ASCII hareketli kar sahnesi


22

Herhangi bir ASCII sanat eserini, yağan kardan oluşmaya başlayan hareketli bir kar sahnesine dönüştürmek için en kısa programı yazınız .

Girdi belirtimi : Programınız isteğe bağlı boşluk, yıldız işareti ve yeni satır kombinasyonlarını kabul etmelidir. Giriş en fazla 23 satır ve satır başına 80 karakter içerecektir. Boş satır olmayacak, ancak satır yalnızca boşluktan oluşabilir. Bir izleyen yeni satır eklenecek ve dikkate alınmaması gerekiyor.

Çıktı : Kullanıcı programı el ile sonlandırana kadar işletim sisteminizin metin konsolu veya terminal emülatörü için ASCII karakterlerini (boşluklar, yıldız işaretleri) ve kontrol kodlarını (satır başları, satır beslemeleri, ANSI çıkış kodları, vb.) Çıkış. İşletim sisteminiz bu ayara izin veriyorsa, terminal penceresinin 80x24 karakter olduğunu varsayabilirsiniz.

Kurallar :

  • Animasyon düzgün ve hızlı olmalıdır (15 fps tercih edilir).
  • Kar yoğunluğu% 5 ile% 15 arasında olmalıdır.
  • Saniyede birden fazla kar ekranı kaydırılamaz. (Bu, herhangi bir saniyede 24 satırdan fazla yeni kar eklenmeyeceği anlamına gelir.)
  • Kar, ekranın üst kısmına girdiğinde bariz bir desen göstermemelidir; rastgele görünmeli.
  • Program, ekranın tüm satırlarını başladığında olabildiğince çabuk karla doldurmalıdır; Ekranın bireysel satırlarının ilk kez doldurulması izleyiciye açık olmamalıdır.
  • Giriş ASCII resminin sol alt köşesi, ekranın sol alt köşesinde olmalıdır (daha fazla açıklama için Şekil 1).
  • ASCII sanatının içindeki veya altındaki alanlar kalıcı olarak yıldızlarla doldurulmamalıdır. Bununla birlikte, yıldızlar bu alanda ilerleyebilir (ancak zorunlu değildir).
  • Girişte gösterilenler dışında ekranın altında veya mevcut karın üzerinde kar birikmemelidir.
  • Karşılıklı boşluklar Noel ağacı animasyonunu orijinal kodumun çıktısından çok farklı gösterdiğinden, daha düşük boşluklar üst boşluklardan önce doldurulmalıdır. (2011-12-20 arası eklendi)

Mutlu tatiller!

Şekil 1: 80x24 ekranın etiketli alanları

---------------------------New snow added on this line--------------------------
                                                                             |
                                                                             |
----------------------------------------------------------+                  |
                                                    ****  |                  |
    Snow MUST fall  Snow MAY fall ---------------->  **** |                  |
    through this    through these          ****      **** |  Snow MUST fall  |
    area.           areas of a              ****     **** |  through this    |
                    completed   \--------->  ****     ****|  area.           |
        ASCII art   scene.    \     ***        ****   ****|                  |
          area         \       \   *******      ****  ****|                  |
                        \       \    ********     ***  ***|  (ALL CAPS terms |
      (located in        \       \-->   *********  ***    |  have standard   |
       lower left         \     *******     ******  MAY   |     RFC 2119     |
       corner of           \    *************  **   fall  |    meanings.)    |
       screen)              \        ***********    here  |                  |
                         *** +--->          ****  ***     |                  |
                         *** | ****************   ***     |                  |
  | Snow MUST fall       *** | ****************   ***     |                  |
  | through this         *** +--->                ***     |                  |
  | area.                *** | ****************   ***     |                  |
--+---------------------+*** +--->                ***+----+------------------+--
  |   Snow MUST NOT     |****************************|      Snow MUST NOT    |
  V  accumulate here.   |****************************|     accumulate here.  V

Örnek girişler

Kod Golf Afişi

 ******   *******  ********  ********     ******    *******  **       ******** 
**    ** **     ** **     ** **          **    **  **     ** **       **       
**       **     ** **     ** **          **        **     ** **       **       
**       **     ** **     ** ******      **   **** **     ** **       ******   
**       **     ** **     ** **          **    **  **     ** **       **       
**    ** **     ** **     ** **          **    **  **     ** **       **       
 ******   *******  ********  ********     ******    *******  ******** **       

