Encontrar a canção de ninar do incendiário

26

Imagine um incendiário andando pela cidade e escolhendo suas vítimas de acordo com um padrão muito específico (ou, alternativamente, imagine uma abelha voando pelo jardim e escolhendo suas flores para polenizar de acordo com um padrão muito específico ). Digamos que a cidade seja uma matriz N × N , onde N é um número inteiro maior ou igual a 2 . O incendiário começa no canto superior esquerdo e coloca sucessivamente os pontos da casa M na frente deles (onde M é o número da casa em que estão atualmente), enquanto muda a direção em que está se movendo após cada incêndio, na ordem Leste ⟶ Sul ⟶ Oeste ⟶ Norte ⟶ Leste ⟶ Sul ... e assim por diante. A canção de ninardo incendiário é o valor de M que os leva a sair da cidade (ou seja, a última casa que visitam antes de parar a abominação). Isso é muito mais fácil de entender com um exemplo. Tome a seguinte matriz, por exemplo:

3 2 3 2 7
3 1 4 1 6
2 5 3 1 1
4 4 3 2 4
1 1 1 1 1
  • Começamos no canto superior esquerdo, então M = 3 ( Xmarca as posições atuais e anteriores do incendiário):
    X 2 3 2 7
    3 1 4 1 6
    2 5 3 1 1
    4 4 3 2 4
    1 1 1 1 1
    
  • De acordo com a ordem conhecida, primeiro ele vai para o leste M (3) pontos e pousa em um 2, para que M mude de acordo:
    X 2 3 X 7
    3 1 4 1 6
    2 5 3 1 1
    4 4 3 2 4
    1 1 1 1 1
    
  • Então ele vai para o sul 2 pontos e M agora é 1 :
    X 2 3 X 7
    3 1 4 1 6
    2 5 3 X 1
    4 4 3 2 4
    1 1 1 1 1
    
  • Agora ele se move 1 ponto para o oeste e M se torna 3 :
    X 2 3 X 7
    3 1 4 1 6
    2 5 XX 1
    4 4 3 2 4
    1 1 1 1 1
    
  • Depois que ele se move 3 pontos ao norte, sai da cidade! Portanto, 3 é a canção de ninar desse incendiário:
        X
    X 2 3 X 7
    3 1 4 1 6
    2 5 XX 1
    4 4 3 2 4
    1 1 1 1 1
    

Dada uma matriz N × N (você também pode usar N como entrada), encontre a canção de ninar do incendiário. Eu escrevi um programa com o qual você pode gerar mais casos de teste e visualizar o caminho do incendiário: Experimente online!

  • Você pode assumir que o incendiário não têm uma canção de ninar (isto é, ele pode realmente sair da matriz).
  • A matriz conterá apenas números inteiros positivos menores ou iguais a 9 (dígitos), para simplificar. Soluções que lidam com qualquer número inteiro positivo são completamente bem-vindas.
  • Observe que o incendiário pode pousar em um local que já queimou, caso o sentido em que está se movendo seja diferente da primeira vez. Nesse cenário, basta pegar o valor desse elemento e mover novamente como de costume.
  • Você pode competir em qualquer linguagem de programação e pode receber e fornecer saída por qualquer método padrão , observando que essas brechas são proibidas por padrão. Isso é , então a submissão mais curta (em bytes) para todos os idiomas vence.

Casos de teste

-------------
9 2 3
1 7 2
8 7 6

Canção de ninar: 9
-------------
2 1 2 1
3 1 1 2
1 2 2 1
1 1 1 3

Canção de ninar: 2
-------------
3 2 3 2 7
3 1 4 1 6
2 5 3 1 1
4 4 3 2 4
1 1 1 1 1

Canção de ninar: 3
-------------
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2

Canção de ninar: 2
-------------
3 2 1 2 1 1 1
2 3 2 3 2 1 1
2 1 1 1 3 1 2
3 1 1 1 1 1 1
4 5 2 3 1 1 1
1 2 1 2 1 2 2
1 2 2 3 2 1 2

Canção de ninar: 3
-------------

As matrizes em um formato diferente:

