Anti-aliasing art ASCII

33

Contexte

L'art ASCII est la pratique de créer des images en utilisant du texte ASCII pour former des formes.

L'aliasing est l'effet créé par les grands "pixels" de l'art ASCII, qui correspondent à la taille des caractères. L'image devient bouchée et difficile à voir. L'anti-aliasing supprime cet effet en créant un dégradé et en adoucissant les contours de l'art ASCII.

Le défi

Votre défi est d’écrire le programme le plus court possible qui prendra un morceau d’art ASCII et produira une version anti-aliasée.

Quelle sorte d'anti-aliasing?

Tout l'art ASCII se composera de deux types de symboles: Espaces et non-blancs. Pour chaque caractère non-blanc, votre programme doit déterminer s'il est dans une position où il doit être anti-aliasé. Si c'est le cas, vous devez le remplacer par le caractère correct. Si ce n'est pas le cas, le personnage reste le même.

Comment savoir si un personnage doit être anti-aliasé? La réponse dépend des caractères qui se trouvent immédiatement au-dessus, en dessous, à gauche et à droite du caractère ( pas les diagonales ). Voici un tableau indiquant les cas où l’anti-aliasing est requis, où ?et xpeut signifier tout caractère non-blanc.

 x? ->  d?
 ?      ? 


?x  -> ?b 
 ?      ? 

 ?      ? 
?x  -> ?F 


 ?      ? 
 x? ->  Y?



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

 ?      ? 
 x  ->  V 



?x  -> ?> 



 x? ->  <?



 x  ->  @ 

Entrée (et exemple d'art ASCII pré-anti-aliasing)

Tout d'abord, il y aura deux lignes d'entrée (à STDIN), un nombre H suivi d'un nombre W. Il y aura ensuite des lignes H de caractères exactement W (à l'exception de la nouvelle ligne). Les lignes suivantes constitueront l’art ASCII qui doit être anti-aliasé. Voici un exemple d'entrée (pas beau, mais un test):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

Sortie (et exemple d'art anti-aliasé)

Votre programme doit sortir vers STDOUT l’art ASCII (de mêmes dimensions), qui a été anti-aliasé. Voici la sortie pour l'entrée ci-dessus. Notez que les caractères de bordure sont traités comme des espaces blancs.

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

Cela peut ne pas sembler très bon (en raison de l'espace entre les lignes du bloc de code), il est plus esthétique avec les illustrations ASCII plus volumineuses et la qualité dépend de la police utilisée.

Un autre exemple

Contribution

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

Sortie

   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

Règles, restrictions et notes

Votre programme doit être écrit en caractères ASCII imprimables uniquement, afin que nous puissions en faire des oeuvres. Autre que cela, les règles standard de code-golf s'appliquent.

PhiNotPi
la source
Comme il n’ya pas encore de réponse, j’ai changé un caractère dans le tableau anti-aliasing. _est devenu ;parce que ça marche mieux.
PhiNotPi
Cela pourrait être ma question de golf de code préféré de tous les temps. Travailler comme 4 solutions géniales différentes.
captncraig
Bien que je sois confus. Vous dites que les diagonales ne comptent pas, mais vos diagrammes présentent tous des points d'interrogation indiquant les diagonales. D'après ce que je vois dans les exemples, il peut être sûr de ne regarder que les côtés, mais je suis confus? Est-ce que les diagonales sont importantes?
captncraig
Non, les diagonales ne comptent jamais. Ce sera probablement plus clair si j'ai enlevé les diagonales du graphique.
PhiNotPi
Je pense qu'il pourrait y avoir une faute de frappe dans votre exemple; Je crois que la colonne de droite devrait avoir des Y sur le bord intérieur. J'ai bien aimé trouver la réponse à cette question, bonne question: D
Ed James

Réponses:

8

Ruby, 180 168 caractères

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

Une autre implémentation de Ruby qui adopte une approche zip. Vous pouvez voir le deuxième exemple en cours d'exécution en ligne .

Edit: Utiliser readlinesenregistre 12 caractères.

Howard
la source
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

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

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

Cristian Lupascu
la source
1) Les parenthèses autour de la définition de la plage ne sont pas nécessaires. 2) 0..h-1peut être écrit comme 0...h. 3) G=[];h.times{G<<gets}peut être écrit de la G=readlinesmême manière que dans votre code C #. 4) Après l'étape 3. la variable h devient inutile, les valeurs de h et w ne sont utilisées qu'une seule fois et h=gets.to_i;w=gets.to_i;H=(0..h-1);W=(0..w-1)peuvent donc être écrites comme H=0...gets.to_i;W=0...gets.to_i. 5) Dans ce cas, vous andpouvez écrire en tant que &&, ce qui ne nécessite pas d'espaces autour. 6) vous avez un extra; et vous avez compté la nouvelle ligne à la fin du fichier, ce qui n'est pas nécessaire. Cela signifie 214 caractères: ideone.com/CiW0l
manatwork
Ouah merci! Je savais qu'il y avait des améliorations à apporter, mais jamais pensé qu'il y avait que beaucoup. J'avais essayé H=0..gets.to_iquand j'avais écrit le code, mais cela ne semblait pas fonctionner (évidemment, cela devait être pour d'autres raisons).
Cristian Lupascu le
1
Reste deux points où vous pouvez réduire d’au moins 7 caractères: 1) Vous pouvez utiliser mapau lieu de each2) z=->...au lieu de def z...end.
Howard
@ Howard Merci, j'ai appliqué le mapau lieu de eachchangement. Pour la syntaxe lambda, cependant, je pense que cela exigerait que les utilisations de zsoient de la forme z.call(args)au lieu de z(args), ajoutant ainsi un bit au nombre de caractères. S'il vous plaît laissez-moi savoir si je manque quelque chose.
Cristian Lupascu
@ Howard Nevermind, je viens de découvrir ce qui me manquait. Je vais mettre à jour pour utiliser l' []utilisation de Lambda .
Cristian Lupascu
4

Javascript, 410 caractères:

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 caractères:

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 J'ai supposé que les deux premières lignes d'entrée étaient en réalité sans importance et que la taille des lignes suivantes était correcte. Je pense aussi que je pourrais peut-être couper quelques caractères de plus quand j'en aurai l'occasion!

Ed James
la source
1
Remplacer la déclaration de m à m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}l'indice de puis le convertir m avec parseInt(): m[parseInt(y[d](''),2)]. Cela réduit la taille à 373 caractères.
manatwork
3

Python, 259 caractères

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

Le programme lit l'entrée dans une chaîne unique I(avec des espaces séparant les lignes), compresse une liste de 5 tuples contenant le caractère et ses quatre caractères environnants, puis recherche le caractère obtenu à l'aide de l'indexation de chaîne.

Keith Randall
la source
3

PHP - 359 330 282 268 257 caractères

<?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];}
Rouillé fausak
la source
@PhiNotPi Cela ne fonctionnait pas car mes fichiers de test sauvegardés localement avaient une fin de vie de type Windows \r\n. J'ai mis à jour mon code pour qu'il fonctionne avec le style unix EOL \n.
Rusty Fausak
Ok, cela semble fonctionner maintenant.
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 et test sur l'échantillon 2, avec la sortie de la solution de Ruby au sommet:

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