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

27

Предположим, что эта сетка пространств и Xs представляет поперечное сечение некоторых странных форм пустых лотков для кубиков льда :

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

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

Если бы мы поместили кран над тарелками и позволили им наполняться водой до тех пор, пока уровень воды во всех отсеках не станет стабильным, точные отсеки, которые будут заполнены, будут зависеть от того, где именно поток воды был расположен над тарелками. (Предположим, тонкий, устойчивый поток воды без брызг.)


Например, если наш кран 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

Вызов

Напишите программу или функцию, которая принимает прямоугольную сетку из пробелов Xи единиц 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 байта

IDEA

  • Если обе стороны острова ниже F имеют одинаковую высоту, замените все X *Xes на X~*Xes на этом острове.
  • Если одна сторона выше, замените все 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 не поддерживает вид сзади переменной длины.

bopjesvla
источник
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
Jakuje
источник
Используйте здесь документы, чтобы проверить это проще! Как это .
Раврон
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.

Jakuje
источник