Yığın Taşması Logosu

                                                    ****
                                                     ****
                                           ****      ****
                                            ****     ****
                                             ****     ****
                                    ***        ****   ****
                                   *******      ****  ****
                                     ********     ***  ***
                                        *********  ***
                                *******     ******
                                *************  **
                                     ***********
                         ***                ****  ***
                         ***   ****************   ***
                         ***   ****************   ***
                         ***                      ***
                         ***   ****************   ***
                         ***                      ***
                         ****************************
                         ****************************

Noel ağaçları

                                        *
                                       ***                           *
                *                     *****                         ***
               ***                   *******           *           *****
              *****                 *********         ***            *
                *                  ***********       *****
                       *          *************     *******
        *             ***        ***************       *               *
       ***           *****      *****************                     ***
      *****         *******    *******************                   *****
     *******           *      *********************                 *******
    *********                           *                          *********
        *                                                              *

1
Üçüncü yılbaşı ağacı kırıldı.
Bobby,

Güzel meydan okuma! Kuralların daha kolay referans olması için sıralanması gerektiğini düşünüyorum ve üçüncü ve altıncı kuralı anlamıyorum ...
hallvabo

@hallvabo Ben bu iki kuralı açıkladım, ikincisi etiketli bir rakam ekleyerek.
Lütfen

