Kenar yumuşatma ASCII sanatı


33

Arka fon

ASCII sanatı, şekiller oluşturmak için ASCII metnini kullanarak görüntü oluşturma pratiğidir.

Aliasing, ASCII resminin karakter büyüklüğü olan büyük "pikselleri" tarafından oluşturulan efekttir. Görüntü tıkalı ve görülmesi zorlaşıyor. Kenar yumuşatma, bu efekti bir degrade oluşturarak ve ASCII sanatının sert kenarlarını yumuşatarak giderir.

Meydan okuma

Buradaki zorluk, bir ASCII sanatının parçası olacak ve anti-alias olan bir versiyonun çıktısını alabilecek en kısa programı yazmak.

Ne tür bir anti-aliasing?

ASCII sanatının tamamı iki tür sembolden oluşacaktır: Boşluklar ve boşluk olmayanlar. Her boşluk olmayan karakter için, programınızın kenar yumuşatması gereken bir konumda olup olmadığını belirlemesi gerekir. Öyleyse, doğru karakterle değiştirmeniz gerekir. Değilse, karakter aynı kalır.

Bir karakterin kenar yumuşatılması gerekip gerekmediğini nasıl anlarsınız? Cevap, karakterin hemen üstünde, altında, solunda ve sağında bulunan karakterlere ( köşegenlere değil ) bağlıdır. Anti-aliasing'in ne zaman yapılmasının gerektiği, beyaz olmayan herhangi bir karakterin nerede ?ve ne xzaman durabileceğini gösteren bir grafik .

 x? ->  d?
 ?      ? 


?x  -> ?b 
 ?      ? 

 ?      ? 
?x  -> ?F 


 ?      ? 
 x? ->  Y?



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

 ?      ? 
 x  ->  V 



?x  -> ?> 



 x? ->  <?



 x  ->  @ 

Girdi (ve örneğin kenar yumuşatma öncesi ASCII resmi)

İlk önce iki giriş satırı (STDIN'a), ardından H ve W sayısı olacak. Her biri tam olarak W karakterli H satırları olacak (yeni satır hariç). Aşağıdaki satırlar, kenar yumuşatma uygulaması gereken ASCII sanatı olacaktır. İşte bir örnek giriş (güzel değil, bir test):

7
9
  888888 
 888888  
999 98  7
 666666  
  666666 
   6666  
    6    

Çıktı (ve diğer kenar yumuşatma sanatı)

Programınız, kenar yumuşatma uygulanmış ASCII sanatını (aynı boyutlarda) STDOUT'a çıkarmalıdır. Yukarıdaki giriş için çıktı. Kenarlık karakterlerinin kenarlık boşluğu olarak nasıl değerlendirildiğine dikkat edin.

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

Bu iyi görünmeyebilir (kod bloğundaki satırlar arasındaki boşluk nedeniyle), daha büyük ASCII resminde daha iyi görünür ve kalite kullanılan yazı tipine bağlıdır.

Başka bir örnek

Giriş

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

Çıktı

   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

Kurallar, Kısıtlamalar ve Notlar

Programınız yalnızca programların dışına çıkarılabilmesi için yalnızca yazdırılabilir ASCII karakterleriyle yazılmalıdır. Bunun dışında standart kod-golf kuralları geçerlidir.


Henüz bir cevap olmadığından, kenar yumuşatma tablosunda bir karakter değiştirdim. _haline gelmiştir ;daha iyi çalıştığı için.
PhiNotPi

Bu, tüm zamanların en sevdiğim kod golf sorusu olabilir. Gibi 4 farklı harika çözümler üzerinde çalışıyor.
captncraig

Yine de kafam karıştı. Köşegenlerin sayılmadığını söylüyorsunuz, fakat şemalarınız köşegenleri dolduran soru işaretleri gösteriyor. Örneklerde gördüğüm kadarıyla, sadece taraflara bakmak güvenli olabilir, fakat kafam karışıyor mu? Köşegenler hiç önemli mi?
captncraig

Hayır, köşegenler asla önemli değil. Diyagonalleri grafikten çıkardıysam muhtemelen daha net olacak.
PhiNotPi

Örnekte bir yazım hatası olabileceğini düşünüyorum; Sağ sütunun iç kenarında Ys olması gerektiğine inanıyorum. Buna cevabını bulmaktan memnun oldum, güzel bir soru: D
Ed James

Yanıtlar:


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

Zip yaklaşımı gerektiren bir başka Ruby uygulaması. Çevrimiçi çalışan ikinci örneği görebilirsiniz .

Düzenleme: Kullanarak readlines12 karakter kaydeder.


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

Örnek 1: http://ideone.com/PfNMA

Örnek 2: http://ideone.com/sWijD


1) Aralık tanımı etrafındaki parantez gerekli değildir. 2) 0..h-1olarak yazılabilir 0...h. 3) C # kodunuzdaki gibi G=[];h.times{G<<gets}yazılabilir G=readlines. 4) 3. adımdan sonra, h değişkeni işe yaramaz hale gelir, h ve w değerleri yalnızca bir kez kullanılır, böylece h=gets.to_i;w=gets.to_i;H=(0..h-1);W=(0..w-1)yazılabilir H=0...gets.to_i;W=0...gets.to_i. 5) Bu durumda etrafındaki boşluklara ihtiyaç andduyulmayan olarak yazılabilir &&. 6) Fazladan var; ve dosya sonunda, gerekli olmayan newline değerini saydınız. Bu 214 karakter demek oluyor: ideone.com/CiW0l
manatwork

