Mengisi Baki Es Batu Sewenang-wenang

27

Misalkan kisi ruang ini dan Xmewakili penampang beberapa nampan es batu berbentuk aneh :

   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Kolom tanpa Xmewakili lubang atau celah di baki yang tidak dapat menampung air, mengalir ke wastafel kapasitas tak terbatas. Air yang jatuh dari ujung paling kiri atau paling kanan dari kotak masuk ke bak cuci tanpa akhir ini juga.

Jika kita menempatkan keran di atas nampan dan membiarkannya terisi dengan air sampai permukaan air di semua kompartemen tetap stabil, kompartemen yang tepat yang menjadi terisi akan bergantung pada tempat aliran air diposisikan di atas nampan. (Asumsikan aliran air tipis dan stabil tanpa percikan.)


Misalnya, jika faucet kami Fberada di atas kolom grid paling kiri

F                   
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

air akan jatuh ke bagian paling atas Xdi kolom itu dan menyebar ke kiri dan kanan, separuh kiri tumpah ke wastafel di bawah, dan separuh kanan mengisi kompartemen 2 × 1. Setelah kompartemen terisi, bagian kanan aliran air tidak memiliki tempat untuk mengalir tetapi ke bak cuci dan permukaan air di mana-mana pada dasarnya stabil.

Mematikan faucet, baki sekarang terlihat seperti ini: (dengan ~air)

   X     X X        
X~~X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Demikian pula jika kita memposisikan faucet seperti ini:

   F                
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Ini akan mengisi dua kompartemen paling kiri tetapi sisa air akan mengalir:

   X     X X        
X~~X~X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Jika kita memposisikan faucet seperti ini:

         F          
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Setengah bagian kiri aliran akan mengalir ke bak cuci tetapi bagian kanan akhirnya akan mengisi tiga kompartemen paling kanan karena tidak ada batasan seberapa jauh air dapat berjalan secara horizontal di permukaan yang datar:

   X     X~X        
X  X X  XX~X~~XX~~~X
XXXXXX XXXXXXXXXXXXX

Diposisikan seperti ini, namun:

        F           
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Semua air mengalir dan tidak ada kompartemen yang terisi:

   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

Tantangan

Tulis program atau fungsi yang menggunakan kotak spasi persegi panjang X, satu, dan satu F. Baris atas akan selalu Fberisi spasi dan sebaliknya hanya berisi spasi. Tanda X's di setiap kolom (jika ada) akan membentang dalam garis yang solid di atas dasar kisi, yaitu tidak akan ada gua atau gubuk.

Cetak atau kembalikan kisi-kisi setelah faucet Fmengisi apa yang bisa dengan air ~seperti dijelaskan di atas. Biarkan Fbaris atas dari output.

  • Grid selain dari baris faucet akan minimal 1 × 1 jadi

    F
    X
    

    adalah input terkecil yang Anda butuhkan untuk mendukung.

  • Input akan muncul sebagai kotak teks lengkap. Ruang-ruang terkemuka dan tertinggal sangat penting dalam input dan output. misal input

        F     
      X  X    
      XXXX    
    

    harus menghasilkan

      X~~X    
      XXXX    
    

    (perhatikan ruang depan dan belakang)

  • Memiliki satu trailing newline di input atau output baik-baik saja.

  • Anda dapat menggunakan empat yang berbeda ASCII printable karakter di tempat ruang, X, F, ~.

Kode terpendek dalam byte menang.


Contoh Besar:

Memasukkan:

                F                                 
              X             X                     
              X             X X                   
X            XXX       X    X X           X    X  
X   X     XXXXXXX      X    XXX     XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX

Keluaran:

              X~~~~~~~~~~~~~X                     
              X~~~~~~~~~~~~~X~X                   
X~~~~~~~~~~~~XXX~~~~~~~X~~~~X~X~~~~~~~~~~~X    X  
X~~~X~~~~~XXXXXXX~~~~~~X~~~~XXX~~~~~XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX
Hobi Calvin
sumber
Oh ya, kesempatan bagus bagi saya untuk menggunakan kekasihku zip()<3
cjfaure
2
Ini perlu jawaban: / Saya akan mengerjakannya.
TheNumberOne
Relatif mudah untuk membuat otomat seluler yang mensimulasikan ini, tetapi saya tidak dapat memikirkan cara untuk mengakhirinya.
DanTheMan
masih ada yang bersaing? Tantangan yang sangat lucu. Sepertinya saya harus mengalahkan diri sendiri :)
Jakuje
terlihat seperti duplikat dari ini: codegolf.stackexchange.com/questions/2563/fill-in-the-lakes
12Me21

Jawaban:

1

perl -p0, 204 + 2 byte

