Ciutkan ascii-art

12

Tantangan

Diberi kisi persegi panjang karakter ascii yang dapat dicetak sebagai string atau melalui input standar, tulis fungsi atau program yang memecah karakter non-spasi menjadi tumpukan di bagian bawah.

Aturan:

  • Output memiliki dimensi dan karakter yang sama dengan input.
  • Karakter non-spasi di (row a,column b)tidak dapat memiliki karakter spasi ' 'di (a-1, b), (a-1,b-1)atau (a-1,b+1), di mana baris dinomori dari paling bawah. Ini memiliki konsekuensi bahwa semua tumpukan vertikal harus runtuh ke samping.
  • Karakter non-ruang dapat melakukan perjalanan di sebagian besar (initial height - final height)tempat ke kiri atau ke kanan (lihat Gambar 1).
  • Anda dapat mengasumsikan gambar memiliki cukup ruang untuk runtuh tanpa karakter jatuh dari layar.

Gambar 1: lokasi akhir yang mungkin untuk karakter yang @#$ditampilkan x,y,zmasing-masing.

..............
...@..........
..xxx.........
.xxxxx...#....
xxxxxxx.yyy.$.

Urutan di mana karakter runtuh dapat dipilih secara bebas. Mengejar spasi tidak apa-apa tetapi mengikuti baris baru.

Ini adalah , jadi jawaban tersingkat dalam byte menang!

Contoh

                 (__)
                 (oo)
           /------\/
          / |    ||
         *  /\---/\
            ~~   ~~
..."Have you mooed today?"...

Satu kemungkinan keluaran:

 
 
 
                --(_
           /----|/|(o_)
          /|/~\---~\\/o)