Vay, teşekkürler! Yapılması gereken iyileştirmeler olduğunu biliyordum, ancak bu kadar fazla olduğunu hiç düşünmemiştim . H=0..gets.to_iKodu yazarken denemiştim , ancak işe yaramadı (açıkçası diğer nedenlerle olmalıydı ).
Cristian Lupascu

1
En az 7 karakter tarafından azaltabilir Hâlâ iki puan: 1) kullanabilirsiniz mapyerine each2) z=->...yerine def z...end.
Howard,

@Howard Teşekkürler, değişiklik mapyerine başvurdum each. Bununla birlikte, lambda sözdizimi için bunun kullanım zşekillerinin z.call(args)yerine kullanılmasını gerektireceğini ve z(args)böylece karakter sayımına biraz eklenmesi gerektiğini düşünüyorum. Bir şey kaçırırsam lütfen bana bildirin.
Cristian Lupascu

@Howard Nevermind, ne kaçırdığımı yeni öğrendim. Lambda []kullanımını kullanmak için güncelleme yapacağım .
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;
}

Orijinal, 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 İlk iki giriş satırının aslında alakasız olduğunu ve aşağıdaki satırların boyutunun doğru olduğunu varsaydım. Ayrıca bir şans yakaladığımda bundan bir kaç karakter daha doğrayabileceğimi de düşünüyorum!


1
İçin m beyanı değiştirin m={22:"b",28:"d",13:"Y",7:"F",20:";",5:"V",6:">",12:"<",4:"@"}ile ardından dönüştürmek m 'subscript parseInt(): m[parseInt(y[d](''),2)]. Bu, boyutu 373 karaktere düşürür.
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, girişi tek bir dizgiye okur I(boşlukları ayıran boşluklarla), karakteri ve çevresindeki dört karakteri içeren 5-tuplerin bir listesini çıkarır, daha sonra dizginin indekslenmesini kullanarak sonuç karakterini arar.


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

@PhiNotPi Yerel olarak kaydedilen test dosyalarımda Windows tarzı EOL olduğundan çalışma değildi \r\n. Kodumu unix stili EOL ile çalışacak şekilde güncelledim \n.
Rusty Fausak

Tamam, şimdi çalışıyor gibi görünüyor.
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 ve örnek 2'deki test, üstteki Ruby çözümünün çıktısına göre farklılık gösterdi:

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)));}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.