Сглаживание ASCII art

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

Во-первых, будет две строки ввода (в STDIN), число H, за которым следует число W. Затем будет H строк ровно по W символов каждая (исключая символ новой строки). Эти следующие строки будут искусством ASCII, которое должно быть сглажено. Вот пример ввода (не красивый, но тестовый):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

Вывод (и пример сглаженного искусства)

Ваша программа должна выводить в STDOUT искусство ASCII (тех же размеров), которое было сглажено. Вот вывод для вышеуказанного ввода. Обратите внимание, как символы границы обрабатываются как ограничивающие пробелы.

  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
источник
Поскольку ответов пока нет, я изменил один символ в таблице сглаживания. _стало ;потому, что работает лучше.
PhiNotPi
Это может быть моим любимым вопросом о гольф-кодах всех времен. Работаю над 4 разными потрясающими решениями.
captncraig
Хотя я в замешательстве. Вы говорите, что диагонали не учитываются, но все ваши диаграммы показывают вопросительные знаки, заполняющие диагонали. Из того, что я вижу в примерах, может быть безопасно смотреть только в стороны, но я запутался? Имеют ли значение диагонали?
captncraig
Нет, диагонали никогда не имеют значения. Вероятно, будет более понятно, если я уберу диагонали с графика.
PhiNotPi
Я думаю, что в вашем примере может быть опечатка; Я считаю, что правый столбец должен иметь Y на внутреннем крае. Приятно было придумать ответ на этот вопрос, хороший вопрос: D
Эд Джеймс

Ответы:

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

Еще одна реализация Ruby, которая использует zip-подход. Вы можете увидеть второй пример, работающий онлайн .

Редактировать: Использование 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
Вау, спасибо! Я знал, что нужно сделать улучшения, но никогда не думал, что их так много. Я пытался, H=0..gets.to_iкогда писал код, но, похоже, он не работал (очевидно, это было по другим причинам).
Кристиан Лупаску
1
Еще две точки, где вы можете уменьшить как минимум на 7 символов: 1) Вы можете использовать mapвместо each2) z=->...вместо def z...end.
Говард
@ Говард Спасибо, я применил mapвместо eachизменений. Однако для лямбда-синтаксиса, я думаю, это потребовало бы, чтобы использование zбыло в форме, z.call(args)а не z(args), таким образом, добавляя немного к числу символов. Пожалуйста, дайте мне знать, если я что-то упустил.
Кристиан Лупаску,
@ Howard Nevermind, я только что узнал, чего мне не хватало. Я обновлю, чтобы использовать использование лямбды [].
Кристиан Лупаску
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;}

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

Оригинал, 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;}

NB Я предположил, что первые две входные строки на самом деле не имеют значения, а размер следующих строк правильный. Я также рассчитываю, что смогу отрубить еще несколько символов, когда у меня будет шанс!

Эд Джеймс
источник
1
Заменить декларацию м до m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}подстрочный затем преобразуйте м с parseInt(): m[parseInt(y[d](''),2)]. Это уменьшает размер до 373 символов.
manatwork
3

Питон, 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 Это не работало, потому что мои локально сохраненные тестовые файлы имели EOL в стиле Windows \r\n. Я обновил свой код для работы с EOL в стиле Unix \n.
Расти Фаусак
Хорошо, похоже, сейчас работает.
PhiNotPi
2

Питон, 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:~$
edwkar
источник
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)));}
Кристиан Лупаску
источник