..."Have*you~mooed~today?"...
Angs
sumber
Hanya untuk memperjelas, bagaimana karakter jatuh dapat dikodekan daripada dihasilkan secara acak setiap kali?
ETHproduksi
18
Apa yang sapi itu lakukan terhadapmu ?? :(
FlipTack
@ ETHproduksi itu benar. Contoh saya melakukannya dari bawah ke atas, kiri ke kanan tetapi urutan acak atau sesuatu yang lain baik-baik saja, selama aturan dipatuhi.
Angs
@ Flp.Tkc Ini hanya model.
Angs
1
@DestructibleWatermelon jika sebuah karakter jatuh dari layar, itu salah mereka, bukan milikmu.
Angs

Jawaban:

4

JavaScript (ES6), 100 90 88 byte

f=s=>s==(l=s.search`
`,s=s.replace(eval(`/(\\S)([^]{${l-1},${l+1}}) /`),` $2$1`))?s:f(s)
s=`                 (__)        
                 (oo)        
           /------\\/         
          / |    ||          
         *  /\\---/\\          
            ~~   ~~          
..."Have you mooed today?"...`
console.log(s)
console.log(f(s))

Membutuhkan string untuk memiliki setidaknya dua garis dan semua garis padded dengan panjang yang sama Output untuk gambar contoh:

              ( --           
            /|---/|-(o__     
          */~~\---~\|\/o))   
..."Have you/mooed~today?"...

Perhatikan bahwa ketika mencoba untuk memindahkan elemen ke kanan jika memungkinkan, *tidak jatuh antara Havedan you.

Sunting: Disimpan 10% berkat @ETHproductions. Disimpan 2 byte lagi berkat @DanielIndie.

Retina 0.8.2 , 50 byte

+`(?<=(.)*)(\S)(.*¶(?<-1>)?(?>(?<-1>.)*).?) 
 $3$2

Cobalah online! Pendekatan yang sedikit berbeda dengan jawaban JavaScript saya, ini menggunakan grup penyeimbang untuk mencocokkan ruang di bawah karakter non-spasi; yang (?<-1>)?memungkinkan ruang untuk menjadi satu kolom ke kiri sementara .?memungkinkan ruang untuk menjadi salah satu kolom di sebelah kanan.

Retina , 40 byte

~0L$`.(.*)¶
+s`(\S)(.{$.1,$.&}) ¶ $$2$$1

Cobalah online! Port jawaban JavaScript saya. Tahap 0L$atom mengambil input dan mengganti dua panjang ke baris kedua menghasilkan perintah yang benar-benar melakukan penggantian, yang kemudian dievaluasi pada input asli oleh ~tahap senyawa.

Neil
sumber
Ini adalah algoritma yang hebat! Anda dapat menggantinya \ndengan baris baru literal untuk menurunkannya menjadi dua digit ;-)
ETHproduk
Juga, saya pikir Anda bisa l=s.search`\n` menghemat beberapa byte.
ETHproduksi
tio.run/##ZY/… 86 byte
DanielIndie
@DanielIndie f=Diperlukan untuk rekursi, tetapi masih menyelamatkan saya 2 byte, terima kasih!
Neil
Anda benar, maaf: P
DanielIndie
3

Python 2, 298 byte

a=input()
L=len(a);s=' '
a=[list(s*L+l.ljust(L+max(map(len,a))))for l in a]
t=1
while t:
 t=0
 for y in range(L-1):
  for x in range(len(a[y])):
   c=a[y][x];C=a[y+1][x-1:x+2]
   if s!=c and s in C:t=1;a[y][x]=s;a[y+1][[[x+1,x][C[1]==s],x-1][C[0]==s]]=c
for l in map(''.join,a):print l[L:].rstrip()

Mengambil input sebagai daftar string (satu per baris)

Contoh: Input:

['                 (__)',
'                 (oo)',
'           /------\/',
'          / |    ||',
'         *  /\---/\ ',
'            ~~   ~~',
'..."Have you mooed today?"...']

Keluaran:

              (
            -----/|-(o__
         //|~~\---~\|\/o))
..."Have*you/mooed~today?"...
TFeld
sumber
3

C, 252 byte

e=1,l,c,i,j,p,r,w,a[999];f(){while((i=getchar())>0)a[w++]=i,i<16?l++:0,l?0:c++;while(e)for(i=e=0;i<c;i++)for(j=l;j>=0;j--)e=(r=a[p=j*(c+1)+i]-32?a[r=p+c+1]-32?a[r=p+c]-32?a[r=p+c+2]-32?0:r:r:r:0)?l=a[p],a[p]=a[r],a[r]=l:e;for(i=0;i<w;)putchar(a[i++]);}

Kode tes tidak digabungkan:

#include <stdio.h>

e=1,l,c,i,j,p,r,w,a[999];
f()
{
    // counting lines and columns
    while ((i = getchar())>0)a[w++] = i, i<16 ? l++ : 0, l ? 0 : c++;
    // main shaking loop
    while (e) // repeat while collapsing
        for (i = e = 0; i < c; i++) // columns loop
            for (j = l; j >= 0; j--) // lines loop
                e = ( // remember that collapsing was
                     r = // find place to collapse
                         a[p = j*(c + 1) + i] - 32 ? // if not space
                             a[r = p + c + 1] - 32 ? // if char under the current is not a space
                                 a[r = p + c] - 32 ? // see one position left
                                    a[r = p + c + 2] - 32 ? 0 // then one position right
                                                          : r
                                    : r
                                 : r
                             : 0
                         ) ? // and if place was found
                           l=a[p],a[p]=a[r],a[r]=l // replace values in positions p and r
                           : e;
    //print resulting picture
    for(i=0;i<w;)putchar(a[i++]);
}

int main(void)
{
    int cnt;
    FILE * testf = fopen("caw.txt","w");
    char testd[][31] = {
        "                 (__)        \n",
        "                 (oo)        \n", 
        "           /------\\/         \n", 
        "          / |    ||          \n", 
        "         *  /\\---/\\          \n", 
        "            ~~   ~~          \n", 
        "...\"Have you mooed today ? \"...",
        "" };
    // prepare data for test
    printf("Initial data:\n");
    for(cnt = 0; cnt < 7; cnt++)
    {
        printf("%s", testd[cnt]);
        fprintf(testf, testd[cnt]);
    }
    fclose(testf);
    // redirect standard input
    freopen("caw.txt", "r", stdin);
    printf("\n\nResult:\n");
    // start test
    f();
}

Hasil tes:

masukkan deskripsi gambar di sini

VolAnd
sumber
2

Algodoo (tidak bersaing)

Input - contoh degenerasi yang digunakan.

Mempersiapkan

Runnning - gravitasi default dan memantul.

Lari

Keluaran - akurasi dapat disesuaikan melalui pengaturan Gesekan dan Kepadatan pada objek.

Keluaran

Algodoo adalah programmable yang logis .

wyldstallyns
sumber
Mengapa ini tidak bersaing? Non-bersaing umumnya disediakan untuk jawaban dalam bahasa yang lebih baru daripada tantangan.
Ad Hoc Garf Hunter
Meskipun Algodoo dapat melakukan logika nyata, simulasi ini setara dengan menjatuhkan print-out merobek-robek input di lantai dan mengambil gambarnya. Saya tidak yakin bagaimana menangkap output itu secara terprogram.
wyldstallyns
Dan sepertinya salah mengatakan "program nol byte! Saya menang!"
wyldstallyns
Saya menduga bahwa ini sebenarnya bukan jawaban nol byte. Anda berbicara tentang pengaturan tweaker yang tampaknya setara dengan menulis kode. Mungkin ide yang bagus untuk membuka pertanyaan meta tentang mencetak Algodoo. Saya juga tidak berpikir ada yang salah dengan memiliki program nol byte.
Ad Hoc Garf Hunter
Saya akan membuka meta itu.
wyldstallyns
1

JavaScript, 286 byte

b=>eval('f=b=>b==null||" "==b;b=b.split`\n`.map(b=>[...b]);a:for(;;){for(c=0;c<b.length-1;c++)for(g=b[c],d=0;d<g.length;d++){h=g[d];if(!f(h)){e=0;f(b[c+1][d])?e=2:f(b[c+1][d-1])?e=1:f(b[c+1][d+1])&&(e=3);if(e){b[c+1][d+e-2]=h;b[c][d]=" ";continue a}}}break}b.map(b=>b.join``).join`\n`')

Contohnya

// Here I assume that you've assigned the above function to `fall`
console.log(fall(`
                 (__)
                 (oo)
           /------\/
          / |    ||
         *  /\---/\\
            ~~   ~~
..."Have you mooed today?"...`))

Keluaran:

                -       
            /--(-\--(__  
          /|~~---/~||/oo))
..."Have*you/mooed~today?"...

Contoh lain:

console.log(fall(`
 (\__/)  .~    ~. ))
 /O O  ./      .'
{O__,   \    {
  / .  . )    \\
  |-| '-' \    }
 .(   _(   )_.'
'---.~_ _ _&`))

Keluaran:

    _ , /            
  OO/__'_.. .         
 {.(|-|.(O'))/.~{      
/('---.~___-_&)_.'}\~.'))

Fungsi tidak disatukan

function fall(input) {
  let move = true
  let lines = input.split("\n").map(line => line.split(""))
  let isSpace = c => c == null || c == " "
  loop: for (;;) {
    for (let y = 0; y < lines.length - 1; y++) {
      let line = lines[y]
      for (let x = 0; x < line.length; x++) {
        let ch = line[x]
        if (!isSpace(ch)) {
          let dx = 0
          if (isSpace(lines[y+1][x])) { dx = 2 }
          else if (isSpace(lines[y+1][x-1])) { dx = 1 }
          else if (isSpace(lines[y+1][x+1])) { dx = 3 }
          if (dx) {
            lines[y + 1][x + dx - 2] = ch
            lines[y][x] = " "
            continue loop
          }
        }
      }
    }
    break
  }
  return lines.map(line => line.join("")).join("\n")
}
Florent
sumber
Sebuah cara singkat untuk menguji karena tidak kosong adalah c>" "di mana cmewakili karakter Anda menguji.
Neil