Encuentra la canción de cuna del pirómano

26

Imagine a un pirómano caminando por la ciudad y recogiendo a sus víctimas de acuerdo con un patrón muy específico (o, alternativamente, imagine una abeja volando por el jardín y recogiendo sus flores para polenizar de acuerdo con un patrón muy específico ). Digamos que la ciudad es una matriz N × N , donde N es un número entero mayor o igual a 2 . El incendiario comienza desde la esquina superior izquierda y establece sucesivamente los puntos M de la casa frente a ellos (donde M es el número de la casa en la que se encuentran actualmente), mientras cambia la dirección en la que se mueve después de cada incendio, en el orden Este ⟶ Sur ⟶ Oeste ⟶ Norte ⟶ Este ⟶ Sur ... y así sucesivamente. La canción de cunadel incendiario es el valor de M que los hace salir de la ciudad (es decir, la última casa que visitan antes de detener la abominación). Esto es mucho más fácil de entender con un ejemplo. Tome la siguiente matriz por ejemplo:

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
  • Comenzamos en la esquina superior izquierda, por lo que M = 3 ( Xmarca las posiciones actuales y anteriores del pirómano):
    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
    
  • Según el orden conocido, primero va al este M (3) puntos y aterriza en un 2, por lo que M cambia en consecuencia:
    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
    
  • Luego va hacia el sur 2 puntos y M es ahora 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
    
  • Ahora se mueve 1 lugar hacia el oeste y M se convierte en 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
    
  • ¡Después de que se mueve 3 puntos al norte, sale de la ciudad! Por lo tanto, 3 es la canción de cuna de este pirómano:
        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 una matriz N × N (opcionalmente, también puede tomar N como entrada), encuentre la canción de cuna del pirómano. He escrito un programa con el que puedes generar más casos de prueba y visualizar el camino del pirómano: ¡ Pruébalo en línea!

  • Es posible suponer que el incendiario hace tener una canción de cuna (que es, en realidad puede salir de la matriz).
  • La matriz solo contendrá enteros positivos menores o iguales a 9 (dígitos), por simplicidad. Las soluciones que manejan cualquier número entero positivo son completamente bienvenidas.
  • Tenga en cuenta que el pirómano puede aterrizar en un lugar que ya ha quemado, en caso de que la sensación de que se mude sea diferente de la primera vez. En tal escenario, simplemente tome el valor de ese elemento y muévalo nuevamente como de costumbre.
  • Puede competir en cualquier lenguaje de programación y puede tomar entradas y proporcionar salidas a través de cualquier método estándar , mientras toma nota de que estas lagunas están prohibidas por defecto. Este es el , por lo que gana el envío más corto (en bytes) para cada idioma .

Casos de prueba

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

Canción de cuna: 9
-------------
2 1 2 1
3 1 1 2
1 2 2 1
1 1 1 3

Canción de cuna: 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

Canción de cuna: 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

Canción de cuna: 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

Canción de cuna: 3
-------------

Las matrices en un 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, 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]]

El quinto caso de prueba es muy interesante de visualizar .

Sr. Xcoder
fuente
1
Esto es como una generalización de Skip like a Rabbit en dos dimensiones, con un objetivo ligeramente diferente. La temática de este desafío y su título se inspiraron en una canción de Hozier
Mr. Xcoder
¿Qué sucede cuando el incendiario aterriza en un cuadrado que ya está quemado?
Level River St
2
¿Podemos suponer que el pirómano no es realmente un pirómano y, en cambio, está haciendo algo bueno en cada lugar en lugar de quemarlo? +1 para una idea muy bonita :)
ElPedro
2
@ElPedro Claro, una versión alternativa para ti: imagina una abeja volando por el jardín y recogiendo sus flores para polenizar de acuerdo con un patrón muy específico. : D ¡Feliz golf amistoso!
Sr. Xcoder
1
Ese es un pensamiento mucho más agradable. Si pudiera votar de nuevo, lo haría por eso.
ElPedro

Respuestas:

11

MATL , 32 bytes

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

Pruébalo en línea! O verificar todos los casos de prueba .

Cómo funciona

La matriz de entrada se rellena con un marco de cinco ceros, por ejemplo

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

se convierte

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

El marco de ceros se usa para detectar cuándo la abeja incendiaria ha salido de la matriz. La extensión con cinco ceros asegura que un desplazamiento modular de longitud hasta 9en cualquier dirección desde cualquiera de las entradas distintas de cero aterrizará correctamente en un cero sin ajustarse a alguna entrada distinta de cero.

En las coordenadas de la matriz, la abeja comienza en la entrada (6,6)de la matriz extendida. Lee esa entrada y actualiza las coordenadas según sea necesario, aplicando un desplazamiento (modular) de la longitud de lectura en la dirección correspondiente. Esto se repite en un bucle hasta que el valor de lectura sea 0. La entrada que se leyó antes de esa (es decir, la última entrada distinta de cero) es la salida.

