Prediksi Falling Rocks

18

Dalam tantangan ini, Anda diberikan peta medan dua dimensi, dilihat dari samping. Sayangnya, beberapa bagian dari medan mengambang di udara, yang berarti mereka akan runtuh. Tugas Anda adalah memprediksi di mana mereka mendarat.

Input

Input Anda adalah satu atau lebih string yang dipisahkan baris baru dengan panjang yang sama, hanya berisi karakter #(tanda angka, menandakan batu) atau .(periode, menandakan ruang kosong).

Hasil

Output Anda memiliki format yang sama dengan input, tetapi dengan modifikasi berikut. Mari kita lihat string input sebagai kisi batuan dua dimensi. Setiap batu di input yang terhubung ke bagian bawah grid oleh jalur batuan yang berdekatan adalah tegas ; batu lainnya longgar . Batuan yang berdekatan secara diagonal tidak dianggap berdekatan. Semua batu lepas akan jatuh lurus ke bawah, dan berakhir sebagai tumpukan di atas batu yang kokoh atau baris bawah. Batuan lepas tidak saling menempel, sehingga jatuh secara individual, bukan sebagai bentukan besar. Outputnya adalah grid yang dihasilkan.

Contohnya

  • Input

    ..###.
    .##.#.
    .#....
    .##.#.
    

    tidak mengandung batu lepas, sehingga hasilnya identik dengan itu.

  • Input

    ...#..
    .#..#.
    .#..##
    .#...#
    .#####
    .#...#
    

    berisi satu batu lepas di bagian atas, yang jatuh di atas batu perusahaan di bawahnya. Outputnya adalah

    ......
    .#..#.
    .#..##
    .#.#.#
    .#####
    .#...#
    
  • Input

    .#####....
    .#....####
    ###.###..#
    #.#...##..
    .####..#.#
    ......###.
    ..#...#..#
    ..#...#..#
    

    memiliki sekelompok besar batuan lepas di sebelah kiri. Kelompok itu rusak ketika batu-batu itu jatuh, demikian juga hasilnya

    ..........
    ....######
    ..#.###..#
    . #...##..
    .##....#..
    .##...####
    ####..#..#
    #####.#..#
    

Klarifikasi

  • Anda dapat mengambil input dari STDIN dan output ke STDOUT, atau menulis fungsi.
  • Ini adalah kode-golf, jadi program terpendek (dalam byte) adalah pemenangnya.
  • Celah standar tidak diijinkan.
Zgarb
sumber

Jawaban:

12

CJam, 180 ... 133 101 ... 94 90 87 byte

qN/~'#/S*_,):L;]N*_,_,*{:A1$='#={[W1LL~)]Af+{W>},1$f=S&,{ASct}*}*}/N/z{S/{$W%}%'#*}%zN*

Pasti ada banyak golf yang mungkin, tetapi saya ingin mempostingnya terlebih dahulu setelah membuatnya berfungsi sepenuhnya.

Lihat bu! Tidak ada scrollbar!

Mengambil kisi-kisi batu (terdiri dari .dan #tanpa baris baru) dari STDIN dan mencetak hasilnya ke STDOUT

PEMBARUAN : Menggunakan pengisian banjir parsial yang tidak efisien tetapi lebih pendek untuk mengetahui batu yang kokoh.

UPDATE 2 : Mengubah algoritma untuk membuat batu jatuh. Jauh lebih pendek sekarang!

UPDATE 3 : Melakukan beberapa optimasi kecil dan pada akhirnya saya dapat menurunkan jumlah byte menjadi setengah dari kode asli!

Cara kerjanya :

qN/~'#/S*_,):L;]N*             "Preparations";
qN/~                           "Read the input, split by new line and expand the array";
    '#/S*                      "In the last row, replace # by space";
         _,):L                 "Copy the last row and store length + 1 in L";
              ;]N*             "Pop the length, wrap everything in array and join by \n";

_,_,*{ ... }/                  "Flood fill";
_,                             "Copy the array and calculate its length";
  _,                           "Copy the length and calculate [0 - length] array";
    *                          "Repeat the above array, length times";
     { ... }/                  "Run the code block on each element of the array";

:A1$='#={ ... }*               "Process only #";
:A1$                           "Store the number in A and copy the input array to stack";
    =                          "Get Ath index element from input array";
     '#={ ... }*               "Run the code block if Ath element equals #";

[W1LL~)]Af+{W>},1$f=S&,{ASct}* "Flood fill spaces";
[W1LL~)]Af+                    "Get the indexes of the 4 elements on the cross formed by"
                               "the Ath index";
           {W>},               "Filter out the negative values";
                1$f=           "For each of the index, get the char from input string";
                    S&,        "Check if space is one of the 4 chars from above step";
                       {    }* "Run the code block if space is present";
                        ASct   "Make the Ath character of input string as space";

