Predire le Falling Rocks


18

In questa sfida, ti viene data una mappa di un terreno bidimensionale, visto di lato. Sfortunatamente, alcune parti del terreno fluttuano nell'aria, il che significa che verranno a schiantarsi. Il tuo compito è prevedere dove atterrano.

L'ingresso

Il tuo input è una o più stringhe separate da newline di uguale lunghezza, contenenti solo i caratteri #(un segno numerico, che indica una roccia) o .(un punto, che indica uno spazio vuoto).

Il risultato

L'output ha lo stesso formato dell'input, ma con la seguente modifica. Vediamo la stringa di input come una griglia bidimensionale di rocce. Ogni roccia nell'ingresso che è collegata al fondo della griglia da un percorso di rocce adiacenti è ferma ; altre rocce sono sciolte . Le rocce adiacenti in diagonale non sono considerate adiacenti. Tutte le rocce sciolte cadranno diritte verso il basso e finiranno come una pila sopra una roccia ferma o la fila inferiore. Le rocce sciolte non sono attaccate l'una all'altra, quindi cadono individualmente, non come grandi formazioni. L'output è la griglia risultante.

Esempi

  • L'input

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

    non contiene rocce sciolte, quindi l'output è identico ad esso.

  • L'input

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

    contiene una roccia sciolta nella parte superiore, che cade sulla roccia ferma sotto di essa. L'output è

    ......
    .#..#.
    .#..##
    .#.#.#
    .#####
    .#...#
    
  • L'input

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

    ha un grande gruppo di rocce sciolte sulla sinistra. Il gruppo si scompone quando le rocce cadono, quindi l'output è

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

chiarimenti

  • Puoi prendere l'input da STDIN e inviarlo a STDOUT, oppure scrivere una funzione.
  • Questo è code-golf, quindi il programma più breve (in byte) è il vincitore.
  • Le scappatoie standard non sono ammesse.

Risposte:


12

CJam, 180 ... 133 101 ... 94 90 87 byte

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

C'è sicuramente molto da giocare a golf, ma volevo pubblicarlo prima di farlo funzionare completamente.

Guarda mamma! Nessuna barra di scorrimento!

Prende la griglia di rocce (composta da .e #senza una nuova riga finale) da STDIN e stampa l'output su STDOUT

AGGIORNAMENTO : Utilizzo di un riempimento parziale parziale inefficiente ma più breve per individuare rocce solide.

AGGIORNAMENTO 2 : modificato l'algoritmo per far cadere le rocce. Molto più breve ora!

AGGIORNAMENTO 3 : Ho fatto diverse piccole ottimizzazioni e alla fine sono stato in grado di ridurre il conteggio dei byte a metà del codice originale!

Come funziona :

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

Per l'inondazione, ripetiamo i tempi dell'intera griglia (griglia). In ogni iterazione, ci viene garantito di convertire almeno 1 #che tocca direttamente uno spazio in (spazio). Lo spazio qui rappresenta un gruppo rock deciso. Pertanto, alla fine delle iterazioni di lunghezza (griglia), siamo certi di avere tutte le rocce solide rappresentate da spazi.

Provalo online qui


15

Perl 5: 98

98 inclusi 2 flag della riga di comando.

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

Spiegazione:

#!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 Mi affido al fatto che l'ultima riga di input sia stata correttamente completata, vedi: ideone.com/7E3gQh Senza questa dipendenza sarebbe un carattere solitario (o uno più breve basato sull'opposto - mancanza di EOL finale).
nutki,

1
Battere CJam di quasi il 30%? Sorprendente. Mi congratulo con te.
DLosc

@DLosc Non più: P
Ottimizzatore

Battere altre lingue imperative del 100-300%? Sorprendente. Mi congratulo con te. ;)
DLosc,

@DLosc Guardando la risposta sopra, non includerò più il Perl nell'elenco delle lingue imperative: P
Ottimizzatore

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

Come funzione con un parametro stringa e restituzione di una stringa.

Inizialmente, aggiungi una riga inferiore di '1' per identificare la linea di terra.
Il primo ciclo cerca le rocce fisse (che si trovano vicino a un '1') e le contrassegna anche come '1'. La ricerca viene ripetuta fino a quando non si trovano più rocce salde.
Il secondo ciclo sposta i caratteri '#' rimanenti verso la riga inferiore. Ancora una volta, questo viene ripetuto fino a quando nessuna roccia può essere spostata.
Alla fine, sostituisci di nuovo "1" con "#" e taglia la riga inferiore.

Meno golf

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

Test (puoi avere prove di ciò che le rocce sono solide e cosa sono cadute)

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

APL, 130 119

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

Dal momento che non è possibile (per quanto ne so) inserire newline quando viene richiesto l'input, questo programma accetta una matrice di caratteri come input.

L'algoritmo utilizzato viene prima convertito in una matrice binaria ( 0è aria ed 1è roccia), quindi si riempie di inondazioni dalla fila inferiore per contrassegnare le rocce solide come 2. Quindi suddividere ciascuna colonna in "spazi tra rocce solide" e ordinare ogni partizione per far "cadere" l'aria.

Edit1: Golfato alcuni utilizzando un diverso algoritmo di riempimento


Esecuzioni di test

Esegui 1

Definisci una matrice di caratteri Ae la stampa:

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

Quindi Ainserire il programma:

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

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

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

Il diluvio riempie le rocce dal fondo, quindi abbassa le rocce piene di inondazioni. Utilizza molta ricorsione con il riempimento dell'inondazione, quindi potrebbe ritardare un po 'il browser.

È una funzione: chiamala con g("input")

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

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


1

Python 3, 364 byte

Sono sicuro che ne potrebbe essere spremuto di più ... ma non potrà mai competere con CJam e 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,"#")

Simile ad altre risposte. Una stranezza è che capovolge prima la griglia (per rendere più convenienti gli indici di loop) e aggiunge una riga e una colonna aggiuntive di .(per evitare problemi con gli -1indici di avvolgimento ). Corri chiamando P(string).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.