Anti-Aliasing ASCII art

33

Hintergrund

ASCII-Kunst ist das Erstellen von Bildern mithilfe von ASCII-Text, um Formen zu bilden.

Aliasing ist der Effekt, der durch die großen "Pixel" der ASCII-Grafik erzeugt wird, die der Größe der Zeichen entsprechen. Das Bild wird blockig und schwer zu sehen. Anti-Aliasing entfernt diesen Effekt, indem ein Farbverlauf erstellt und die harten Kanten der ASCII-Grafik geglättet werden.

Die Herausforderung

Ihre Herausforderung besteht darin, das kürzestmögliche Programm zu schreiben, das ein Stück ASCII-Kunst aufnimmt und eine Version ausgibt, die geglättet wurde.

Welche Art von Anti-Aliasing?

Alle ASCII-Zeichen bestehen aus zwei Arten von Symbolen: Leerzeichen und Nicht-Leerzeichen. Für jedes Nicht-Whitespace-Zeichen muss Ihr Programm ermitteln, ob es sich an einer Position befindet, an der ein Anti-Aliasing erforderlich ist. Wenn dies der Fall ist, müssen Sie es durch das richtige Zeichen ersetzen. Ist dies nicht der Fall, bleibt der Charakter derselbe.

Woher weißt du, ob ein Charakter geglättet werden muss? Die Antwort hängt von den Zeichen ab, die unmittelbar über, unter, links und rechts vom Zeichen stehen ( nicht von den Diagonalen ). Hier ist ein Diagramm , wenn Anti-Aliasing erforderlich ist, wo ?und xfür jede Nicht-Leerzeichen stehen kann.

 x? ->  d?
 ?      ? 


?x  -> ?b 
 ?      ? 

 ?      ? 
?x  -> ?F 


 ?      ? 
 x? ->  Y?



 x  ->  ;   Note: This character has been changed from _ to ;
 ?      ? 

 ?      ? 
 x  ->  V 



?x  -> ?> 



 x? ->  <?



 x  ->  @ 

Eingabe (und Beispiel für eine Pre-Anti-Aliasing-ASCII-Grafik)

Zuerst gibt es zwei Eingabezeilen (für STDIN), eine Zahl H, gefolgt von einer Zahl W. Dann gibt es H Zeilen mit jeweils genau W Zeichen (ohne die neue Zeile). Diese folgenden Zeilen sind ASCII-Zeichen, die geglättet werden müssen. Hier ist eine Beispieleingabe (nicht schön, aber ein Test):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

Ausgabe (und Beispiel Anti-Alias-Art)

Ihr Programm sollte die ASCII-Grafik (mit den gleichen Abmessungen), die mit Anti-Alias ​​versehen wurde, an STDOUT ausgeben. Hier ist der Ausgang für den obigen Eingang. Beachten Sie, wie die Umrandungszeichen als angrenzende Leerzeichen behandelt werden.

  d8888> 
 d8888F  
<99 98  @
 Y6666b  
  Y6666> 
   Y66F  
    V    

Dies sieht möglicherweise nicht so gut aus (aufgrund des Abstands zwischen den Zeilen im Codeblock), bei größeren ASCII-Grafiken sieht es besser aus, und die Qualität hängt von der genauen verwendeten Schriftart ab.

Ein anderes Beispiel

Eingang

12
18
   xx  xxx  xxx   
  xxxx  xxx  xxx  
 xxxxxx  xxx  xxx 
xxx  xxx  xxx  xxx
xxxx xxx  xxx  xxx
 xxxxxx  xxx  xxx 
  xxxx  xxx  xxx  
x  xx  xxx  xxx  x
xx    xxx  xxx  xx
xxx  xxx  xxx  xxx
xxxx  xxx  xxx  xx
xxxxx  xxx  xxx  x

Ausgabe

   db  <xb  <xb   
  dxxb  Yxb  Yxb  
 dxxxxb  Yxb  Yxb 
dxx  xxb  xxb  xxb
Yxxb xxF  xxF  xxF
 YxxxxF  dxF  dxF 
  YxxF  dxF  dxF  
;  YF  dxF  dxF  ;
xb    dxF  dxF  dx
xxb  <xF  <xF  <xx
xxxb  Yxb  Yxb  Yx
Yxxx>  Yx>  Yx>  V

Regeln, Einschränkungen und Hinweise

Ihr Programm sollte nur in druckbaren ASCII-Zeichen geschrieben sein, damit wir Kunst aus den Programmen machen können. Ansonsten gelten die Standard-Code-Golf-Regeln.