Açıklama talebi: Yeni satır en fazla 80 karakter uzunluğunda mı, yoksa en fazla 80 karakter artı yeni satır mı? (İkincisini kabul ettim, ancak bazı bildirimler
eskisini

@IlmariKaronen İkincisi.
Lütfen

Yanıtlar:


5

Perl, 196/239 karakter

chomp(@p=(@f=($"x80)x24,<>)[-24..-1]);{@s=(join("",map rand>.1?$":"*",1..80),@s);if(@s>23){$t=$f[$_],print$_?$/:"\e[H",($f[$_]|=$s[$_]&$p[$_])|($s[$_]&=~$t^$f[$_])for 0..23;select"","","",.1}redo}

Bu çözüm, JS örneğinizden farklıdır; desen, aşağıdan yukarıya yerine yukarıdan aşağıya doğru doldurulur, ancak kurallarda bu konuda hiçbir şey söylemediğiniz için bunun doğru olduğunu varsayıyorum.

\eBasit bir ESC karakteri ile değiştirilerek önemsiz bir 1 karakterlik azaltma elde edilebilir , ancak bu kodun okunmasını ve düzenlenmesini zorlaştırır.


Güncelleme: Ben yaptım aşağıdan yukarıya doğru desen doldurur ve kar 43 ekstra karakter pahasına, örnek JS uygulanmasında olduğu gibi, desen dolu bölümleri arasında düşmesine izin vermeyen bir sürümü ile gelip yönetmek:

chomp(@p=(@q=@f=($"x80)x24,<>)[-24..-1]);{@s=(join("",map rand>.1?$":"*",1..80),@s);if(@s>23){my$q;$q[-1-$_]=($q|=$p[-$_]&~$f[-$_])for@a=0..23;print$_?$/:"\e[H",($f[$_]|=$s[$_]&$p[$_]&~$q[$_])|($s[$_]&=~$f[$_])for@a;select"","","",.1}redo}

Şununla değiştirmek ($s[$_]&=~$f[$_]), $s[$_]düşen karın, desenin doldurulmuş kısımlarından geçmesine izin vererek 11 karakterden tasarruf etmenizi sağlar (spesifikasyona uygun, ancak örnek uygulamada değil).


Tamam, hala bir hafta sonra yarışa öncülük ediyor gibi göründüğüm için, çözümümün daha fazla rekabeti teşvik etmek için nasıl çalıştığını açıklamalıyım. (Not: Bu açıklama, 196 char üstten yükleme dolum sürümü içindir. Daha sonra diğer sürümü eklemesi için değişiklik yapabilir.)

Her şeyden önce, çözümümün dayandığı büyük numara, ASCII karakter kodlarının düzenlenmesi nedeniyle, bir alan için ASCII kodundaki 1 bitin bir kod için olanların bir alt kümesi haline gelmesidir. yıldız işareti.

Böylece, aşağıdaki ifadeler doğrudur: " " & "*" eq " "ve " " | "*" eq "*". Bu, sahnenin statik ve hareketli parçalarını ayrı ayrı karakterler üzerinde dolaşmak zorunda kalmadan birleştirmek için bitli dize işlemlerini kullanmamı sağlıyor.

Yani, bunun dışında, hadi kodu geçelim. İşte bir de-golfed versiyonu:

chomp(@p = (@f = ($" x 80) x 24, <ARGV>)[-24..-1]);
{
    @s = (join('', map((rand > 0.1 ? $" : '*'), 1..80)), @s);
    if (@s > 23) {
        foreach (0 .. 23) {
            $t = $f[$_];
            print( $_ ? $/ : "\e[H" );
            print( ($f[$_] |= $s[$_] & $p[$_]) | ($s[$_] &= ~$t ^ $f[$_]) );
        }
        select '', '', '', 0.1;
    }
    redo;
}

İlk satır dizileri @f("sabit" için) ve @p("desen" için ) ayarlar . @fekranın sabit bir parçasını oluşturacak ve @pdoğrudan bir şey gösterilmeden, giriş desenini içeren boşluklardan başka bir şey içermemeye başlar ; animasyon ilerledikçe, @fsonuçta görünene kadar daha fazla yıldız ekleyeceğiz @p.

Özellikle, her biri 80 boşluk olan 24 dizeye @f = ($" x 80) x 23ayarlar @f. ( $"varsayılan değeri sadece boşluk olan özel bir Perl değişkenidir.) Daha sonra bu listeyi alıyoruz, readline operatörünü kullanarak giriş satırlarını ekliyoruz <>, bu birleştirilmiş listenin son 24 satırını alıyoruz ve şuna atayın @p: şudur: Desenin @polması gerektiği yerde görünmesi için boş çizgilerle doldurmanın kompakt bir yolu . Sonunda chompgirdiler , @pdaha sonra sorun çıkarmayacakları için takip eden yeni satırları kaldırmak için giriyoruz .

Şimdi ana döngüye bakalım. Sonuçta {...;redo}sonsuz bir döngü yazmanın daha kısa bir yol olduğu , while(1){...}hatta daha for(;;){...}önce noktalı virgül atlamayı başarabilirsek, redoçünkü hemen bir ifbloğu takip ettiği ortaya çıktı.

Ana döngünün ilk satırı @s, her yinelemede% 90 boşluk ve% 10 yıldızla rastgele 80 karakterli bir dizge hazırladığı diziyi ("kar" için) tanıtır . (Birkaç karakterden tasarruf etmek için, @sdizinin sonundan itibaren hiçbir zaman aslında fazladan satır çıkmaz , bu yüzden daha uzun ve daha uzun süre devam eder. Sonunda, dizi belleğe sığmayacak kadar uzun sürdüğü için programı durdurur. çoğu insanın bu animasyonu izleyeceğinden çok daha uzun sürecek . Yedi karakter karşılığında bunu düzeltmeden pop@s;önce bir açıklama eklemek select.)

Ana döngünün geri kalanı bir ifbloğa sarılır , böylece yalnızca @sdizi en az 24 satır içerdiğinde çalışır . Bu, tüm ekranın en baştan düşen karla dolmasını gerektiren ve aynı zamanda bitsel işlemleri biraz kolaylaştırmayı gerektiren şartnameye uymanın basit bir yoludur.

Daha foreachsonra golflü versiyonda aslında for 0..23değiştiricili tek bir ifade olan bir döngü geliyor . Döngünün içeriği muhtemelen bir açıklama gerektirdiğinden, biraz daha açacağım:

foreach (0 .. 23) {
    print $_ ? $/ : "\e[H";     # move cursor top left before first line, else print newline
    $t = $f[$_];                # save the previous fixed snowflakes
    $f[$_] |= $s[$_] & $p[$_];  # snowflakes that hit the pattern become fixed 
    $s[$_] &= ~$t ^ $f[$_];     # ...and are removed from the moving part
    print $f[$_] | $s[$_];      # print both moving and fixed snowflakes ORed together
}

Her şeyden önce, $_başka bir değişken belirtilmediği sürece Perl'deki varsayılan döngü sayacı değişkenidir. Burada 0 ila 23 arasında, yani ekran çerçevesindeki 24 çizginin üzerinde çalışıyor. dizide $foo[$_]indekslenen öğeyi belirtir .$_@foo

De-golfed döngünün ilk satırda, biz ya bir yeni satır baskı (uygun olarak elde edilen $/zaman, özel bir değişkeni) ya da $_0 eşittir dize "\e[H", \eESC karakterini göstermektedir. Bu, imleci ekranın sol üst köşesine taşıyan bir ANSI terminal kontrol kodudur . Teknik olarak, eğer belirli bir ekran boyutu kabul edersek, bunu bu versiyonda tuttum, çünkü animasyonu çalıştırmak için terminalimi yeniden boyutlandırmam gerekmediği için bunu ihmal edebiliriz.

Çizgide, bir sonraki satırda potansiyel olarak değiştirmeden önce "geçici" bir değişkenin (bu nedenle ) $t = $f[$_]geçerli değerini kaydederiz; burada düşen kar ile giriş düzeninin ve operatörün OR'lerinin kesişimini (bit yönünde VE) verir. Bu sabit çıkış hattına .$f[$_]$t$s[$_] & $p[$_]|=$f[$_]

Aşağıdaki satırda $t ^ $f[$_], önceki ve şimdiki değerlerin bit cinsinden XOR değerini verir $f[$_], yani önceki satırda değiştirdiğimiz bitlerin bir listesini (varsa) ve giriş dizelerinin ikisini de yok ~saymak çıkışı olumsuzlar. Böylece, elde ettiğimiz şey, bir önceki satıra yeni eklediklerimiz dışında tüm bitlerin 1'e ayarlandığı bir bit maskesidir $f[$_]. VE bu bit maskesini üzerine sokmak, $s[$_]bu bitleri ondan kaldırır; Aslında, bunun anlamı, düşen bir kar tanesi sabit düzendeki bir deliğe girdiğinde düşen kar dizisinden çıkarılmasıdır.

Son olarak, print $f[$_] | $s[$_](golf sürümünde önceki iki satırı bir araya getirerek uygulanır), mevcut satırdaki sabit ve hareketli kar taneleri birliğini yazdırır.

Açıklamak için kalan bir şey daha select '', '', '', 0.1iç döngü altında. Bu sadece Perl'de 0.1 saniye uyumak için kirli bir yoldur; Aptal tarihsel bir nedenle, standart Perl sleepkomutunun bir saniyelik çözünürlüğü var ve modülden daha iyisini sleepalmak 4-arg 'ıTime::HiRes kötüye kullanmaktan daha fazla karakter alıyor .select


Hafif bir hata var gibi gözüküyor: 24. satır kullanılmıyor ve ASCII sanatının en alt satırı 23. satır. Üstelik başlangıçta belirtmemiş olmama rağmen, üst alanları doldurmadan önce alt boşlukları doldurması gerekiyor.
Lütfen 21:11

@PleaseStand: 2 satırın saymaliyeti karşılığında 24 satırın tümünü (ve bu arada bunlardan kurtuldu) kullanmak için kodu değiştirdim . Yine de doldurma sırasını çok kolay değiştirebileceğimi sanmıyorum; benim uygulamam oldukça temelde buna bağlı.
Ilmari Karonen

Harika bir açıklama! Keşke bu girişi tekrar oylayabilseydim.
Dillon Cower

@PleaseStand: Aslında yoktu şimdi hemen hemen sizin JS örnek olarak aynı görünüyor tabandan tavana dolum versiyonunu yapmak yönetmek; yukarıdan aşağıya biraz daha uzun, ama şimdiye kadar diğer girişlerden daha kısa.
Ilmari Karonen

3

HTML ve JavaScript, 436 karakter

Girdiye bağlı olarak:

<body onload="for(a=[],b=[],c=document.body.firstChild,e=c[H='innerHTML'].split(N='\n'),f=e.length-1,g=24,h=g-f;f--;)for(X=80;X--;)b[80*(h+f)+X]='*'==e[f][X];for(setInterval(F='for(y=24;y--;)for(x=80;x--;)if(a[w=80*y+x]){d=1;if(b[w])for(d=0,z=y+1;24>z;++z)b[s=80*z+x]&&!a[s]&&(d=1);d&&(a[w]=0,a[w+80]=1)}for(x=80;x--;).1>Math.random(i=0)&&(a[x]=1);for(t=\'\';1920>i;++i)t+=\'* \'[+!a[i]],79==i%80&&(t+=N);c[H]=t',67);g--;)eval(F)"><pre>

Her örnek için çalıştığını görün: kod golf , Yığın Taşması logosu , Noel ağaçları . Internet Explorer kullanıcılarının 9. sürümü çalıştırmaları ve bu belgenin düzgün çalışması için "Belge Modu" nu "IE9 standartlarına" (F12 geliştirici araçlarını kullanarak) ayarlaması gerekir.


1
Her 3 kırılmış gibi görünüyor? pasteall.org/pic/show.php?id=66297
CoDEmanX

1

Python, 299 karakter

Bu, yeni hattın 80 karakter sınırına dahil olduğunu varsayarak kurallara uygun olmalıdır.

import random,sys,time
C=1920
v=_,x=' *'
a=['']*C
f=lambda n:[random.choice(e*9+x)for e in _*n]
for e in sys.stdin:a+="%-80s"%e
a=a[-C:]
s=f(C)
while 1:
 z=0;t=''
 for e in s:
    t+=v[x<a[z]or e>_]
    if(e>_<a[z])>(x in a[z+80::80]):a[z]='+'
    t+=z%80/79*'\n';z+=1
 print t;s=f(80)+s[:-80];time.sleep(.1)

Girdi tam olarak 80 karakter (artı yeni satır) uzunluğunda herhangi bir çizgiye sahipse çıkışınız berbatlaşır. Lütfen tamam olup olmadığını açıklamak için PleaseStand istedim.
Ilmari Karonen,

Bunun nedeni 80 karakterlik geniş her hattın sonuna yeni bir satır eklemem. Açıklama, burada yeni satırların dahil edilmesi gerektiğini belirttiği için belirsizdir, ancak terminalin 80 karakter genişliğinde olduğu varsayılabilir (bu durumda yeni satırları atlayabilir ve otomatik sararmaya bağlı olabilir).
hallvabo

Bence asıl sorun, giriş satırlarını 80 karaktere doldurmadan önce yeni satırları çıkarmamanızdır, böylece 80 karakter artı bir satırsonu girişi aslında 81 karakter ekleyerek adizine neden olur. Sadece bunu denedim ve değiştirilmesi gibi görünüyor %eile %e.rstrip()on line 6 düzeltmeleri sorunu. (Tabii ki, daha kısa bir düzeltme olabilir; Python
Ilmari

81 karakter çizgisini desteklemek istiyorsanız, sayıları değiştirmeniz yeterli. Satır başına 100 karakterin altında kaldığınız sürece, karakter sayısı değişmeyecek :-)
hallvabo

Kodunuzu 81 satırlık satırlar kullanacak şekilde değiştirirsem 80 sütunluk bir terminalde düzgün çalışmayacak, değil mi? Sadece 80 sütunluk bir çıktı veriyorsunuz, doğru olarak 80 sütunluk girdiyi kabul etmiyorsunuz . Deneyin: her birinde 80 yıldız bulunan birkaç satırlık bir giriş dosyası oluşturun ve ne olduğunu görün. O kadar zor olmamalı: benim çözümüm çok iyi idare ediyor.
Ilmari Karonen

0

Java, 625 karakter

import java.io.*;import java.util.*;class s extends TimerTask {int _c,_k;char _i[],_o[];boolean _b[];public s(String f) throws IOException {_i=new char[23*80];_o=new char[80];_b=new boolean [23*80];BufferedReader br = new BufferedReader(new FileReader(f));while (br.read(_i,_c++*80,80)!=-1);} public void run(){_k=--_k<0?_c:_k;for(int i=0;i<80;_b[_k*80+i]=Math.random()>0.9?true:false,i++);for(int m=0;m<_c;m++){for(int n=0;n<80;_o[n]=_b[(_k+m)%_c*80+n]?'*':_i[m*80+n],n++);System.out.println(_o);}}public static void main(String[] a) throws IOException{Timer timer=new Timer();timer.scheduleAtFixedRate(new s(a[0]),0,500);}}

Java'da basit bir çözüm.


Güzel, ama şartnameye uyduğunu sanmıyorum. Özellikle, tüm deseni baştan gösterirsiniz - bu, örnek demoda olduğu gibi "yağan kardan oluşmaz". (Kuşkusuz, bu soruda daha iyi açıklanabilir. Ne yapması gerektiğini anlamak için gösteriyi izlemeniz gerekiyor.) Ayrıca, kare hızınız çok yavaş, karla kaplı bir ekranla başlamıyorsunuz. Verilen örneklerden farklı bir giriş formatı varsayıyorsanız, ve imleç konumunu çerçeveler arasında sıfırlamanız "\033[H"gerekir (baskı bunu yapmalıdır).
Ilmari Karonen
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.