[[9, 2, 3], [1, 7, 2], [8, 7, 6]]
[[2, 1, 2, 1], [3, 1, 1, 2], [1, 2, 2, 1], [1, 1, 1, 3]]
[[3, 2, 3, 2, 7], [3, 1, 4, 1, 6], [2, 5, 3, 1, 1], [4, 4, 3, 2, 4], [ 1, 1, 1, 1, 1]]
[[1, 2, 1, 2, 1, 2], [1, 2, 1, 2, 1, 2], [1, 2, 1, 2, 1, 2], [1, 2, 1, 2, 1, 2], [1, 2, 1, 2, 1, 2], [1, 2, 1, 2, 1, 2]]
[[3, 2, 1, 2, 1, 1, 1], [2, 3, 2, 3, 2, 1, 1], [2, 1, 1, 1, 1, 3, 1, 2], [ 3, 1, 1, 1, 1, 1, 1], [4, 5, 2, 3, 1, 1, 1], [1, 2, 1, 2, 1, 2, 2], [1, 2, 2, 3, 2, 1, 2]]

O quinto caso de teste é muito interessante para visualizar .

Mr. Xcoder
fonte
1
É como uma generalização de Skip como um coelho em duas dimensões, com um objetivo ligeiramente diferente. A temática desse desafio e seu título foram inspirados por uma música de Hozier
Mr. Xcoder
o que acontece quando o incendiário pousa em um quadrado que já está queimado?
Level River St
2
Podemos assumir que o incendiário não é realmente um incendiário e, em vez disso, está fazendo algo agradável em cada local, em vez de incendiá-lo? +1 para uma idéia muito agradável :)
ElPedro
2
@ElPedro Sure, uma versão alternativa para você: imagine uma abelha voando pelo jardim e colhendo suas flores para polenizar de acordo com um padrão muito específico. : D Golfe amigável e feliz!
Sr. Xcoder
1
Esse é um pensamento muito melhor. Se eu pudesse votar novamente, faria isso.
ElPedro

Respostas:

11

MATL , 32 bytes

