Seni ASCII anti-aliasing

33

Latar Belakang

Seni ASCII adalah praktik membuat gambar dengan menggunakan teks ASCII untuk membentuk bentuk.

Aliasing adalah efek yang dibuat oleh "piksel" besar seni ASCII, yang merupakan ukuran karakter. Gambar menjadi gumpal dan sulit dilihat. Anti-aliasing menghilangkan efek ini dengan menciptakan gradien dan dengan melunakkan tepi keras seni ASCII.

Tantangan

Tantangan Anda adalah menulis program sesingkat mungkin yang akan mengambil karya seni ASCII dan akan menampilkan versi yang anti-alias.

Anti-aliasing macam apa?

Semua seni ASCII akan terdiri dari dua jenis simbol: Spasi dan non-spasi putih. Untuk setiap karakter non-spasi putih, program Anda harus menentukan apakah karakter tersebut berada pada posisi di mana ia harus anti-alias. Jika ya, maka Anda harus menggantinya dengan karakter yang benar. Jika tidak, maka karakternya tetap sama.

Bagaimana Anda tahu jika karakter perlu anti-alias? Jawabannya tergantung pada karakter yang tepat di atas, di bawah, kiri, dan kanan karakter ( bukan diagonal ). Berikut adalah bagan kapan anti-aliasing diperlukan, di mana ?dan xbisa berdiri untuk karakter non-spasi putih.

 x? ->  d?
 ?      ? 


?x  -> ?b 
 ?      ? 

 ?      ? 
?x  -> ?F 


 ?      ? 
 x? ->  Y?



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

 ?      ? 
 x  ->  V 



?x  -> ?> 



 x? ->  <?



 x  ->  @ 

Input (dan contoh seni ASCII sebelum anti-aliasing)

Pertama, akan ada dua baris input (ke STDIN), angka H diikuti oleh angka W. Kemudian akan ada baris H masing-masing karakter W (tidak termasuk baris baru). Baris-baris berikut ini akan menjadi seni ASCII yang perlu anti-alias. Berikut adalah contoh input (tidak cantik, tetapi ujian):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

Keluaran (dan contoh seni anti-alias)

Program Anda harus menghasilkan STDOUT the ASCII art (dengan dimensi yang sama), yang anti-alias. Berikut ini adalah output untuk input di atas. Perhatikan bagaimana karakter perbatasan diperlakukan sebagai membatasi spasi.

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

Ini mungkin tidak terlihat bagus (karena jarak antar baris dalam blok kode), terlihat lebih baik dengan seni ASCII yang lebih besar, dan kualitasnya tergantung pada jenis huruf yang digunakan.

Contoh lain

Memasukkan

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

Keluaran

   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

Aturan, Batasan, dan Catatan

Program Anda harus ditulis dalam karakter ASCII yang dapat dicetak saja, sehingga kami dapat membuat karya seni keluar dari program. Selain itu, aturan kode-golf standar berlaku.

PhiNotPi
sumber
Karena belum ada jawaban, saya telah mengubah satu karakter di bagan anti-aliasing. _telah menjadi ;karena berfungsi lebih baik.
PhiNotPi
Ini mungkin pertanyaan golf kode favorit saya sepanjang masa. Bekerja seperti 4 solusi hebat yang berbeda.
captncraig
Meskipun saya bingung. Anda mengatakan diagonal tidak masuk hitungan, tetapi diagram Anda semua menunjukkan tanda tanya yang mengisi diagonal. Dari apa yang saya lihat dalam contoh, mungkin aman untuk hanya melihat ke samping, tetapi saya bingung? Apakah diagonal itu penting?
captncraig
Tidak, diagonal tidak penting. Mungkin akan lebih jelas jika saya menghapus diagonal dari grafik.
PhiNotPi
Saya pikir mungkin ada kesalahan ketik dalam contoh Anda; Saya percaya kolom kanan harus memiliki Ys di tepi dalam. Senang datang dengan jawaban untuk yang satu ini, pertanyaan yang bagus: D
Ed James

Jawaban:

8

Ruby, 180 168 karakter

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

Implementasi Ruby lain yang mengambil pendekatan zip. Anda dapat melihat contoh kedua berjalan online .

Sunting: Menggunakan readlinesmenyimpan 12 karakter.

Howard
sumber
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

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

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

Cristian Lupascu
sumber
1) Parenthesis di sekitar rentang definisi tidak diperlukan. 2) 0..h-1dapat ditulis sebagai 0...h. 3) G=[];h.times{G<<gets}dapat ditulis sebagai G=readlines, sama seperti dalam kode C # Anda. 4) Setelah langkah 3. variabel h menjadi tidak berguna, nilai h dan w hanya digunakan satu kali, sehingga h=gets.to_i;w=gets.to_i;H=(0..h-1);W=(0..w-1)dapat ditulis sebagai H=0...gets.to_i;W=0...gets.to_i. 5) Dalam hal ini anddapat ditulis sebagai &&, yang tidak membutuhkan ruang di sekitar. 6) Anda memiliki tambahan; dan Anda menghitung baris baru di akhir file, yang tidak perlu. Ini berarti 214 chars: ideone.com/CiW0l
manatwork
Wow terima kasih! Saya tahu ada perbaikan yang harus dilakukan, tapi tidak pernah berpikir ada yang banyak. Saya telah mencoba H=0..gets.to_iketika saya menulis kode, tetapi sepertinya tidak berhasil (jelas itu pasti karena alasan lain).
Cristian Lupascu
1
Masih dua poin di mana Anda dapat mengurangi setidaknya 7 karakter: 1) Anda dapat menggunakan mapbukannya each2) z=->...alih-alih def z...end.
Howard
@Howard Terima kasih, saya telah menerapkan mapalih - alih eachperubahan. Untuk sintaks lambda, bagaimanapun, saya pikir itu akan membutuhkan penggunaan zmenjadi bentuk z.call(args)bukan z(args), sehingga menambahkan sedikit ke jumlah karakter. Tolong beri tahu saya jika saya melewatkan sesuatu.
Cristian Lupascu
@Howard Nevermind, saya baru tahu apa yang saya lewatkan. Saya akan memperbarui untuk menggunakan []penggunaan lambda .
Cristian Lupascu
4

Javascript, 410 karakter:

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

Asli, 440 karakter:

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 Saya berasumsi bahwa dua jalur input pertama sebenarnya tidak relevan dan ukuran baris berikut ini benar. Saya juga berpikir saya mungkin bisa memotong beberapa karakter lagi ketika saya mendapat kesempatan!

Ed James
sumber
1
Menggantikan deklarasi m untuk m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}subscript kemudian mengkonversi m dengan parseInt(): m[parseInt(y[d](''),2)]. Ini mengurangi ukuran menjadi 373 karakter.
manatwork
3

Python, 259 karakter

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

Program membaca input menjadi string tunggal I(dengan spasi memisahkan garis-garis), membuka daftar 5-tupel yang berisi karakter dan empat karakter di sekitarnya, lalu mencari karakter hasil menggunakan string indexing.

Keith Randall
sumber
3

PHP - 359 330 282 268 257 karakter

<?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
sumber
@PhiNotPi Tidak berfungsi karena file tes yang disimpan secara lokal saya memiliki EOL gaya windows \r\n. Saya memperbarui kode saya untuk bekerja dengan gaya unix EOL \n.
Rusty Fausak
Ok, sepertinya sudah berfungsi sekarang.
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 dan uji pada sampel 2, berbeda dengan output dari solusi Ruby di atas:

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