Simulador de gravidade

33

Declaração

Você recebe uma imagem estática de uma série de bolas caindo em uma grade 2D. Essa grade é cercada por paredes imutáveis ​​e inquebráveis, para que toda a ação contida nelas. Sua tarefa é determinar qual será o estado do cenário depois que a gravidade fizer todo o trabalho.

Elementos dentro da grade

  • - Chão, não altera a direção das bolas caindo.
  • \ Deslize para a direita, altera o caminho da bola uma (1) posição para a direita.
  • / O slide esquerdo altera o caminho da bola uma (1) posição esquerda.
  • o Uma bola.

Regras

  • Bolas caem.
  • Pisos e slides não caem .
  • Se a bola bater em um escorregador que o faria atravessar uma parede ( \#ou #/) ou atravessar um piso, o escorregador atuará como um piso.
  • Quando uma bola bate em outra bola, ela se torna uma bola, mas aumenta seu poder na soma das duas bolas.
  • Novas bolas (unidas) continuarão a se comportar como de costume.
  • Quando uma bola não pode mais se mover, ela é substituída por seu poder.
  • O poder de uma bola sempre será no máximo 9.

Entrada

A grade será fornecida em uma variável de string com o nome mais curto no seu idioma de escolha. Por padrão, usaremos acomo entrada. Uma amostra de uma entrada, exatamente como recebida:

##########\n# \      #\n#o       #\n#  - -\o #\n#/-    \ #\n#  \oo-/\#\n#-/ \   /#\n#   \ \  #\n#       /#\n##########

Para grades aleatórias geradas, use https://repl.it/B1j3/2 . Use minha página gerada (sem anúncios, porcaria, apenas a entrada e a saída)

Observe quebras de linha são \n. Imprimir a entrada na tela (não necessária para o desafio) mostraria coisas assim. Embora eu tenha colocado quatro quebra-cabeças ao lado para um espaço seguro.

##########  ##########  ##########  ##########
# \      #  # o    -/#  #       o#  #-o /    #
#o       #  #    \   #  # o     -#  #-- \ /\ #
#  - -\o #  #-  \    #  #    - \o#  # - -- o-#
#/-    \ #  #        #  #o /\    #  #/ \     #
#  \oo-/\#  #o  -o-  #  # /    -o#  #/ /o oo/#
#-/ \   /#  #   -/-  #  # -  o  -#  #o/      #
#   \ \  #  #    \\  #  #   \o  /#  #o-o    o#
#       /#  # \o\  /\#  #     \o #  # -\o o /#
##########  ##########  ##########  ##########

Saída

A mesma grade, impressa na tela com o resultado final da força da bola. Uma resposta válida seria um (1) dos seguintes quebra-cabeças, cada um corresponde à entrada na mesma posição, é claro que se a entrada for diferente, você deve ajustar a saída. Não o limite àqueles quatro!

##########  ##########  ##########  ##########
# \      #  #      -/#  #       1#  #-1 /    #
#        #  #    \   #  #       -#  #-- \ /\ #
#1 - -\  #  #-  \    #  #    - \ #  # - --  -#
#/-    \1#  #        #  #  /\    #  #/ \     #
#  \  -/\#  #   -1-  #  # /    -2#  #/ /    /#
#-/ \   /#  #   -/-  #  # -     -#  # /      #
#   \ \  #  #    \\  #  #   \   /#  # -      #
#    2  /#  #1\2\  /\#  #2   2\1 #  #2-\3 23/#
##########  ##########  ##########  ##########

Ponto

Os idiomas competirão entre si, portanto, sinta-se livre para usar idiomas não-lobos. Para validar uma solução, devo poder testá-la em algum lugar para ver se funciona !.

Pontuação é o número de bytes. Em caso de empate, a primeira resposta para alcançar a pontuação empatada vence.

Advertências

  • Se não tiver certeza de como uma bola deve reagir, pergunte-me e esclarecerei. Fui o mais claro possível, mas tenho certeza de que há casos confusos.
  • Os slides são montados apenas se você puder sair deles ; pense nisso como um slide real. Há um cara no topo que não deixa você passar pela bola, a menos que ela saia pelo outro lado.

Esclarecendo exemplos do movimento da bola

######                       ######
#-o- #    BALL WOULD GO RD   #- - #
# \  #                       # \o #
######                       ######

######                       ######
#-o- #     BALL WOULD STAY   #-o- #
# \\ #                       # \\ #
######                       ######

######                       ######
#  -o#     BALL WOULD STAY   #  -o#
#   \#                       #   \#
######                       ######

######                       ######
#  o #     BALL WOULD STAY   #  o #
#  \/#                       #  \/#
######                       ######

######                       ######
#-o- #    BALL WOULD GO LD   #- - #
# /\ #                       #o/\ #
######                       ######

ATUALIZAÇÕES

Como posso testar se minha resposta é válida?

Configurei uma página simples em um dos meus sites que fornecerá um quebra-cabeça aleatório e sua resposta. Pegue a entrada e verifique com a saída. Minha solução, sem se preocupar muito com o golfe, está em python (gerador e página também python)389b 355b

Entre os melhores

Juan Cortés
fonte
1
Lembro-me de Marbelous .
Arcturus
10
Pontos de bônus se alguém responder em Marbelous.
Mego
Dupe Borderline de A Mere Bagatelle e não sua rotina de feijão Máquina
Peter Taylor
Soa como potencialmente um jogo de pinball ascii-art
Khaled.K
@ JuanCortés, por que você não usa o código do quadro de líderes sofisticado para não precisar atualizar os rankings?
usandfriends 4/16/16

Respostas:

6

JavaScript (ES6), 157196

Edite char por char em vez de linha por linha, resultado muito melhor

g=>(s=~g.search`
`,g=[...g]).map((c,i)=>c<' '?0:g[[0,1,-1].map(d=>!d|'\\ /'[d+1]==g[d+=i]&&+g[d+=s]?g[v+=+g[d],d+v-v]=' ':0,v=c>'a'?1:+c),i]=v?v:c)&&g.join``

Nota: não lida com valores de bola> 9. Mas poderia, com um custo de 18 bytes. Veja o código básico abaixo.

Snippet de teste (melhor página inteira)

F=g=>(s=~g.search`
`,g=[...g]).map((c,i)=>c<' '?0:g[[0,1,-1].map(d=>!d|'\\ /'[d+1]==g[d+=i]&&+g[d+=s]?g[v+=+g[d],d+v-v]=' ':0,v=c=='o'?1:+c),i]=v?v:c)&&g.join``

// Basic code, starting point before golfing
B=g=>{
  s = ~g.search('\n');
  (g=[...g]).map((c,i)=>{
    v = c == 'o' ? 1 : +c
    if (c>=' ' // skip newlines
        && !isNaN(v)) // digit or space
    {
      if (w=+g[i+s]) v += w, g[i+s]=' '
      if (g[i-1]=='\\' && (w=+g[i+s-1])) v += w, g[i+s-1]=' '
      if (g[i+1]=='/' && (w=+g[i+s+1])) v += w, g[i+s+1]=' '
      if (v) g[i] = v
    }
  })      
  // return g.join``
  // To handle values > 9 ...
  return g.map(v=>+v?v%10:v).join``
}  

function test() {
  O.textContent = F(I.value)
}

test()
textarea,pre { width: 15em; height: 15em; display: block; margin: 0; }
iframe { height: 25em; width: 15em}
td { vertical-align: top }
<table>
  <tr>
    <th>Test cases</th>
    <th>Input</th>
    <td></td>
    <th>Output</th>
  </tr><tr>
    <td>
    Copy/paste test cases from here <br>(courtesy of OP)
    <button onclick="T.src='http://bohem.io/wadus/index.php'">reload</button><br>
    <iframe id=T src="http://bohem.io/wadus/index.php"></iframe>
    </td>
    <td><textarea id=I>##########
#  o  o o#
# o\o o  #
#oo o/   #
#       o#
#     /o #
#\o   o  #
# o /-   #
#   o  - #
##########</textarea></td>
    <td><button onclick='test()'>Test</button></td>
    <td><pre id=O></pre></td>
  </tr>
</table>

edc65
fonte
Agradável! Eu tenho muito a aprender nas formas de golfe
usandfriends
você não deve mapear valores> 9 com v>9?9:v?
Titus
@ Titus eu poderia, mas na verdade eu poderia fazer o que eu quiser, como um valor> 9 não é esperado, veja o comentário do OP respondendo à minha pergunta.
Edc65
5

Javascript (ES6), 453 426 409 306 290 286 bytes

A primeira e mais óbvia solução que me veio à mente é aquela que olha em volta dos slides e depois se funde ou substitui.

a=>{a=a.split`
`.map(b=>[...b.replace(/o/g,'1')]);for(r=1;r<a.length-1;r++){d=a[r];for(c=1;c<d.length-1;c++){e=a[r+1];f=e[c]=='\\'?c+1:e[c]=='/'?c-1:!isNaN(+e[c])?c:null;(''+d[c]).match(/[0-9]/g)&&f!=null&&!isNaN(+e[f])?(e[f]=+e[f]+ +d[c],d[c]=' '):0}}return a.map(b=>b.join``).join`
`}

Ungolfed:

func = state => {
    state = state.split `
`.map(line => [...line.replace(/o/g, '1')]);

    for (r = 1; r < state.length - 1; r++) {
        thisState = state[r];
        for (c = 1; c < thisState.length - 1; c++) {
            nextState = state[r + 1];
            nc = nextState[c] == '\\' ? c + 1 : nextState[c] == '/' ? c - 1 : !isNaN(+nextState[c]) ? c : null;

            ('' + thisState[c]).match(/[0-9]/g) && nc != null && !isNaN(+nextState[nc]) ? (
                nextState[nc] = +nextState[nc] + +thisState[c],
                thisState[c] = ' '
            ) : 0;
        }
    }

    return state.map(line => line.join ``).join `
`;
}

Teste como:

func(`##########
# -- o - #
# \\\\\\ -  #
#-       #
# o  o   #
#o \\\\ /-\\#
#      \\ #
#/-  //  #
#   /- o #
##########`)

Graças a: @ edc65

usandfriends
fonte
Vou postar meu python quando tiver certeza de que não posso mais jogar golfe, mas até agora é o código python que está gerando a resposta. De alguma forma eu posso testar seu código de golfe em algum lugar para que eu possa aparecer na tabela de classificação? (jsFiddle, jsbin, ideone, qualquer que seja)
Juan Cortés
baixou para 355, sua jogada!
Juan Cortés
@ JuanCortés Feito!
usandfriends 4/16/16
b.replace(/o/g,'1').split`` pode ser encurtado para[...b.replace(/o/g,1)]
edc65
@ edc65 Acho que consertei. Basicamente, ele sempre mantém o poder abaixo de 10 modificando 10.
usandfriends
4

Java, Muitos 1102 987 bytes

Porque Java.

\ o / Está abaixo de 1000!

class G{class T{char s;int p=0;T(char c){s=c;}}T A=new T(' ');T[][]o;boolean i(){for(int i=1;i<o.length;i++)for(int j=1;j<o[i].length;j++)if(o[i][j].p>0){if(m(i,j,i+1,j)||o[i+1][j].s=='/'&&m(i,j,i+1,j-1)||o[i+1][j].s=='\\'&&m(i,j,i+1,j+1))return 1>0;int w=o[i][j].p;o[i][j]=new T(Integer.toString(w).charAt(0)){{p=w;}};}return 1<0;}boolean m(int a,int b,int c,int d){if(o[c][d]==A||o[c][d].p>0){o[a][b].p+=o[c][d].p;o[c][d]=o[a][b];o[a][b]=A;return 1>0;}return 1<0;}String s(){String s="";for(T[]r:o){for(T t:r)s+=t.s;s+="\n";}return s;}void f(String s){String[]r=s.split("\\\\n");o=new T[r.length][r[0].length()];for(int i=0;i<o.length;i++)for(int j=0;j<o[i].length;j++)switch(r[i].charAt(j)){case'-':o[i][j]=new T('-');break;case'\\':o[i][j]=new T('\\');break;case'/':o[i][j]=new T('/');break;case'o':o[i][j]=new T('o'){{p=1;}};break;case'#':o[i][j]=new T('#');break;default:o[i][j]=A;}}public static void main(String[]a){G g=new G();g.f(a[0]);while(g.i());System.out.println(g.s());}}

A meta lado estava sendo capaz de imprimir cada iteração do conselho: basta remover o meio ;em while(g.i()) ; System.out.print(g.s());(Embora isto faz desativar a última impressão que tem a 0-> conversão de energia). Infelizmente, nesta versão, a gravidade funciona estranhamente. A cada passe, pego a primeira bola não presa e a movo. Curto-circuito, iterate()há menos bytes do que passar por toda a placa e retornar se alguma coisa mudar.

Esta é uma classe principal completa, compila e executa na linha de comando com o argumento:

java -jar G.jar "##########\n# o-/    #\n#-  / -/ #\n# oo   o #\n# /   \o #\n# o   o \#\n#    o   #\n#   -\o  #\n#\  \\ o/#\n##########"

Versão "legível":

class GravitySimulator {
    class Token {
        char symbol;
        int power = 0;

        Token(char c) {
            symbol = c;
        }
    }

    Token A = new Token(' ');

    Token[][] board;

    boolean iterate() {
        for (int i=1; i<board.length; i++)
            for (int j=1; j<board[i].length; j++) 
                if (board[i][j].power>0) {
                    if (move(i,j,i+1,j) || board[i+1][j].symbol=='/' && move(i,j,i+1,j-1) || board[i+1][j].symbol=='\\' && move(i,j,i+1,j+1)) return true;
                    int pow = board[i][j].power;
                    board[i][j] = new Token(Integer.toString(pow).charAt(0)){{power=pow;}};
                }
        return false;
    }

    boolean move(int x1, int y1, int x2, int y2) {
        if (board[x2][y2] == A || board[x2][y2].power>0) {
            board[x1][y1].power += board[x2][y2].power;
            board[x2][y2] = board[x1][y1];
            board[x1][y1] = A;
            return true;
        } return false;
    }

    String string() {
        String s = "";
        for (Token[] row : board) {
            for (Token token : row) s+=token.symbol;
            s+="\n";
        }
        return s;
    }

    void fromString(String s) {
        String[] rows = s.split("\\\\n");
        board = new Token[rows.length][rows[0].length()];
        for (int i=0; i<board.length; i++) 
            for (int j=0; j<board[i].length; j++) 
                switch(rows[i].charAt(j)) {
                    case '-': board[i][j]=new Token('-');break;
                    case '\\':board[i][j]=new Token('\\');break;
                    case '/': board[i][j]=new Token('/');break;
                    case 'o': board[i][j]=new Token('o'){{power=1;}};break;
                    case '#': board[i][j]=new Token('#');break;
                    default:  board[i][j]=A;
                }
    }

    public static void main(String[] args) {
        GravitySimulator g = new GravitySimulator();
        g.fromString(args[0]);
        while(g.iterate());
        System.out.println(g.string());
    }
}
CAD97
fonte
Tal java muito detalhado. +1
Rohan Jhunjhunwala
1

Python3, 355b

g=g.replace("o","1").split("\n")
r=1
while r:
 r=0
 for y in range(len(g)):
  for x in range(len(g[y])):
   if g[y][x].isdigit():
    h=g[y+1]
    m={"/":-1,"\\":1}
    j=x+m[h[x]]if h[x]in m else x
    if("0"+h[j].strip()).isdigit():
     r=1
     g[y+1]=h[:j]+str(int(g[y][x])+int("0"+h[j]))+h[j+1:]
     g[y]=g[y][:x]+' '+g[y][x+1:]
print("\n".join(g))

Teste aqui

Juan Cortés
fonte
0

PHP, 228 204 197 194 bytes

for($a=strtr($a,o,1);$c=$a[$i];$i++)$c>0&&(($d=$a[$t=$i+strpos($a,"
")+1])>" "?$d!="/"?$d!="\\"?$d>0:$a[++$t]<"!"||$a[$t]>0:$a[--$t]<"!"||$a[$t]>0:1)&&$a[$t]=min($a[$t]+$c,9).!$a[$i]=" ";echo$a;

gera avisos no PHP 7.1. Insira (int)antes $a[$t]+$cpara corrigir.

Corra com php -nr '$a="<string>";<code>'ou experimente online .

demolir

for($a=strtr($a,o,1);   # replace "o" with "1"
    $c=$a[$i];$i++)     # loop through string
    $c>0                    # if character is numeric
    &&(($d=$a[                  # and ...
        $t=$i+                  # 3: target position = current position + 1 line
            strpos($a,"\n")+1   # 2: width = (0-indexed) position of first newline +1
    ])>" "                  # if target char is not space
        ?$d!="/"                # and not left slide
        ?$d!="\\"               # and not right slide
        ?$d>0                   # but numeric: go
        :$a[++$t]<"!"||$a[$t]>0     # right slide: if target+1 is space or ball, then go
        :$a[--$t]<"!"||$a[$t]>0     # left slide: if target-1 is space or ball, then go
    :1                              # space: go
    )&&                     # if go:
        $a[$t]=min($a[$t]+$c,9) # move ball/merge balls
        .!$a[$i]=" "            # clear source position
    ;
echo$a;                 # print string
Titus
fonte