Las coordenadas se almacenan realmente como un número complejo, por lo que, por ejemplo, se (6,6)convierte en 6+6j. De esta manera, las cuatro direcciones cíclicas pueden realizarse como potencias de la unidad imaginaria. La potencia correspondiente ( j, 1, -jo -1) se multiplica por la entrada de lectura para obtener el complejo desplazamiento que se utiliza para la actualización de las coordenadas.

Los valores leídos sucesivamente se mantienen en la pila. Cuando se sale del bucle, la pila contiene todos los valores de lectura distintos de cero en orden, luego el último valor de lectura que es 0, luego las últimas coordenadas complejas. Entonces, el tercer elemento superior es la salida requerida.

Luis Mendo
fuente
1
+1 para un enfoque muy innovador.
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)

Pruébalo en línea!

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 el signo del módulo en JS es el del dividendo, la dirección se actualiza de esta manera:

 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
fuente
4

Carbón , 25 18 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

PS

Imprima la cadena de entrada, pero no mueva la posición de impresión.

Gire el pivote hacia la izquierda, de modo que la dirección de impresión esté ahora hacia arriba.

WKK«

Repita mientras haya un carácter debajo de la posición de impresión.

≔ιθ

Guarde el personaje en una variable.

×Iι¶

Lanza el personaje a un número e imprime tantas líneas nuevas. Como la dirección de impresión ahora está hacia arriba, esto termina imprimiendo horizontalmente. El resultado es que hemos movido la posición de impresión en la dirección deseada por la cantidad dada por el número debajo de la posición de impresión.

↷»

Gire el pivote para que las nuevas líneas nuevas muevan la posición de impresión en la siguiente dirección en el sentido de las agujas del reloj para la próxima pasada del bucle.

F⟦ωθ⟧¿ιι⎚

Desafortunadamente, todavía tenemos la entrada abarrotando nuestro lienzo, y aún más desafortunadamente, si limpiamos el lienzo también borramos nuestra variable. Entonces, esto es un poco truco: una lista de la cadena vacía y la variable se repite. En la primera pasada del bucle, la variable del bucle está vacía, por lo que el lienzo y la variable del bucle y la variable del resultado se borran. ¡Pero el ciclo no ha terminado! En el segundo paso del ciclo, aún podemos acceder a nuestra variable cuidadosamente preservada en nuestra lista de ciclos. Simplemente queda por imprimirlo.

⎚θ

Borre el lienzo e imprima la variable guardada. (Gracias a @ ASCII-only por la solución a Charcoal).

Neil
fuente
2

Carbón , 50 49 46 34 33 26 bytes

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

Pruébalo en línea

El enlace es a la versión detallada del código

La entrada debe ser N en su propia línea, luego las líneas de la matriz en líneas separadas después de eso.

Cualquier forma de eliminar bytes es bienvenida y deseada, ya que no soy un buen golfista en el carbón.

-12 bytes gracias a @Neil! -1 byte gracias a @ ASCII-only! -7 bytes gracias a @ ASCII-only (cambió un error que hizo que las Clearvariables de reinicio)

Zacharý
fuente
1

Rojo , 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]

Pruébalo en línea!

Más legible:

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
fuente
1

Perl 6 , 62 bytes

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

Pruébalo en línea!

Toma la matriz como lista plana y ancho.

nwellnhof
fuente
1

Limpio , 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

Pruébalo en línea!

Define la función ? :: {#{#Int}} -> Int, toma una matriz sin caja de matrices enteras sin caja y devuelve el resultado.

Οurous
fuente
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;}

Pruébalo en línea.

Alternativa con el mismo número 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;}}

Utiliza try-finally en lugar de verificar si x,y-coordinate todavía está dentro de los límites.

Pruébalo en línea.

Explicación:

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
fuente
0

Perl 5 , 92 bytes

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

Pruébalo en línea!

¿Cómo?

El conjunto de mapas anidados y la unión producen esto:

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

que luego se evalúa para determinar si el ciclo termina. Debido a que el booleano se evalúa de izquierda a derecha, el valor de $nrealmente cambia (hasta) cuatro veces durante la evaluación. Debido a que la lógica booleana cortocircuita en Perl, el valor de $nes la canción de cuna cuando se sale del bucle.

Xcali
fuente
0

Python 3 , 85 84 bytes

xcoder: -1 (nunca recuerdo el truco + ~)

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

Pruébalo en línea!

En lugar de moverse en diferentes direcciones (E, S, W, N), esta solución siempre se mueve hacia el este y gira la cuadrícula en sentido antihorario después de cada movimiento. Después de rotar, lo que fue la última columna ahora es la primera fila, por lo que si el índice de la fila es menor que cero, significa que nos salimos del tablero.

RootTwo
fuente
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

Pruébalo en línea!

TwiNight
fuente