Kod-golf ascii sanat kolay yolu!


18

Görev:

Gibi, ASCII art halinde düzenlenir bu sitede cevapların bir yeri vardır bu bir . Genellikle düzenleme elle yapılır, ancak bir program bu konuda yardımcı olmaz mı? :)

Programınız 3 giriş alacak:

  • Tek satırlık kod
  • Desendeki satır sayısı (gerekli değilse atlanabilir)
  • *S veya başka bir karakter olarak desenin kendisi

Kurallar:

  • Stdin'den okunan bir program (işlev değil) yazmanız gerekir
  • Metin satır başına soldan sağa yerleştirilir
  • Deseni dolduracak kadar metin yoksa, .kalan boşluklara s koyun
  • Deseni doldurmak için çok fazla metin varsa, çıktıdan sonra yazdırın
  • , yani bayt olarak en kısa kod kazanır

Örnek Çalışmalar:

Giriş (Tam Uyum testi) :

qwertyuiopasdfghjklzxcvbnm
4
***** * ***
*   * * *
*   * * *
***** * ***

Çıktı :

qwert y uio
p   a s d
f   g h j
klzxc v bnm

Giriş (Ekstra karakter testi) :

qwertyuiopasdfghjklzxcvbnm12345
4
***** * ***
*   * * *
*   * * *
***** * ***

Çıktı :

qwert y uio
p   a s d
f   g h j
klzxc v bnm
12345

Giriş (Yetersiz Karakter testi) :

qwertyuiopasdfg
4
***** * ***
*   * * *
*   * * *
***** * ***

Çıktı :

qwert y uio
p   a s d
f   g . .
..... . ...

2
Programın anlambilimini değiştirmeden boşluklar ve yeni satırlar eklemeye izin verilen yerlerde ne gibi varsayımlar yapılmalıdır?
Peter Taylor

1
@PeterTaylor kodu yerleştirmek / ayırmak için hiçbir yolu var gibi görünüyor, bu yüzden anlambilim yok sayılır?
Martin Ender

1
Spec ortalama bölümlerini "atlanabilir" ve "ya da başka bir karakter" Do biz sizsiniz, diyelim ki, hat sayısı belirtmek için ücretsiz olmalıdır atlanabilir ve yıldızlar, diyelim ki, tarafından değiştirilmesi gerektiğini Xiçin es bizim program?
Ilmari Karonen

1
@Bakuriu Yorumunuzu anlamıyorum. ASCII'de bir program yazarsanız, her karakter bir bayt olur. UTF-32 ile yazarsanız, her karakter 4 bayt olur. Karakterlere göre bayt cinsinden en kısa kod , geçerli spesifikasyona göre kazanır. Kodlamanın bir gereksinim olmasını istediğiniz gibi görünüyor, ancak neden gerekli olduğunu anlamıyorum. Yorumunuzu yanlış anladım mı?
Rainbolt

1
Bazı kuralları eksik bazı cevaplara dayanarak, iki örnek ekledim ve daha fazla netlik için tüm örnek bloğunu kural bloğunun altına taşıdım.
Veskah

Yanıtlar:


5

GolfScript, 30 karakter

