抗锯齿ASCII艺术


33

背景

ASCII艺术是通过使用ASCII文本形成形状来创建图像的实践。

混叠是由ASCII艺术的大“像素”(即字符大小)产生的效果。图像变得块状且难以看清。抗锯齿功能通过创建渐变并软化ASCII艺术作品的硬边来消除这种影响。

挑战

您面临的挑战是编写尽可能最短的程序,该程序将花费一部分ASCII文字并输出经过抗锯齿的版本。

什么样的抗锯齿?

所有ASCII文字都将由两种类型的符号组成:空格和非空白。对于每个非空白字符,您的程序必须确定它是否处于需要消除锯齿的位置。如果是这样,则需要用正确的字符替换它。如果不是,则字符保持不变。

您如何知道角色是否需要消除锯齿?答案取决于字符上方,下方,左侧和右侧的字符(而不是对角线)。下面是当需要抗混叠的一个图表,其中?x可以代表任何非空白字符。

 x? ->  d?
 ?      ? 


?x  -> ?b 
 ?      ? 

 ?      ? 
?x  -> ?F 


 ?      ? 
 x? ->  Y?



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

 ?      ? 
 x  ->  V 



?x  -> ?> 



 x? ->  <?



 x  ->  @ 

输入(以及示例抗锯齿前的ASCII艺术)

首先,会有两行输入(到STDIN),数字H之后是数字W。然后将有H行,每行正好是W个字符(不包括换行符)。以下几行将是需要反走样的ASCII艺术。这是一个示例输入(不是很漂亮,而是一个测试):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

输出(以及消除锯齿的示例)

您的程序应将经过抗锯齿处理的ASCII图形(相同尺寸)输出到STDOUT。这是上述输入的输出。注意如何将边框字符视为边框空白。

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

这可能看起来不太好(由于代码块中各行之间的间隔),使用较大的ASCII艺术效果看起来更好,并且质量取决于所使用的确切字体。

另一个例子

输入项

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

输出量

   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

规则,限制和注释

您的程序仅应使用可打印的ASCII字符编写,以便我们可以利用程序制作美术作品。除此之外,还适用标准代码高尔夫球规则。


由于没有答案,因此我在抗锯齿图中更改了一个字符。_已经成为;因为它更好地工作。
PhiNotPi 2012年

这可能是我一直以来最喜欢的高尔夫代码问题。致力于4种不同的出色解决方案。
captncraig 2012年

虽然我很困惑。您说对角线不计算在内,但是您的所有图表都在对角线上填充了问号。从我在示例中看到的来看,只看侧面可能是安全的,但是我感到困惑吗?对角线有关系吗?
captncraig 2012年

不,对角线没关系。如果我从图表中删除对角线,可能会更加清楚。
PhiNotPi 2012年

我认为您的示例中可能有错别字;我认为右侧列的内侧边缘应为Y。很高兴提出这个问题的答案,但是很好的问题:D
Ed James

Answers:


8

红宝石,180点 168的字符

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

另一个采用zip方法的Ruby实现。您可以看到第二个示例在线运行

编辑:使用readlines保存12个字符。


6

红宝石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

范例1:http//ideone.com/PfNMA

范例2:http//ideone.com/sWijD


1)不需要在范围定义周围加上括号。2)0..h-1可以写成0...h。3)G=[];h.times{G<<gets}可以编写为G=readlines,类似于您的C#代码。4)步骤3之后,变量h变得无用,h和w的值仅使用一次,因此h=gets.to_i;w=gets.to_i;H=(0..h-1);W=(0..w-1)可以写成H=0...gets.to_i;W=0...gets.to_i。5)在这种情况下and可以写成&&,不需要周围的空格。6)你有一个额外的;并且您在文件末尾计算了换行符,这不是必需的。这意味着214个字符:ideone.com/CiW0l
manatwork 2012年

哇谢谢!我知道有待改进,但从未想到有那么多。我在H=0..gets.to_i编写代码时曾尝试过,但似乎没有用(显然,它可能是出于其他原因)。
Cristian Lupascu 2012年

1
还有两点可以减少至少7个字符:1)您可以使用map代替each2)z=->...代替def z...end
霍华德

@Howard谢谢,我已应用map而不是each更改。但是,对于lambda语法,我认为这将要求使用z形式为z.call(args)而不是z(args),从而在字符数上增加了一点。如果我缺少什么,请告诉我。
Cristian Lupascu 2012年

@Howard Nevermind,我才发现自己所缺少的东西。我将更新为使用lambda []用法。
Cristian Lupascu 2012年

4

Javascript,410个字符:

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

松散:

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

原版的, 440个字符

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

注意:我假设前两行输入实际上是无关紧要的,而随后几行的大小是正确的。我还估计,如果有机会,我也许可以砍掉更多的字符!


1
替换m的声明,m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}然后将m的下标转换为parseInt()m[parseInt(y[d](''),2)]。这样可以将大小减少到373个字符。
manatwork 2012年

3

Python,259个字符

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

该程序将输入读取为单个字符串I(用空格分隔各行),压缩包含该字符及其四个周围字符的5元组列表,然后使用字符串索引查找结果字符。


3

PHP - 359 330 282 268 257个字符

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

@PhiNotPi它不起作用,因为我本地保存的测试文件具有Windows风格的EOL \r\n。我更新了代码以与Unix风格的EOL一起使用\n
Rusty Fausak

好的,它现在似乎正在工作。
PhiNotPi 2012年

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并在示例2上进行测试,与顶部的Ruby解决方案的输出有所不同:

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

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)));}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.