N/z{S/{$W%}%'#*}%zN*           "Let the rocks fall";
N/z                            "Split the resultant string by newlines and"
                               "transpose the matrix";
   {           }%              "Run the code block for each row (column of original)";
    S/{   }%                   "Split by space and run the code block for each part";
       $W%                     "Sort and reverse. This makes # come down and . to go up";
            '#*                "Join by 3, effectively replacing back spaces with #";
                 zN*           "Transpose to get back final matrix and join by newline";

Untuk penimbunan banjir, kami mengulangi seluruh panjang grid (grid) kali. Dalam setiap iterasi, kami dijamin untuk mengkonversi setidaknya 1 #yang secara langsung menyentuh spasi ke (spasi). Ruang di sini mewakili grup rock yang kuat. Dengan demikian, pada iterasi panjang (kisi-kisi), kami dijamin memiliki semua batuan keras yang diwakili oleh spasi.

Cobalah online di sini

Pengoptimal
sumber
15

Perl 5: 98

98 termasuk 2 flag baris perintah.

#!perl -p0
1while/
/,($x="($`)")=~y!#!.!,s/#(.*
$)/%$1/+s/#$x?%|%$x?#/%$1$2%/s;1while s/#$x\./.$1#/s;y!%!#!

Penjelasan:

#!perl -p0 #read entire input to $_ and print at the end
/\n/;($x="($`)")=~y!#!.!; #calculate pattern matching space
                          #between two characters in the same column
                          #looks like "(......)" 
1 while s/#(.*\n$)/%$1/+s/#$x?%|%$x?#/%$1$2%/s;
                          #flood fill solid rock with %
1 while s/#$x\./.$1#/s;   #drop loose rock
y!%!#!                    #change % back to #
nutki
sumber
@Optimizer Saya bergantung pada baris input terakhir yang diselesaikan dengan benar, lihat: ideone.com/7E3gQh Tanpa ketergantungan ini akan menjadi satu karakter penyendiri (atau lebih pendek bergantung pada yang berlawanan - kurangnya EOL akhir).
nutki
1
Mengalahkan CJam hampir 30%? Luar biasa. Saya mengucapkan selamat kepada Anda.
DLosc
@DLosc Tidak lagi: P
Pengoptimal
Mengalahkan bahasa imperatif lainnya hingga 100-300%? Luar biasa. Saya mengucapkan selamat kepada Anda. ;)
DLosc
@DLosc Melihat jawaban di atas, saya tidak akan memasukkan Perl dalam daftar bahasa imperatif lagi: P
Optimizer
5

JavaScript (ES6) 232