n/(\(;n*'*'/{@.!'.'*+([]+@+}*\

Çevrimiçi çalıştırın .

Örnekler:

> qwertyuiopasdfghjklzxcvbnm
> 4
> ***** * ***
> *   * * *
> *   * * *
> ***** * ***

qwert y uio
p   a s d
f   g h j
klzxc v bnm

> qwertyuiopasdfghjklzxcvbnm
> 1
> ***** * ***

qwert y uio
pasdfghjklzxcvbnm

> qwerty
> 2
> ***** * ***
> *   * * *

qwert y ...
.   . . .

10

Perl 6: 60 karakter DÜZENLEME : 38 puan (aşağıya bakın)

  #C#O     D#E#G#O       #L#
#F    #.#S#       T#A#C#K
  get\     .subst(       "*"
,{    shift       BEGIN [
  get\     .comb,\       "."
xx    * ]},       :g)\ .\
  say\     xx get\       ()\
#E    #X#C#       H#A#N#G
  #E#.     #C#O#M#       #!#

Korkunç sanat becerilerimi takdir etmiyorsanız, golf:

get.subst("*",{shift BEGIN [get.comb,"."xx*]},:g).say xx get

Bu, değerlendirme süreleriyle garip şeyler yapar.

İlk olarak, BEGINanahtar kelime [get.comb, "." xx *]önce değerlendirilmeye zorlanır, bir diziye "kodu" oluşturan karakterlerin listesini ve ardından sonsuz miktarda"." s ekler.

Daha getsonra, ASCII sanat şablonunun satır sayısını alarak, sonunda değerlendirilir. xxOperatör programın ilk kısmı bunu defalarca tekrar eder. Bu code() xx count()temel olarak şeker olduğunu fark ettiğinizde daha mantıklıdır code() for 1..count(): count()önce değerlendirilmelidir.

Son olarak, getprogramın başlangıcında ASCII sanat şablonunun bir çizgisini alır ve her "*"şeyi, her şeyden önce yaptığımız dizinin başlangıcından kaymış bir değerle değiştirir ({shift BEGIN …} ).

DÜZENLE:

37 karaktere kadar artı bir komut satırı anahtarı için golf:

perl6 -pe's:g[\*]=shift BEGIN [get.comb,"."xx*]'

Bu, orijinal ile aynı kavramdır, -pher satırda yinelenen anahtar ( BEGIN"kodu" içinde okuduktan sonra ) ve *yazdırmadan önce tüm harfleri "kod" dan sonraki harfle değiştirir. Bunun için giriş biçimi, biçimin satır sayısını içermemelidir.


6

Ruby 2.0, 53 52 karakter

c=gets.chop
$><<gets($n).gsub(?*){c.slice!(0)||?.}+c

Spesifikasyona göre, 'satır sayısı' parametresini kullanmaz.

Örnek çalışma:

qwertyuiopasd
***** * ***
*   * * *
*   * * *
***** * ***

Çıktı:

qwert y uio
p   a s d
.   . . .
..... . ...

1
./ascii.rb: line 2: syntax error near unexpected token `(' ./ascii.rb: line 2: `puts gets($n).gsub(?*){c.slice!(0)||?.},c'
Charles

@Charles Yüklediğim Ruby'nin herhangi bir sürümünde bu hatayı alamıyorum. IDEONE üzerinde çalışan kod şu şekildedir: ideone.com/3HG3Fb
Paul Prestidge

tuhaf. IDEONE iyi çalıştı. Neyse, değiştirerek bir char (boşluk) kaydedebilirsiniz puts ile $><<ve değişen ,bir karşı uçta+
Değil Charles

@Charles İyi çağrı. Teşekkürler!
Paul Prestidge

2

PowerShell , 63 86 83 82 bayt

+20 bytes teşekkürler @Veskah

param($s,$p)-join($p|% *ht($s|% Le*)'*'|% t*y|%{if($_-eq42){$_=$s[$i++]}"$_."[0]})

Çevrimiçi deneyin!

Daha az golf:

param($string,$pattern)

$chars = $pattern |
    % PadRight ($string|% Length) '*' |
    % toCharArray |
    % {
        if($_-eq42){$_=$string[$i++]}    # $_ can become $null
        "$_."[0]                         # $_ or '.' if $_ is $null
    }
-join($chars)


2

T-SQL, 142 bayt

@h giriş metnidir

@ patern

DECLARE @h varchar(max)='qwertyuiopasdfg'
DECLARE @ varchar(max)='
***** * ***
*   * * *
*   * * *
***** * ***'

WHILE @ like'%*'SELECT @=left(@,charindex('*',@)-1)+left(@h+'.',1)+stuff(@,1,charindex('*',@),''),@h=substring(@h,2,999)PRINT
concat(@,'
'+@h)

Çevrimiçi deneyin



1

JavaScript - 199

text="qwertyuiopasdfghjklzxcvbnm";
pattern="***** * ***\n*   * * *\n*   * * *\n***** * ***";

function p(a,c){z=c.length,y=a.length,x=0;for(i=z;i-->0;)if(c[i]=="*")x+=1;if(x-y>0)for(i=x-y;i-->0;)a+=".";for(;i++<x;)c=c.replace(new RegExp("[*]"),a[i]);console.log(c);console.log(a.substring(x))}

p(text,pattern);

Desende kullanılmazsa metin girişinde fazladan karakterler çıkarır, dolgulu "." eğer yeterli değilse.

EDIT: metin ve desen kabul eden bir işlev olarak değiştirildi


4
Güzel ... ama bu sabit kodlu girişi kullanıyor.
TheDoctor

JS'den stdin'i, özellikle yeni satırları nasıl kullanacağımdan emin değildim. Öneriler?
Matt

@Matt Düğümü? Örümcek maymunu?
Charles

Belki de bir işlev haline getirir ...
TheDoctor

4
136:function p(a,c){x=c.split(s='*').length-1;for(i=x-a.length;i--;)a+='.';for(;i++<x;)c=c.replace(s,a[i]);console.log(c+'\n'+a.substring(x))}
Michael M.

1

JavaScript (ES6) - 96 87

r=(c,p)=>{c=0+c;console.log(p.replace(/\*/g,t=>(c=c.substr(1),c[0]||'.'))+c.substr(1))}

Not: OP tarafından önerildiği gibi bir işlev kullanıyorum. Ancak bir programa sahip olması gerekiyorsa, 93 karakterlik bir çözüm .

c=0+(x=prompt)();p=x();console.log(p.replace(/\*/g,t=>(c=c.substr(1),c[0]||'.'))+c.substr(1))

EDIT1: Büyük değişiklik, bunu neden ilk defa fark etmediğimi bilmiyorum: P 40 karakter kaydetti.


Kullanımı :

// r(code, pattern)
r("qwertyuiopasdfghjklzxcvbnm", "***** * ***\n*   * * *\n*   * * *\n***** * ***\n** ** **)

Test Girişi : (spesifikasyona göre gereksiz isteğe bağlı numara olmadan)

qwertyuiopasdfghjklzxcvbnm
***** * ***
*   * * *
*   * * *
***** * ***
** ** **

Çıktı :

qwert y uio
p   a s d
f   g h j
klzxc v bnm
.. .. ..      // not much text was there to fill *s - replaced with dots as per spec

Kodlanmamış Kod :

function run(code, pattern){
  code = "0" + code;  // prepend a zero; useful for the substring operation ahead

  pattern = pattern.replace(/\*/g, function(){  // replace the dots
    // by removing the first letter of code
    // and replacing dot with the first-letter of leftover code 
    // and if it isn't there (code finished)
    // return a dot

    code = code.substr(1); 
    return c[0] || '.';
  });
  }

  // after this operation; code contains the last letter of the org. code

  console.log(  p +  // the pattern has now code
                "\n" +   // and a newline
                c.substr(1) // if there is more than one letter of code left; display it
             );
}

Kullanıcılardan herhangi bir öneri duymak çok güzel olurdu :)


1

Perl, 70 karakter

@_=split'',<>=~s/\n//r;<>;print/\*/?shift@_||'.':$_ for map{split''}<>

Veya sınır kontrolü olmadan 56 karakter

@_=split'',<>;<>;print/\*/?shift@_:$_ for map{split''}<>

Bu kod, spesifikasyonda olduğu gibi ikinci satırı kullanmaz ve üç karakterle kısaltılabilir <>;


1

Bash, 166156111 106

Standart girişten okur, satır sayısı almaz. İlk girdi satırı, ascii sanatına koymak istediğiniz koddur, sonraki tüm satırlar, @karakterden oluşan ascii sanatıdır . Girdinin uzunluğu en fazla 999 karakterdir ve eğik çizgi içermesine izin verilmez . (Kullanmamayı seçtim *ya da #Bash'te özel anlamları var).

read -n999 -d/ i p
while [[ $p =~ @ && -n $i ]];do
p="${p/@/${i:0:1}}"
i=${i:1}
done
tr @ .<<<"$p"
echo $i

UYARI: Bu program adlı bir dosya kullanır p. Programı yürüttükten sonra silinp - programı ikinci çalıştırdığınızda karıştırır.

Buradaki çalışmaların çoğu

p="${p/@/${i:0:1}}"
i=${i:1}

İlk satır ilk satırın yerine geçer @ , teknikteki kodun ilk karakteri ile değiştirir. İkinci satır, kodun ilk karakterini kaldırır.

Şekli doldurmak için yeterli kod yoksa, ana ascii art çıktısından sonra bir satırsonu yazdırılır echo $i.


1

C, 98 , 91 karakter

Burada 100 karakterin altında oldukça basit bir C çözümü. Bu, satır sayısı girişini kullanmaz. (Başka bir gereksiz gereksiz alır () gerekir).

char b[999],*s;c;main(){gets(s=b);while(~(c=getchar()))putchar(c^42?c:*s?*s++:46);puts(s);}

ungolfed:

char b[999],*s;c;
main(){
    gets(s=b);
    while(~(c=getchar()))
        putchar(c^42?c:*s?*s++:46);
    puts(s);
}

7 bayt kaydetmek puts(s)yerine kullanabilirsiniz printf("%s",s).
nyuszika7h

@ nyuszika7h Teşekkürler! Ama ek \nbir sorun olup olmadığını bilmiyorum .
MarcDefiant

1

Python 2.7, 165 155 150 138 119 karakter

Pekala, sanırım Python ile yapmanın en küçük yolu bu.

import sys
r=raw_input
l=list(r())
w=sys.stdout.write
for c in"\n".join([r()for _ in[1]*input()]):w(c=='*'and(l and l.pop(0)or'.')or c)
w("".join(l))

Düzenleme: daha az bayt kullanılan yeni fonksiyonel 1.0.1 sürümü:

Edit2: Kullanılmayan içe aktarma map(r,['']*input())yerine [r()for _ in[1]*input()]kaldırıldı

Edit3: bir karakter kaydetmek ve desen için bilgi istemi karakteri eklemek '>'*input()yerine ['']*input():)

r=raw_input
l=list(r())
print''.join(map(lambda c:c=='*'and(l and l.pop(0)or'.')or c,"\n".join(map(r,'>'*input())))+l)

9 bayt kaydetmek (['.']+l).pop(0)yerine kullanabilirsiniz (len(l)and l.pop(0)or'.'). Ve 1 bayt kaydetmek input()yerine int(r()).
nyuszika7h

İçin teşekkürler input! Ne yazık ki ilk tavsiyeniz işe yaramıyor çünkü dize uzunluğu> 0 olduğu sürece noktalar çıkıyor.
avall

Önerimin neden doğru olmadığını anlıyorum. (l+['.']).pop(0)Bunun yerine deneyin , ancak bu da işe yaramazsa, l andyerine kullanarak 4 bayt kaydedebilirsiniz len(l)and.
nyuszika7h

(l+['.']).pop(0)öğeleri kaldırmaz lyüzden sadece ilk karakter baskılı ama ldurum :) işleri
avall


0

05AB1E , 18 17 15 bayt

s0¢.$«0¹S.;0'.:

Kodu ilk girdi olarak alır, örüntüyü ikinci olarak alır ( 0yerine #).

Çevrimiçi deneyin veya tüm test senaryolarını doğrulayın .

18 15 bayt alternatifi girişleri ters sırada alarak:

0¢.$¹ì0IS.;0'.:

Çevrimiçi deneyin .

Açıklama:

s                # Swap with implicit inputs, so the stack order is now: [code, pattern]
 0¢              # Count the amount of "0" in the pattern
   .$            # Remove that many leading characters from the code
     «           # Append it to the (implicit) pattern input
      0¹S.;      # Replace every "0" one by one with the characters of the first code input
           0'.: '# Then replace any remaining "0" with "."
                 # (after which the result is output implicitly as result)
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.