JQ6*`G5thYay&Zj3$)wyJ2@-^*+8M]b&

Experimente online! Ou verifique todos os casos de teste .

Como funciona

A matriz de entrada é preenchida com um quadro de cinco zeros, portanto, por exemplo

3 2 3 2 7
3 1 4 1 6
2 5 3 1 1
4 4 3 2 4
1 1 1 1 1

torna-se

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 3 2 3 2 7 0 0 0 0 0
0 0 0 0 0 3 1 4 1 6 0 0 0 0 0
0 0 0 0 0 2 5 3 1 1 0 0 0 0 0
0 0 0 0 0 4 4 3 2 4 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

O quadro de zeros é usado para detectar quando a abelha incendiária saiu da matriz. A extensão com cinco zeros garante que um deslocamento modular de comprimento 9em qualquer direção de qualquer uma das entradas diferentes de zero aterre corretamente em um zero, sem envolver uma entrada diferente de zero.

Nas coordenadas da matriz, a abelha começa na entrada (6,6)da matriz estendida. Ele lê essa entrada e atualiza as coordenadas conforme necessário, aplicando um deslocamento (modular) do comprimento da leitura na direção correspondente. Isso é repetido em um loop até que o valor de leitura seja 0. A entrada que foi lida antes dessa (ou seja, a última entrada diferente de zero) é a saída.

As coordenadas são realmente armazenadas como um número complexo, por exemplo, (6,6)se tornam 6+6j. Dessa maneira, as quatro direções cíclicas podem ser percebidas como potências da unidade imaginária. A energia correspondente ( j, 1, -jou -1) é multiplicado pela entrada de leitura para obter o deslocamento complexo, que é usado para actualização das coordenadas.

Os valores lidos sucessivamente são mantidos na pilha. Quando o loop é encerrado, a pilha contém todos os valores de leitura diferentes de zero em ordem e, em seguida, o último valor de leitura, que é 0as coordenadas complexas mais recentes. Portanto, o terceiro elemento superior é a saída necessária.

Luis Mendo
fonte
1
+1 para uma abordagem muito inovadora.
LastStar007
7

JavaScript (ES6), 70 68 bytes

m=>(g=d=>(n=(m[y]||0)[x])?g(--d&3,x-=d%2*(y+=--d%2*n,L=n)):L)(x=y=0)

Experimente online!

Comentado

m => (                        // given m = input matrix
  g = d =>                    // g = recursive function taking the direction d
    (n = (m[y] || 0)[x]) ?    // let n be the content of the current cell; if it's defined:
      g(                      //   do a recursive call:
        --d & 3,              //     with the next direction (0 = E, 3 = S, 2 = W, 1 = N)
        x -=                  //     update x by subtracting ...
          d % 2 * (           //       ... ((d - 1) % 2) * n
            y += --d % 2 * n, //       and update y by adding ((d - 2) % 2) * n
            L = n             //       save n into L
          )                   //     end of x update
      )                       //   end of recursive call
    :                         // else:
      L                       //   stop recursion and return L
)(x = y = 0)                  // initial call to g() with x = y = d = 0

Dado que o sinal do módulo em JS é o do dividendo, a direção é atualizada da seguinte maneira:

 d | d' = --d&3 | dx = -(d%2)  | dy = --d%2 | direction
---+------------+--------------+------------+------------------
 0 |     3      | -(-1%2) = +1 | -2%2 =  0  | (+1,  0) = East
 3 |     2      | -( 2%2) =  0 |  1%2 = +1  | ( 0, +1) = South
 2 |     1      | -( 1%2) = -1 |  0%2 =  0  | (-1,  0) = West
 1 |     0      | -( 0%2) =  0 | -1%2 = -1  | ( 0, -1) = North
Arnauld
fonte
4

Carvão , 25 18 bytes

PS↶WKK«≔ιθ×Iι¶↷»⎚θ

Experimente online! Link é a versão detalhada do código. Explicação:

PS

Imprima a sequência de entrada, mas não mova a posição de impressão.

Gire o pivô para a esquerda, para que a direção da impressão esteja agora para cima.

WKK«

Repita enquanto houver um caractere na posição de impressão.

≔ιθ

Salve o caractere em uma variável.

×Iι¶

Transmita o caractere para um número e imprima muitas linhas novas. Como a direção da impressão agora está alta, isso acaba sendo impresso horizontalmente. O resultado é que movemos a posição de impressão na direção desejada pela quantidade fornecida pelo número sob a posição de impressão.

↷»

Gire o pivô para que as próximas novas linhas movam a posição de impressão na próxima direção no sentido horário para a próxima passagem do loop.

F⟦ωθ⟧¿ιι⎚

Infelizmente ainda temos a entrada bagunçando nossa tela, e ainda mais, se limparmos a tela, também limparemos nossa variável. Então, isso é um truque: uma lista da string vazia e da variável é repetida. Na primeira passagem do loop, a variável loop está vazia; portanto, a tela e a variável loop e a variável result são todas limpas. Mas o ciclo não está terminado! Na segunda passagem do loop, ainda conseguimos acessar nossa variável cuidadosamente preservada em nossa lista de loop. Resta simplesmente imprimi-lo.

⎚θ

Limpe a tela e imprima a variável salva. (Obrigado a @ ASCII-only pela correção para Charcoal.)

Neil
fonte
2

Python 2 , 85 84 bytes

a=input();x=y=e=0;d=1
while-1<y<len(a)>x>=0:v=a[y][x];x+=v*d;y+=e*v;d,e=-e,d
print v

Experimente online!

Dica o chapéu para o Sr. Xcoder por 1 byte.

Chas Brown
fonte
2

Carvão , 50 49 46 34 33 26 bytes

NθEθSMθ↑WKK«MIι✳⊗Lυ⊞υι»⎚⊟υ

Experimente online

O link é para a versão detalhada do código

A entrada deve ser N em sua própria linha, depois as linhas da matriz em linhas separadas.

Quaisquer maneiras de eliminar bytes são bem-vindas e desejadas, pois eu não sou um bom jogador de golfe em Carvão!

-12 bytes graças a @Neil! -1 byte graças a @ ASCII-only! -7 bytes graças a @ ASCII-only (mudou um bug que fazia as Clearvariáveis ​​de redefinição)

Zacharý
fonte
1

Vermelho , 145 bytes

func[b][h:[0 1 0 -1 0]x: y: 1 i: 0
until[y: h/(i: i % 4 + 1) *(t: b/(y)/(x)) + y x: h/(i + 1) * t + x none = b/(y) or(x < 1 or(x > length? b))]t]

Experimente online!

Mais legível:

f: func[b][
    h: [0 1 0 -1 0]                                ; step lengths (combined for x and y) 
    x: y: 1                                        ; starting coords (1,1)
    i: 0                                           ; step counter 
    until[
        y: h/(i: i % 4 + 1) * (t: b/(y)/(x)) + y   ; next y; t stores the lullaby
        x: h/(i + 1) * t + x                       ; next x
        none = b/(y) or (x < 1 or (x > length? b)) ; until x or y are not valid indices
    ]
    t                                              ; return the lullaby
]
Galen Ivanov
fonte
1

Perl 6 , 62 bytes

{$^w;$^m[0,{$_+$m[$_]*(1,$w,-1,-$w)[$++%4]}...{!$m[$_]}][*-2]}

Experimente online!

Toma a matriz como lista plana e largura.

Nwellnhof
fonte
1

Limpo , 141 bytes

import StdEnv
d=[0,1,1,0,0,-1,-1,0:d]
$m[x,y]n[a,b:l]#r=size m
#u=x+a*n
#v=y+b*n
|0>u||0>v||u>=r||v>=r=n= $m[u,v]m.[u,v]l
?m= $m[0,0]m.[0,0]d

Experimente online!

Define a função ? :: {#{#Int}} -> Int, obtendo uma matriz sem caixa de matrizes sem caixa de números inteiros e retornando o resultado.

Furioso
fonte
1

Java 8, 121 bytes

m->{int l=m.length,x=0,y=0,f=0,r=0;for(;x*y>=0&x<l&y<l;x+=f<1?r:f==2?-r:0,y+=f==1?r:f>2?-r:0,f=++f%4)r=m[y][x];return r;}

Experimente online.

Alternativa com a mesma contagem de bytes de 121 bytes :

m->{int l=m.length,x=0,y=0,f=0,r=0;try{for(;;x+=f<1?r:f==2?-r:0,y+=f==1?r:f>2?-r:0,f=++f%4)r=m[y][x];}finally{return r;}}

Usa try-finalmente em vez de verificar se o x,y-coordinate ainda está dentro dos limites.

Experimente online.

Explicação:

m->{                   // Method with integer-matrix parameter and integer return-type
  int l=m.length,      //  Dimensions of the matrix
      x=0,y=0,         //  x,y coordinate, starting at [0,0]
      f=0,             //  Direction-flag, starting at 0 (east)
      r=0;             //  Result-integer
  for(;x*y>=0&x<l&y<l  //  Loop as long as the x,y coordinates are still within bounds
      ;                //    After every iteration:
       x+=f<1?         //     If the direction is east:
           r           //      Increase the `x` coordinate by `r`
          :f==2?       //     Else-if the direction is west:
           -r          //      Decrease the `x` coordinate by `r`
          :            //     Else (it's north/south):
           0,          //      Leave the `x` coordinate the same
       y+=f==1?        //     If the direction is south:
           r           //      Increase the `y` coordinate by `r`
          :f>2?        //     Else-if the direction is north:
           -r          //      Decrease the `y` coordinate by `r`
          :            //     Else:
           0,          //      Leave the `y` coordinate the same
       f=++f%4)        //     Go to the next direction (0→1→2→3→0)
    r=m[y][x];         //   Set `r` to the value of the current cell
  return r;}           //  Return the last `r` before we went out of bounds
Kevin Cruijssen
fonte
0

Perl 5 , 92 bytes

sub b{1while eval join'&&',map{/./;map"(\$$_$&=".'$n=$_[$y][$x])'.$',x,'y'}'+<@_','->=0';$n}

Experimente online!

Quão?

O conjunto de mapas aninhados e a junção produzem isso:

($x+=$n=$_[$y][$x])<@_&&($y+=$n=$_[$y][$x])<@_&&($x-=$n=$_[$y][$x])>=0&&($y-=$n=$_[$y][$x])>=0

que é então avaliado para determinar se o loop termina. Como o booleano é avaliado da esquerda para a direita, o valor $nrealmente muda (até) quatro vezes durante a avaliação. Como a lógica booleana causa um curto-circuito no Perl, o valor de $né a canção de ninar quando o loop é encerrado.

Xcali
fonte
0

Python 3 , 85 84 bytes

xcoder: -1 (nunca me lembro do truque + ~)

def f(x):
 r=c=0
 while-1<r:d=x[r][c];r,c=len(x)-c+~d,r;x=[*zip(*x)][::-1]
 return d

Experimente online!

Em vez de se mover em direções diferentes (E, S, W, N), essa solução sempre se move para o leste e gira a grade no sentido anti-horário após cada movimento. Após a rotação, qual foi a última coluna agora é a primeira linha; portanto, se o índice da linha for menor que zero, significa que fugimos do quadro.

RootTwo
fonte
84 bytes : -d-1=>+~d
Sr. Xcoder
0

Retina , 161 bytes

.
 $.%`*_#$&*
(?<=(.+¶)+|^)
A ¶A$#1*
~(K`{`^X\1YZ¶1S$4¶1XYZ¶2$4$2$4$3¶2XYZ¶3S¶3XY\1Z¶S
X
(_$*)(A_$*)
Y
( _$*)
Z
(?=\n\D$*\2\b.$*\3#(_+))
)`S
$$4$$2$$3
L$0`_+
$.0

Experimente online!

TwiNight
fonte