Заповнення довільних лотків для кубиків льоду


27

Припустимо, ця сітка пробілів і Xs представляє поперечний переріз якихось дивовижних порожніх кубиків льоду :

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

Стовпці без X'являють собою отвори або проміжки в лотках, які не можуть утримувати воду, стікаючи в раковину безмежної ємності. Вода, що падає на крайній лівий або правий край сітки, потрапляє і в цю нескінченну раковину.

Якби ми розміщували кран над лотками і давали їм наповнюватись водою до тих пір, поки рівень води у всіх відділеннях не залишиться стабільним, точні відсіки, які заповнюються, залежатимуть від того, де саме розташувався потік води над лотками. (Припустимо, тоненький постійний потік води без бризок.)


Наприклад, якщо наш змішувач Fзнаходився над самою лівою колоною сітки

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

вода впала б у Xверхню частину цього стовпчика і поширилася ліворуч і праворуч, ліва половина розлилася в раковину внизу, а права половина заповнила відділення 2 × 1. Після того, як відсік заповниться, правій половині водного потоку нікуди не стікає, а в раковину, і рівень води скрізь є по суті стабільним.

Відключивши кран, лоток тепер виглядає так: (з ~водою)

   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

Він заповнить два крайні ліві відсіки, але решта води буде стікати:

   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

Ліва половина потоку буде надходити в раковину, але права половина врешті заповнить три найправіші відсіки, оскільки немає обмеження в тому, наскільки вода може ходити по горизонталі на рівній поверхні:

   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

Вся вода стікає і жодні відсіки не заповнюються:

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

Виклик

Напишіть програму або функцію, яка займає прямокутну сітку пробілів, Xs та one F. У верхньому рядку завжди буде Fрозміщено пробіли, а в іншому випадку - лише пробіли. У X«s в кожному стовпці (якщо такий є) буде проходити у вигляді суцільної лінії вгору від підстави решітки, тобто не будуть ніяких печер або звисів.

Роздрукуйте або поверніть сітку після того, як змішувач Fзаповнив воду, ~як описано вище. Залиште верхній Fряд із виводу.

  • Сітка крім ряду змішувача буде, як мінімум, 1 × 1

    F
    X
    

    - це найменший вхід, який потрібно підтримати.

  • Вхід вийде як повноцінний текстовий прямокутник. Провідні та кінцеві простори мають значення у вході та виході. наприклад вхід

        F     
      X  X    
      XXXX    
    

    має призвести до

      X~~X    
      XXXX    
    

    (зверніть увагу на провідні та кінцеві місця)

  • Добре мати єдиний трейлінг нового рядка на вході чи виході.

  • Ви можете використовувати будь-які чотири різних друкуються ASCII символів замість простору X, F, ~.

Виграє найкоротший код у байтах.


Великий приклад:

Вхід:

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

Вихід:

              X~~~~~~~~~~~~~X                     
              X~~~~~~~~~~~~~X~X                   
X~~~~~~~~~~~~XXX~~~~~~~X~~~~X~X~~~~~~~~~~~X    X  
X~~~X~~~~~XXXXXXX~~~~~~X~~~~XXX~~~~~XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX

О так, прекрасна можливість для мене використовувати мого коханого zip()<3
cjfaure

2
На це потрібна відповідь: / Я над цим працюю.
TheNumberOne

Робити стільниковий автомат, який імітує це, порівняно просто, але я не можу придумати спосіб його закінчення.
DanTheMan

все ще нікому не змагатись? Так милий виклик. Схоже, мені доведеться перемогти себе :)
Jakuje

виглядає як дублікат цього: codegolf.stackexchange.com/questions/2563/fill-in-the-lakes
12Me21

Відповіді:


1

perl -p0, 204 + 2 байти

ІДЕЯ

  • Якщо обидві сторони острова нижче F мають однакову висоту, замінити всі X *Xес з X~*Xес на цьому острові.
  • Якщо одна сторона вище, замініть всі X *Xes на X~*Xes між стоком на нижній стороні та точкою, найближчою до F, що вище, ніж нижня частина сторони.

Земля безпосередньо нижче F вважається частиною обох сторін тут.

ГОЛЬФ

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

ПРИМІТКИ

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
'

Можливо, буде важко розпізнати оригінальний алгоритм у цій реалізації, оскільки Perl не підтримує параметри змінної довжини.


6

Lua 5.2, 581 байт

Знову повільно почніть з настільки неефективної мови для гольфу та з неефективним алгоритмом. Але я вдосконалюся :)

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

Випробування (з джерелом води):

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

з bash можна перевірити так, але це виглядає не так добре:

$ echo "    F     
  X  X    
  XXXX   " | lua f.lua

Скористайтеся тут-документами для тестування цього! Як це .
ravron

1

Javascript, 460 байт

Демонстрація в Інтернеті (в консолі, протестована в поточних Chrome і 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(""))}

Кидати виклик собі не так весело, але все ж можливо. Той же алгоритм, що і Lua, тепер у JavaScript.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.