PhiNotPi
quelle
Da es noch keine Antworten gibt, habe ich ein Zeichen in der Anti-Aliasing-Tabelle geändert. _ist geworden, ;weil es besser funktioniert.
PhiNotPi
Dies könnte meine Lieblings-Code Golf Frage aller Zeiten sein. Arbeite an 4 verschiedenen tollen Lösungen.
Captncraig
Obwohl ich verwirrt bin. Sie sagen, Diagonalen zählen nicht, aber Ihre Diagramme enthalten Fragezeichen, die die Diagonalen ausfüllen. Nach dem, was ich in den Beispielen sehe, kann es sicher sein, nur zur Seite zu schauen, aber ich werde verwirrt? Sind Diagonalen jemals wichtig?
Captncraig
Nein, die Diagonalen spielen keine Rolle. Es wird wahrscheinlich klarer, wenn ich die Diagonalen aus dem Diagramm entferne.
PhiNotPi
Ich denke, es könnte ein Tippfehler in Ihrem Beispiel sein; Ich glaube, die rechte Spalte sollte Ys an der Innenkante haben. Genossen es, die Antwort auf diese Frage zu finden, gute Frage: D
Ed James

Antworten:

8

Ruby, 180 168 Zeichen

gets
w=1+gets.to_i
f=*(readlines*"").chars
f.zip(f[1..-1]+s=[" "],s+f,s*w+f,f[w..-1]+s*w){|a,*b|$><<"@;V#{a}>bF#{a}<dY#{a*5}"[a>" "?(b.map{|y|y>" "?1:0}*"").to_i(2):3]}

Eine weitere Ruby-Implementierung, die einen Zip-Ansatz verfolgt. Sie können das zweite Beispiel online sehen .

Bearbeiten: Mit werden readlines12 Zeichen gespeichert.

Howard
quelle
6

Ruby 275 265 263 261 258 254 244 243 214 212 207

H=0...gets.to_i
W=0...gets.to_i
G=readlines
z=->x,y{(H===y&&W===x&&' '!=G[y][x])?1:0}
H.map{|j|W.map{|i|l=G[j][i]
G[j][i]="@V;#{l}>Fb#{l}<Yd#{l*5}"[z[i+1,j]*8+z[i-1,j]*4+z[i,j+1]*2+z[i,j-1]]if' '!=l}}
puts G

Beispiel 1: http://ideone.com/PfNMA

Beispiel 2: http://ideone.com/sWijD

Cristian Lupascu
quelle
1) Klammern um die Bereichsdefinition sind nicht erforderlich. 2) 0..h-1kann geschrieben werden als 0...h. 3) G=[];h.times{G<<gets}kann so geschrieben werden G=readlines, ähnlich wie in Ihrem C # -Code. 4) Nach Schritt 3 wird die Variable h unbrauchbar, die Werte von h und w werden nur einmal verwendet und h=gets.to_i;w=gets.to_i;H=(0..h-1);W=(0..w-1)können als geschrieben werden H=0...gets.to_i;W=0...gets.to_i. 5) In diesem Fall andkann als geschrieben werden &&, was die Leerzeichen nicht benötigt. 6) Sie haben eine extra; und Sie haben die Zeilenumbrüche am Ende der Datei gezählt, die nicht erforderlich sind. Dies bedeutet 214 Zeichen: ideone.com/CiW0l
manatwork
Wow, danke! Ich wusste, dass Verbesserungen vorgenommen werden mussten, hätte aber nie gedacht, dass es so viele gibt. Ich hatte versucht, H=0..gets.to_ials ich den Code schrieb, aber es schien nicht zu funktionieren (offensichtlich muss es aus anderen Gründen gewesen sein).
Cristian Lupascu
1
Noch zwei Punkte, bei denen Sie um mindestens 7 Zeichen reduzieren können: 1) Sie können mapanstelle von each2) z=->...anstelle von verwenden def z...end.
Howard
@Howard Danke, ich habe die mapanstelle der eachÄnderung übernommen. Für die Lambda - Syntax, aber ich denke , dass die Nutzungen erfordern würde , zvon der Form zu sein , z.call(args)statt z(args), so dass ein Bit auf die Zeichenzahl hinzufügen. Bitte lassen Sie mich wissen, wenn ich etwas vermisse.
Cristian Lupascu
@ Howard Nevermind, ich habe gerade herausgefunden, was mir gefehlt hat. Ich aktualisiere, um die Lambda- []Verwendung zu verwenden.
Cristian Lupascu
4

Javascript, 410 Zeichen:

function(t){m={"10110":"b","11100":"d","01101":"Y","00111":"F","10100":";","00101":"V","00110":">","01100":"<","00100":"@"},d="join",l="length",t=t.split('\n').splice(2),t=t.map(function(x)x.split('')),f=function(i,j)t[i]?(t[i][j]||' ')==' '?0:1:0;for(o=t[l];o--;){for(p=t[o][l];p--;){y=[f(o+1,p),f(o,p+1),f(o,p),f(o,p-1),f(o-1,p)],t[o][p]=m[y[d]('')]||t[o][p]}}t=t.map(function(x)x[d](''))[d]('\n');return t;}

ungolfed:

function(t){
    m={
        "10110":"b",
        "11100":"d",
        "01101":"Y",
        "00111":"F",
        "10100":";",
        "00101":"V",
        "00110":">",
        "01100":"<",
        "00100":"@"
    },
    d="join",
    l="length",
    t=t.split('\n').splice(2),
    t=t.map(function(x) x.split('')),
    f=function(i,j) t[i]?(t[i][j]||' ')==' '?0:1:0;

    for(o=t[l];o--;){
        for(p=t[o][l];p--;){
            y=[f(o+1,p),f(o,p+1),f(o,p),f(o,p-1),f(o-1,p)],

            t[o][p]=m[y[d]('')]||t[o][p]
        }
    }
    t=t.map(function(x)x[d](''))[d]('\n');
    return t;
}