IDE

  • Jika kedua sisi pulau di bawah F memiliki ketinggian yang sama, ganti semua X *Xes dengan X~*Xes di pulau itu.
  • Jika satu sisi lebih tinggi, ganti semua X *Xes dengan X~*Xselokan di sisi bawah dan titik terdekat dengan F yang lebih tinggi dari atas sisi bawah.

Tanah tepat di bawah F dihitung sebagai bagian dari kedua belah pihak di sini.

GOLF

s/.*(F).*
//;$f=@-[1];($%,$r)=map{y///c}/(.{0,$f})\bX+?\b(.*)$/;($a,$b)=map{y///c}/[^~]*^(?(?=(.{$%,$f}X)).{$f} *|.{$f} *X(.*)).{$r}
/m;$a=$%if!$a||$b;$b+=$r;s/(?<=.{$a})\b *\b(?=.{$b})/"~"x length($&)/ge

CATATAN

perl -p0e ' # slurp stdin, print the result

s/.*(F).*\n//; # remove the first line, record the index of F
$f=@-[1]; # get the index of F

($l,$r)=map{length}m/(.{0,$f})\bX+?\b(.*)$/;
# gets the distance from either side to the drains closest to F
($a,$b)=map{length}m/[^~]*^(?(?=(.{$l,$f}X)).{$f} *|.{$f} *X(.*)).{$r}\n/m;
# tries to find the lowest line that has at least one X on
# one side of the island, but none on the other
$a=$l if !$a||$b;
$b+=$r; # use the captured groups to calculate the left and right bounds
s/(?<=.{$a})\b *\b(?=.{$b})/"~" x length($&)/ge;
# replace all pools within those bounds
'

Mungkin sulit untuk mengenali algoritma asli dalam implementasi ini karena Perl tidak mendukung tampilan yang terlihat dari panjang variabel.

bopjesvla
sumber
6

Lua 5.2, 581 Bytes

Sekali lagi, mulai lambat dengan bahasa yang tidak efektif untuk bermain golf dan dengan algoritma yang tidak efektif. Tapi saya akan meningkatkan :)

r=io.read w=io.write F=r()f=F:find("F")o={[1]=F}W=#F i=2 
repeat s=r()if s==nil then break end o[i]={}for j=1,W do o[i][j]=s:sub(j,j)end i=i+1 until false
function e(i,j)
local k,l,b,c=j+1,j-1,false
if i>=#o or(o[i+1][j]==" "and e(i+1,j)==0)then return 0 end
while k<=W do
b=b or o[i][k]=="X"
if b or(o[i+1][k]==" "and e(i+1,k)==0)then break end
k=k+1 end
while l>0 do
c=c or o[i][l]=="X"
if c or(o[i+1][l]==" "and e(i+1,l)==0)then break end
l=l-1 end
if b and c then for m=l+1,k-1 do o[i][m]="~"end return 1 end
return 0 end
e(1,f)for i=2,#o do for j=1,W do w(o[i][j])end w"\n"end

Test case (dengan sumber air):

---------
    F    
  X~~X   
  XXXX   
--------------------
         F          
   X     X~X        
X  X X  XX~X~~XX~~~X
XXXXXX XXXXXXXXXXXXX
--------------------
   F                
   X     X X        
X~~X~X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX
--------------------------------------------------
                F                                 
              X~~~~~~~~~~~~~X                     
              X~~~~~~~~~~~~~X~X                   
X~~~~~~~~~~~~XXX~~~~~~~X~~~~X~X~~~~~~~~~~~X    X  
X~~~X~~~~~XXXXXXX~~~~~~X~~~~XXX~~~~~XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX

dari bash dimungkinkan untuk menguji dengan cara ini, tetapi tidak terlihat bagus:

$ echo "    F     
  X  X    
  XXXX   " | lua f.lua
Jakuje
sumber
Gunakan di sini-dokumen untuk mengujinya lebih mudah! Seperti ini .
ravron
1

Javascript, 460 Bytes

Demo online (di konsol, diuji di Chrome dan Firefox saat ini).

function e(i,j){var k=j+1,l=j-1,b=0,c=0,I=i+1
if(i>(O-2)||(o[I][j]==" "&&e(I,j)==0))return 0
while(k<W){b=b||(o[i][k]=="X")
if(b||(o[I][k]==" "&&e(I,k)==0))break
k++}while(l>=0){c=c||(o[i][l]=="X")
if(c||(o[I][l]==" "&&e(I,l)==0))break
l--}if(b&&c){for(m=l+1;m<k;m++)o[i][m]="~"
return 1}return 0}function f(d){o=d.split("\n")
F=o[0];s=F.indexOf("F");W=F.length;O=o.length
for(i=0;i<O;i++)o[i]=o[i].split("")
e(0,s);for(i=1;i<O;i++)console.log(o[i].join(""))}

Menantang diri sendiri tidak begitu menyenangkan, tetapi masih memungkinkan. Algoritma yang sama dengan Lua, sekarang dalam javascript.

Jakuje
sumber