Прогнозуйте падаючі скелі


18

У цьому виклику вам надається карта двовимірної місцевості, розглянута збоку. На жаль, деякі частини місцевості плавають у повітрі, а значить, вони зійдуть вниз. Ваше завдання - передбачити, де вони приземляться.

Вхідні дані

Ваш вхід - це одна або кілька рядків, розділених новою лінією однакової довжини, що містять лише символи #(знак числа, що позначає скелю) або .(крапка, що означає порожній пробіл).

Вихід

Ваш вихід має той же формат, що і вхідний, але з наступною модифікацією. Розглянемо вхідний рядок як двовимірну сітку гірських порід. Кожна скеля на вході, яка з'єднана з дном сітки шляхом до сусідніх гірських порід, є твердою ; інші породи пухкі . Діагонально сусідні породи не вважаються суміжними. Всі пухкі скелі впадуть прямо вниз і закінчуються як стопка зверху або твердої скелі, або нижнього ряду. Сипучі скелі не прикріплені один до одного, тому вони падають окремо, не як великі утворення. Вихід - отримана сітка.

Приклади

  • Вхід

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

    не містить пухких гірських порід, тому вихід його ідентичний.

  • Вхід

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

    містить одну пухку скелю вгорі, яка падає на тверду скелю під нею. Вихід є

    ......
    .#..#.
    .#..##
    .#.#.#
    .#####
    .#...#
    
  • Вхід

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

    має велику групу пухких скель зліва. Група розпадається, коли гірські породи падають, тому вихід є

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

Роз'яснення

  • Ви можете або взяти вхід зі STDIN і вивести в STDOUT, або записати функцію.
  • Це код-гольф, тому найкоротша програма (в байтах) є переможцем.
  • Стандартні лазівки заборонені.

Відповіді:


12

CJam, 180 ... 133 101 ... 94 90 87 байт

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

Однозначно можливо багато гольфу, але я хотів опублікувати його першим після того, як він повністю запрацював.

Подивися ма! Немає смуг прокрутки!

Знімає сітку гірських порід (складену .і #без кінцевої нової лінії ) зі STDIN і друкує вихід на STDOUT

ОНОВЛЕННЯ : Використовуючи неефективну, але коротшу часткову заливку, щоб розкрити міцні породи.

ОНОВЛЕННЯ 2 : Змінено алгоритм змушення гірських порід. Набагато коротше зараз!

ОНОВЛЕННЯ 3 : Зробив кілька невеликих оптимізацій, і врешті-решт я зміг звести кількість байтів до половини початкового коду!

Як це працює :

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

Для заливки ми повторюємо по всій довжині сітки (сітці) разів. У кожній ітерації ми гарантуємо перетворення щонайменше 1, #який безпосередньо стосується пробілу (пробіл). Простір тут являє собою міцну рок-групу. Таким чином, в кінці довжини (сітчасті) ітерації ми гарантуємо, що всі тверді породи представлені пробілами.

Спробуйте його онлайн тут


15

Перл 5: 98

98, включаючи 2 прапори командного рядка.

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

Пояснення:

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

@Optimizer Я покладаюсь на те, що фінальний рядок введення буде закінчено належним чином див.: Ideone.com/7E3gQh Без цього опору це був би один ледаря (або один коротший посилання на протилежне - відсутність остаточного EOL).
nutki

1
Побиття CJam майже на 30%? Дивовижний. Вітаю тебе.
DLosc

@DLosc Більше не: P
Оптимізатор

Побиття інших імперативних мов на 100-300%? Дивовижний. Вітаю тебе. ;)
DLosc

@DLosc Дивлячись на вищевказану відповідь, я більше не включатиму Perl до списку загальнообов’язкових мов: 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)}

Як функція з параметром рядка і поверненням рядка.

Спочатку додайте нижній ряд "1", щоб визначити лінію землі.
Перший цикл здійснює пошук нерухомих гірських порід (які знаходяться поблизу '1') і позначає їх як "1". Пошук повторюється, поки не знайдеться більш твердих порід.
Другий цикл перемістіть залишилися символи "#" до нижнього ряду. Знову ж таки, це повторюється, поки жодна скеля не може бути переміщена.
Нарешті, знову замініть "1" на "#" і виріжте нижній ряд.

Менше гольфу

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

Тест (Ви можете мати докази того, які породи міцні, а які впали)

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


3

АПЛ, 130 119

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

Оскільки неможливо (наскільки я знаю) вводити нові рядки, коли буде запропоновано введення, ця програма приймає символьну матрицю як вхід.

Використовуваний алгоритм спочатку перетворюється на двійкову матрицю ( 0є повітряною та 1скельною), а потім заповнює заливку з нижнього ряду, щоб позначити тверді породи як 2. Потім розділіть кожен стовпчик на «проміжки між твердими породами» і сортуйте кожну перегородку, щоб сипуча скеля «провалилася» повітря.

Edit1: Деякі гольфи використовували інший алгоритм заливки


Тестові прогони

Виконати 1

Визначте матрицю символів Aта роздрукуйте її:

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

Потім подайте Aв програму:

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

Виконати 2

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

2

JS - 443 байт

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,"#")};

Повінь заповнює скелі з дна, потім збиває незатоплені скелі вниз. Використовує багато рекурсії із заливкою, що може затримати ваш браузер на трохи.

Це функція - називайте її за допомогою g("input")

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

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


1

Пітон 3, 364 байти

Я впевнений, що з цього може бути витіснено більше ... але це все одно ніколи не буде конкурувати з CJam і 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,"#")

Подібно до інших відповідей. Одна химерність полягає в тому, що вона спочатку перевертає сітку догори дном (щоб зробити індекси циклу більш зручними) і додає додатковий рядок і стовпець .(щоб уникнути проблем із загортанням -1індексів). Запустити по телефону P(string).

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