s=>{for(s=[...s+'1'.repeat(r=1+s.search('\n'))];s=s.map((c,p)=>c=='#'&(s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f;);for(;s.map((c,p)=>c=='#'&s[p+r]=='.'&&(s[p]='.',f=s[p+r]=c),f=0),f;);return s.join('').replace(/1/g,rok).slice(0,-r)}

Sebagai fungsi dengan parameter string dan mengembalikan string.

Pada awalnya, tambahkan baris bawah '1' untuk mengidentifikasi garis tanah.
Pencarian lingkaran pertama untuk batuan tetap (yang berada di dekat '1') dan menandainya sebagai '1' juga. Pencarian diulang sampai tidak ada lagi batuan keras yang ditemukan.
Loop kedua memindahkan karakter '#' yang tersisa ke baris bawah. Sekali lagi, ini diulang sampai tidak ada batu yang bisa dipindahkan.
Akhirnya, ganti '1' dengan '#' lagi dan potong baris bawah.

Kurang golf

s=>{
  r = 1+s.search('\n');
  s = [...s+'1'.repeat(r)];
  for (; s = s.map((c,p) => c=='#' & (s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f; );
  for (; s.map((c,p) => c=='#' & s[p+r]=='.'&& (s[p] ='.', s[p+r]=c, f=1),f=0),f; );
  return s.join('')
    .replace(/1/g,'#')
    .slice(0,-r)
}

Uji (Anda dapat memiliki bukti batu apa yang keras dan apa yang telah jatuh)

F=
s=>{for(s=[...s+'1'.repeat(r=1+s.search('\n'))];s=s.map((c,p)=>c=='#'&(s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f;);for(;s.map((c,p)=>c=='#'&s[p+r]=='.'&&(s[p]='.',f=s[p+r]=c),f=0),f;);return s.join('').replace(/1/g,rok).slice(0,-r)}

var rok // using rok that is 3 chars like '#'

function update() {
  rok = C.checked ? '@' : '#';
  O.textContent=F(I.textContent)
}

update()
td { padding: 5px }
pre { border: 1px solid #000; margin:0 }
<table><tr><td>Input</td><td>Output</td></tr>
<tr><td><pre id=I>.#####....
.#....####
###.###..#
#.#...##..
.####..#.#
......###.
..#...#..#
..#...#..#</pre></td>
<td><pre id=O></pre>
</td></tr></table>
<input type='checkbox' id=C oninput='update()'>Show firm rocks

edc65
sumber
3

APL, 130 119

'.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓ ⍉⊃⌈/(1,¨⍳⍴⊃↓x){x←⍵⋄(⍺⌷x)∧←2⋄x≡⍵:x⋄⊃⌈/((⊂⍴⍵)⌊¨1⌈(,∘-⍨↓∘.=⍨⍳2)+⊂⍺)∇¨⊂x}¨⊂⊖'#'=x←⎕]

Karena tidak mungkin (sejauh yang saya tahu) untuk memasukkan baris baru ketika input diminta, program ini mengambil matriks karakter sebagai input.

Algoritma yang digunakan adalah pertama mengkonversi ke matriks biner ( 0adalah udara dan 1batu) kemudian mengisi banjir dari baris bawah untuk menandai batuan perusahaan sebagai 2. Kemudian partisi setiap kolom menjadi "ruang di antara batu-batu yang kokoh" dan urutkan setiap partisi untuk membuat batu yang lepas "jatuh" ke udara.

Sunting1: Golf beberapa menggunakan algoritma mengisi banjir yang berbeda


Tes berjalan

Jalankan 1

Tentukan matriks karakter Adan cetak:

      A←↑('.#####....') ('.#....####') ('###.###..#') ('#.#...##..') ('.####..#.#') ('......###.') ('..#...#..#') ('..#...#..#')
      A
.#####....
.#....####
###.###..#
#.#...##..
.####..#.#
......###.
..#...#..#
..#...#..#

Kemudian beri makan Ake dalam program:

      '.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓⍉(1,¨⍳⊃⌽⍴x){⍵≡y←⊃⌈/x←⍺{x←⍵⋄(⍺⌷x)∧←2⋄x}¨⊂⍵:y⋄((⊂⍴⍵)⌊¨1⌈,(,∘-⍨↓∘.=⍨⍳2)∘.+⍺/⍨x≢¨⊂⍵)∇y}⊖'#'=x←⎕]
⎕:
      A
..........
....######
..#.###..#
..#...##..
.##....#..
.##...####
####..#..#
#####.#..#

Jalankan 2

      A←↑('#######')('#.....#')('#.#.#.#')('#.....#')('#######')
      A
#######
#.....#
#.#.#.#
#.....#
#######
      '.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓⍉(1,¨⍳⊃⌽⍴x){⍵≡y←⊃⌈/x←⍺{x←⍵⋄(⍺⌷x)∧←2⋄x}¨⊂⍵:y⋄((⊂⍴⍵)⌊¨1⌈,(,∘-⍨↓∘.=⍨⍳2)∘.+⍺/⍨x≢¨⊂⍵)∇y}⊖'#'=x←⎕]
⎕:
      A
#######
#.....#
#.....#
#.#.#.#
#######
TwiNight
sumber
2

JS - 443 byte

function g(b){function f(b,c,e){return b.substr(0,c)+e+b.substr(c+1)}function e(d,c){"#"==b[c][d]&&(b[c]=f(b[c],d,"F"),1<d&&e(d-1,c),d<w-1&&e(d+1,c),1<c&&e(d,c-1),c<h-1&&e(d,c+1))}b=b.split("\n");w=b[0].length;h=b.length;for(i=0;i<w;i++)"#"==b[h-1][i]&&e(i,h-1);for(j=h-2;-1<j;j--)for(i=0;i<w;i++)if(k=j+1,"#"==b[j][i]){for(;k<h&&"F"!=b[k][i]&&"#"!=b[k][i];)k++;k--;b[j]=f(b[j],i,".");b[k]=f(b[k],i,"#")}return b.join("\n").replace(/F/g,"#")};

Banjir mengisi batu dari bawah, lalu membawa batu yang tidak terisi banjir ke bawah. Menggunakan banyak rekursi dengan isi banjir sehingga dapat sedikit memperlambat browser Anda.

Ini sebuah fungsi - sebut saja dengan g("input")

JSFiddle: http://jsfiddle.net/mh66xge6/1/

JSFiddle Ungolfed: http://jsfiddle.net/mh66xge6/

DankMemes
sumber
1

Python 3, 364 byte

Saya yakin lebih banyak yang bisa diperas dari ini ... tapi itu tidak akan pernah bisa bersaing dengan CJam dan Perl.

z="%";R=range
def F(r,c,g):
 if z>g[r][c]:g[r][c]=z;[F(r+d%2*(d-2),c+(d%2-1)*(d-1),g)for d in R(4)]
def P(s):
 t=s.split()[::-1];w=len(t[0]);g=[list(r+".")for r in t+["."*w]];[F(0,c,g)for c in R(w)]
 for c in R(w):
  for r in R(len(g)):
   while g[r][c]<z<g[r-1][c]and r:g[r][c],g[r-1][c]=".#";r-=1
 return"\n".join(''.join(r[:w])for r in g[-2::-1]).replace(z,"#")

Mirip dengan jawaban lain. Satu kekhasan adalah bahwa itu membalikkan grid terbalik terlebih dahulu (untuk membuat indeks lingkaran lebih nyaman) dan menambahkan baris & kolom tambahan .(untuk menghindari masalah dengan -1indeks pembungkus ). Jalankan dengan menelepon P(string).

DLosc
sumber