Arte ASCII antisolapamiento

33

Fondo

El arte ASCII es la práctica de crear imágenes usando texto ASCII para formar formas.

El alias es el efecto creado por los grandes "píxeles" del arte ASCII, que son del tamaño de los caracteres. La imagen se vuelve bloqueada y difícil de ver. El suavizado elimina este efecto al crear un degradado y al suavizar los bordes duros del arte ASCII.

El reto

Su desafío es escribir el programa más corto posible que tomará una pieza de arte ASCII y generará una versión que haya sido suavizada.

¿Qué tipo de anti-aliasing?

Todo el arte ASCII consistirá en dos tipos de símbolos: espacios y no espacios en blanco. Para cada carácter que no sea un espacio en blanco, su programa debe determinar si está en una posición en la que necesita ser suavizado. Si es así, debe reemplazarlo con el carácter correcto. Si no es así, el personaje permanece igual.

¿Cómo sabes si un personaje necesita ser suavizado? La respuesta depende de los caracteres que están inmediatamente arriba, abajo, a la izquierda y a la derecha del personaje ( no las diagonales ). Aquí hay una tabla de cuándo se requiere anti-aliasing, donde? y xpuede representar cualquier carácter que no sea un espacio en blanco.

 x? ->  d?
 ?      ? 


?x  -> ?b 
 ?      ? 

 ?      ? 
?x  -> ?F 


 ?      ? 
 x? ->  Y?



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

 ?      ? 
 x  ->  V 



?x  -> ?> 



 x? ->  <?



 x  ->  @ 

Entrada (y ejemplo de arte ASCII pre-anti-aliasing)

Primero, habrá dos líneas de entrada (a STDIN), un número H seguido de un número W. Luego habrá líneas H de exactamente W caracteres cada una (excluyendo la nueva línea). Estas siguientes líneas serán el arte ASCII que necesita ser suavizado. Aquí hay un ejemplo de entrada (no hermoso, pero una prueba):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

Salida (y ejemplo de arte anti-alias)

Su programa debe enviar a STDOUT el arte ASCII (de las mismas dimensiones), que ha sido suavizado. Aquí está la salida para la entrada anterior. Observe cómo los caracteres de borde se tratan como espacios en blanco que bordean.

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

Esto podría no verse tan bien (debido al espacio entre líneas en el bloque de código), se ve mejor con un arte ASCII más grande, y la calidad depende de la fuente exacta utilizada.

Otro ejemplo

Entrada

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

Salida

   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

Reglas, restricciones y notas

Su programa debe escribirse solo en caracteres ASCII imprimibles, para que podamos hacer arte de los programas. Aparte de eso, se aplican las reglas estándar de código de golf.

PhiNotPi
fuente
Como todavía no hay respuestas, he cambiado un personaje en la tabla de suavizado. _se ha convertido ;porque funciona mejor.
PhiNotPi
Esta podría ser mi pregunta de código de golf favorita de todos los tiempos. Trabajando en como 4 soluciones increíbles diferentes.
captncraig
Aunque estoy confundido. Dices que las diagonales no cuentan, pero todos tus diagramas muestran signos de interrogación que completan las diagonales. Por lo que veo en los ejemplos, puede ser seguro solo mirar hacia los lados, pero me confundo. ¿Importan alguna vez las diagonales?
captncraig
No, las diagonales nunca importan. Probablemente será más claro si elimino las diagonales de la tabla.
PhiNotPi
Creo que puede haber un error tipográfico en tu ejemplo; Creo que la columna de la derecha debería tener Ys en el borde interior. Sin embargo, disfruté con la respuesta a esta, buena pregunta: D
Ed James

Respuestas:

8

Ruby, 180 168 caracteres

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]}

Otra implementación de Ruby que toma un enfoque zip. Puede ver el segundo ejemplo ejecutándose en línea .

Editar: El uso readlinesguarda 12 caracteres.

Howard
fuente
6

Rubí 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

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

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

Cristian Lupascu
fuente
1) Los paréntesis alrededor de la definición del rango no son necesarios. 2) 0..h-1se puede escribir como 0...h. 3) G=[];h.times{G<<gets}se puede escribir como G=readlines, de manera similar a su código C #. 4) Después del paso 3. la variable h se vuelve inútil, los valores de h y w se usan solo una vez, por lo que h=gets.to_i;w=gets.to_i;H=(0..h-1);W=(0..w-1)se pueden escribir como H=0...gets.to_i;W=0...gets.to_i. 5) En este caso andse puede escribir como &&, que no necesita los espacios alrededor. 6) Tienes un extra; y contó la nueva línea al final del archivo, que no es necesaria. Esto significa 214 caracteres: ideone.com/CiW0l
manatwork
¡Wow gracias! Yo sabía que había mejoras por hacer, pero nunca había pensado que muchos. Lo intenté H=0..gets.to_icuando escribí el código, pero no pareció funcionar (obviamente debe haber sido por otras razones).
Cristian Lupascu
1
Todavía hay dos puntos en los que puede reducir al menos 7 caracteres: 1) Puede usar en maplugar de each2) en z=->...lugar de def z...end.
Howard
@Howard Gracias, he aplicado el mapcambio en lugar de each. Sin embargo, para la sintaxis lambda, creo que eso requeriría que los usos de zsean de la forma en z.call(args)lugar de z(args), agregando así un poco al recuento de caracteres. Por favor, avíseme si me falta algo.
Cristian Lupascu
@Howard Nevermind, acabo de descubrir lo que me faltaba. Actualizaré para usar el []uso de lambda .
Cristian Lupascu
4

Javascript, 410 caracteres:

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;}

sin golf:

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 caracteres:

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;}

Nota: he asumido que las dos primeras líneas de entrada son realmente irrelevantes y el tamaño de las siguientes líneas es correcto. ¡También creo que podría cortar algunos caracteres más cuando tenga la oportunidad!

Ed James
fuente
1
Sustituir a la declaración de ma m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}subíndice A continuación, convertir de M con parseInt(): m[parseInt(y[d](''),2)]. Esto reduce el tamaño a 373 caracteres.
manatwork
3

Python, 259 caracteres

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])

El programa lee la entrada en una sola cadena I(con espacios que separan las líneas), comprime una lista de 5 tuplas que contienen el carácter y sus cuatro caracteres circundantes, luego busca el carácter resultante usando la indexación de cadena.

Keith Randall
fuente
3

PHP - 359 330 282 268 257 caracteres

<?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];}
Fausak oxidado
fuente
@PhiNotPi No funcionaba porque mis archivos de prueba guardados localmente tenían EOL de estilo Windows \r\n. Actualicé mi código para trabajar con EOL de estilo Unix \n.
Rusty Fausak
Ok, parece estar funcionando ahora.
PhiNotPi
2

Pitón, 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 y prueba en la muestra 2, diferencie con la salida de la solución Ruby en la parte superior:

t:~$ wc trans.py && python trans.py < lala2 > o && diff -q o ruby_out2_sample
  2 11 241 trans.py
t:~$
edwkar
fuente
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
fuente