Original, 440 Zeichen:

function (t){m={"10110":"b","11100":"d","01101":"Y","00111":"F","10100":";","00101":"V","00110":">","01100":"<","00100":"@"},s="split",d="join",l="length",t=t[s]('\n').splice(2),t=t.map(function(x) x[s]('')),f=function(i,j)i<0||i>=t[l]?0:(j<0||j>=t[i][l]?0:t[i][j]==' '?0:1);for(o=t[l];o--;){for(p=t[o][l];p--;){y=[f(o+1,p),f(o,p+1),f(o,p),f(o,p-1),f(o-1,p)],h=m[y[d]('')];if(h){t[o][p]=h}}}t=t.map(function(x) x[d](''))[d]('\n');return t;}

NB Ich habe angenommen, dass die ersten beiden Eingabezeilen tatsächlich irrelevant sind und die Größe der folgenden Zeilen korrekt ist. Ich rechne auch damit, dass ich vielleicht noch ein paar Zeichen abschneiden kann, wenn ich die Chance bekomme!

Ed James
quelle
1
Ersetzen Sie die Erklärung von m bis m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}dann der Index des convert m mit parseInt(): m[parseInt(y[d](''),2)]. Dies reduziert die Größe auf 373 Zeichen.
Manatwork
3

Python, 259 Zeichen

H=input()
W=input()+1
I=' '.join(raw_input()for i in' '*H)
for i in range(H):print''.join(map(lambda(s,a,b,c,d):(s*5+'dY<'+s+'bF>'+s+';V@'+' '*16)[16*(s==' ')+8*(a==' ')+4*(b==' ')+2*(c==' ')+(d==' ')],zip(I,I[1:]+' ',' '+I,I[W:]+' '*W,' '*W+I))[i*W:i*W+W-1])

Das Programm liest die Eingabe in eine einzelne Zeichenfolge I(mit Leerzeichen zwischen den Zeilen), komprimiert eine Liste mit 5 Tupeln, die das Zeichen und seine vier umgebenden Zeichen enthalten, und sucht dann das Ergebniszeichen mithilfe der Zeichenfolgenindizierung.

Keith Randall
quelle
3

PHP - 359 330 282 268 257 Zeichen

<?php
$i=fgets(STDIN)+0;$w=fgets(STDIN)+1;$s='';$m='@<;d>0b0VY00F000';
for(;$i--;)$s.=fgets(STDIN);
for(;++$i<strlen($s);){
$b=trim($s[$i])?0:15;
foreach(array($i+1,$i+$w,$i-1,$i-$w)as$k=>$x)
$b|=pow(2,$k)*(isset($s[$x])&&trim($s[$x]));
echo $m[$b]?$m[$b]:$s[$i];}
Rusty Fausak
quelle
@PhiNotPi Es hat nicht funktioniert, weil meine lokal gespeicherten Testdateien Windows-EOL hatten \r\n. Ich habe meinen Code aktualisiert, um mit EOL im Unix-Stil zu arbeiten \n.
Rusty Fausak
Ok, es scheint jetzt zu funktionieren.
PhiNotPi
2

Python, 246 241

H=input();W=1+input()
S=' '
o=W*S
F=o+'\n'.join((raw_input()+o)[:W-1]for k in range(H))+o
print ''.join((16*x+'@;<d>b'+2*x+'V'+x+'Y'+x+'F'+3*x)[
16*(x>S)|8*(a>S)|4*(l>S)|2*(r>S)|(b>S)]for
x,a,l,r,b in zip(F[W:-W],F,F[W-1:],F[W+1:],F[2*W:]))

WC und Test an Probe 2, mit der Ausgabe der Ruby-Lösung oben:

t:~$ wc trans.py && python trans.py < lala2 > o && diff -q o ruby_out2_sample
  2 11 241 trans.py
t:~$
edwkar
quelle
1

C # 591 563

string A(string t){var s=new StringReader(t);var h=int.Parse(s.ReadLine());var w=int.Parse(s.ReadLine());var lines=s.ReadToEnd().Split(new[]{"\r\n"},StringSplitOptions.None).Select(x=>x.ToCharArray()).ToArray();for(var i=0;i<h;i++)for(var j=0;j<w;j++){var c=lines[i][j];if(c==' ')continue;var n=(i>0?(lines[i-1][j]!=' '?1:0):0)+(i<h-1?(lines[i+1][j]!=' '?2:0):0)+(j>0?(lines[i][j-1]!=' '?4:0):0)+(j<w-1?(lines[i][j+1]!=' '?8:0):0);lines[i][j]=new[]{'@','V',';',c,'>','F','b',c,'<','Y','d',c,c,c,c,c}[n];}return string.Join("\r\n",lines.Select(l=>new string(l)));}
Cristian Lupascu
quelle