Wypełnianie dowolnych tac kostek lodu

27

Załóżmy, że ta siatka przestrzeni i Xreprezentuje przekrój niektórych dziwnie ukształtowanych pustych tac kostek lodu :

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

Kolumny bez Xprzedstawiają dziury lub luki w tacach, które nie mogą pomieścić wody, spływając do nieskończonej pojemności. Woda spadająca z lewej lub prawej krawędzi kratki również trafia do tego niekończącego się zlewu.

Gdybyśmy umieścili kran nad tacami i pozwolili im napełnić się wodą, aż poziom wody we wszystkich przedziałach pozostanie stabilny, dokładne przedziały, które zostaną wypełnione, będą zależeć dokładnie od tego, gdzie strumień wody został umieszczony nad tacami. (Załóżmy, że cienki, stały strumień wody nie rozpryskuje się.)


Na przykład, jeśli nasz kran znajduje się Fpowyżej bardzo lewej kolumny siatki

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

woda spadałaby do najwyższego poziomu Xw tej kolumnie i rozprzestrzeniałaby się w lewo i prawo, lewa połowa rozlewała się do zlewu poniżej, a prawa połowa wypełniałaby komorę 2 × 1. Gdy komora się zapełni, prawa połowa strumienia wody nie ma już przepływu, ale do zlewu, a poziom wody wszędzie jest zasadniczo stabilny.

Po wyłączeniu kranu taca wygląda teraz tak: (z ~wodą)

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

Podobnie, jeśli umieścimy kran w ten sposób:

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

Wypełni dwa skrajne lewe przedziały, ale reszta wody odpłynie:

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

Jeśli ustawimy kran w ten sposób:

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

Lewa połowa strumienia wpłynie do zlewu, ale prawa połowa ostatecznie wypełni trzy przedziały po prawej stronie, ponieważ nie ma ograniczeń co do odległości, jaką woda może przepłynąć poziomo na płaskiej powierzchni:

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

Ustawiono jednak tak:

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

Cała woda odpływa i żadne przedziały nie są wypełnione:

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

Wyzwanie

Napisz program lub funkcję, która przyjmuje prostokątną siatkę odstępów X, i jeden F. Górny rząd zawsze będzie zawierał, Fa poza tym tylko spacje. W X„e w każdej kolumnie (jeśli istnieją) będzie rozciągać się w linii ciągłej w górę od podstawy kraty, to znaczy nie będzie jaskiniach nawisy.

Wydrukuj lub zwróć siatkę po Fnapełnieniu kranu wodą, ~tak jak to opisano powyżej. Pozostaw górny Fwiersz poza wyjściem.

  • Siatka poza rzędem kranów będzie wynosić co najmniej 1 × 1

    F
    X
    

    to najmniejsze wejście, które potrzebujesz wesprzeć.

  • Dane wejściowe pojawią się jako pełny prostokąt tekstowy. Wiodące i końcowe spacje mają znaczenie na wejściu i wyjściu. np. wejście

        F     
      X  X    
      XXXX    
    

    powinno skutkować

      X~~X    
      XXXX    
    

    (zwróć uwagę na spacje wiodące i końcowe)

  • Posiadanie pojedynczej nowej linii na wejściu lub wyjściu jest w porządku.

  • Można używać cztery odrębne druku ASCII znaków zamiast przestrzeni, X, F, ~.

Najkrótszy kod w bajtach wygrywa.


Duży przykład:

Wkład:

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

Wydajność:

              X~~~~~~~~~~~~~X                     
              X~~~~~~~~~~~~~X~X                   
X~~~~~~~~~~~~XXX~~~~~~~X~~~~X~X~~~~~~~~~~~X    X  
X~~~X~~~~~XXXXXXX~~~~~~X~~~~XXX~~~~~XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX
Hobby Calvina
źródło
O tak, świetna okazja dla mnie, aby użyć mojego ukochanego zip()<3
cjfaure
2
To wymaga odpowiedzi: / Popracuję nad tym.
TheNumberOne
Stworzenie automatu komórkowego, który to symuluje, jest stosunkowo łatwe, ale nie mogę wymyślić, jak to się skończy.
DanTheMan
Nadal nikt nie konkuruje? Takie słodkie wyzwanie. Wygląda na to, że będę musiał pokonać siebie :)
Jakuje

Odpowiedzi:

1

perl -p0, 204 + 2 bajty

POMYSŁ

  • Jeśli obie strony wyspy poniżej F są jednakowej wysokości, należy wymienić wszystkie X *Xes z X~*Xes na tej wyspie.
  • Jeśli jedna strona jest wyższa, zastąp wszystkie X *Xes X~*Xes pomiędzy odpływem na dolnej stronie i punktem najbliższym F, który jest wyższy niż góra dolnej strony.

Teren bezpośrednio poniżej F liczy się tutaj jako część obu stron.

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

UWAGI

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
'

Może być trudno rozpoznać oryginalny algorytm w tej implementacji, ponieważ Perl nie obsługuje wyszukiwań o zmiennej długości.

bopjesvla
źródło
6

Lua 5.2, 581 bajtów

Znowu powolny start z tak nieskutecznym językiem gry w golfa i nieefektywnym algorytmem. Ale poprawię :)

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

Przypadki testowe (ze źródłem wody):

---------
    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

z bash można przetestować w ten sposób, ale nie wygląda to tak ładnie:

$ echo "    F     
  X  X    
  XXXX   " | lua f.lua
Jakuje
źródło
Skorzystaj z dokumentów tutaj, aby przetestować to łatwiej! Tak .
ravron
1

JavaScript, 460 bajtów

Demo online (w konsoli, przetestowane w obecnych Chrome i Firefox).

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(""))}

Stawianie sobie wyzwań nie jest tak zabawne, ale wciąż możliwe. Ten sam algorytm co Lua, teraz w javascript.

Jakuje
źródło