Trouver la berceuse d'un pyromane

26

Imaginez un pyromane se promener dans la ville et cueillir ses victimes selon un modèle très spécifique (ou, alternativement, imaginer une abeille volant dans le jardin et cueillant ses fleurs pour polliniser selon un modèle très spécifique ). Disons que la ville est une matrice N × N , où N est un entier supérieur ou égal à 2 . L'incendiaire part du coin supérieur gauche et place successivement les points M de la maison devant eux (où M est le numéro de la maison dans laquelle ils se trouvent actuellement), tout en changeant la direction dans laquelle il se déplace après chaque incendie, dans l'ordre Est ⟶ Sud ⟶ Ouest ⟶ Nord ⟶ Est ⟶ Sud ... et ainsi de suite. La berceusede l'incendiaire est la valeur de M qui les fait sortir de la ville (c'est-à-dire la dernière maison qu'ils visitent avant d'arrêter l'abomination). C'est beaucoup plus facile à comprendre avec un exemple. Prenez par exemple la matrice suivante:

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
  • Nous commençons dans le coin supérieur gauche, donc M = 3 ( Xmarque les positions actuelle et précédente de l'incendiaire):
    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
    
  • Selon l'ordre connu, il va d'abord vers l'est M (3) et atterrit sur un 2 donc M change en conséquence:
    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
    
  • Ensuite, il va vers le sud 2 spots et M est maintenant 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
    
  • Maintenant, il se déplace de 1 place vers l'ouest et M devient 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
    
  • Après avoir déplacé 3 spots vers le nord, il quitte la ville! Par conséquent, 3 est la berceuse de cet pyromane:
        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
    

Étant donné une matrice N × N (vous pouvez également prendre N comme entrée en option ), trouvez la berceuse de l'incendiaire. J'ai écrit un programme avec lequel vous pouvez générer plus de cas de test et visualiser le chemin du pyromane: essayez-le en ligne!

  • Vous pouvez supposer que le pyromane n'avoir une berceuse (qui est, il peut effectivement sortir de la matrice).
  • La matrice ne contiendra que des entiers positifs inférieurs ou égaux à 9 (chiffres), pour plus de simplicité. Les solutions qui gèrent tout entier positif sont les bienvenues.
  • Notez que l'incendiaire peut atterrir sur un endroit qu'ils ont déjà brûlé, au cas où le sentiment qu'ils emménager serait différent de la première fois. Dans un tel scénario, prenez simplement la valeur de cet élément et déplacez-vous à nouveau comme d'habitude.
  • Vous pouvez concurrencer dans n'importe quel langage de programmation et pouvez prendre des entrées et fournir des sorties par n'importe quelle méthode standard , tout en prenant note que ces failles sont interdites par défaut. Il s'agit de , donc la soumission la plus courte (en octets) pour chaque langue l' emporte.

Cas de test

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

Berceuse: 9
-------------
2 1 2 1
3 1 1 2
1 2 2 1
1 1 1 3

Berceuse: 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

Berceuse: 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

Berceuse: 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

Berceuse: 3
-------------

Les matrices dans un format différent:

[[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]]

Le cinquième cas de test est très intéressant à visualiser .

M. Xcoder
la source
1
C'est comme une généralisation de Skip like a Rabbit en deux dimensions, avec un objectif légèrement différent. La thématique de ce challenge et son titre sont inspirés d' une chanson de Hozier
Mr. Xcoder
que se passe-t-il lorsque l'incendiaire atterrit sur une place déjà brûlée?
Level River St
2
Pouvons-nous supposer que le pyromane n'est pas réellement un pyromane et fait plutôt quelque chose de bien à chaque endroit plutôt que de le brûler? +1 pour une très bonne idée :)
ElPedro
2
@ElPedro Bien sûr, une version alternative pour vous: imaginez une abeille volant dans le jardin et cueillant ses fleurs à polliniser selon un schéma très spécifique. : D Joyeux golf amical!
M. Xcoder,
1
C'est une bien meilleure idée. Si je pouvais encore voter, je le ferais.
ElPedro

Réponses:

11

MATL , 32 octets

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

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Comment ça marche

La matrice d'entrée est remplie d'un cadre de cinq zéros, donc par exemple

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

devient

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

Le cadre de zéros est utilisé pour détecter quand l' abeille pyromane a quitté la matrice. L'extension avec cinq zéros garantit qu'un déplacement modulaire de la longueur jusqu'à 9dans n'importe quelle direction à partir de n'importe quelle entrée non nulle atterrira correctement dans un zéro sans s'enrouler autour d'une entrée non nulle.

En coordonnées matricielles, l'abeille commence à l'entrée (6,6)de la matrice étendue. Il lit cette entrée et met à jour les coordonnées selon les besoins, en appliquant un déplacement (modulaire) de la longueur de lecture dans la direction correspondante. Ceci est répété en boucle jusqu'à ce que la valeur lue soit 0. L'entrée qui a été lue avant celle-ci (c'est-à-dire la dernière entrée non nulle) est la sortie.

Les coordonnées sont en fait stockées sous la forme d'un nombre complexe, ainsi (6,6)devient par exemple 6+6j. De cette façon, les quatre directions cycliques peuvent être réalisées en tant que puissances de l'unité imaginaire. La puissance correspondante ( j, 1, -jou -1) est multiplié par l'entrée de lecture pour obtenir le déplacement complexe qui est utilisé pour la mise à jour des coordonnées.

Les valeurs lues successivement sont conservées sur la pile. Lorsque la boucle est terminée, la pile contient toutes les valeurs de lecture non nulles dans l'ordre, puis la dernière valeur de lecture qui est 0, puis les dernières coordonnées complexes. Le troisième élément supérieur est donc la sortie requise.

Luis Mendo
la source
1
+1 pour une approche très innovante.
LastStar007
7

JavaScript (ES6), 70 68 octets

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

Essayez-le en ligne!

Commenté

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

Étant donné que le signe du modulo en JS est celui du dividende, la direction est mise à jour de cette façon:

 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
la source
4

Fusain , 25 18 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

PS

Imprimez la chaîne d'entrée, mais ne déplacez pas la position d'impression.

Faites pivoter le pivot vers la gauche pour que le sens d'impression soit maintenant vers le haut.

WKK«

Répétez l'opération tant qu'il y a un caractère sous la position d'impression.

≔ιθ

Enregistrez le caractère dans une variable.

×Iι¶

Attribuez un caractère à un nombre et imprimez autant de retours à la ligne. Comme la direction d'impression est maintenant vers le haut, cela finit par imprimer horizontalement. Le résultat est que nous avons déplacé la position d'impression dans la direction souhaitée du montant donné par le nombre sous la position d'impression.

↷»

Faites pivoter le pivot de sorte que les sauts de ligne suivants déplacent la position d'impression dans le sens des aiguilles d'une montre pour le prochain passage de la boucle.

F⟦ωθ⟧¿ιι⎚

Malheureusement, nous avons encore l'entrée encombrant notre toile, et encore plus malheureusement, si nous effaçons la toile nous effaçons également notre variable. Donc, c'est un peu une astuce: une liste de la chaîne vide et la variable est bouclée. Au premier passage de la boucle, la variable de boucle est vide, donc le canevas et la variable de boucle et la variable de résultat sont tous effacés. Mais la boucle n'est pas terminée! Au deuxième passage de la boucle, nous avons toujours accès à notre variable soigneusement préservée dans notre liste de boucles. Il ne reste plus qu'à l'imprimer.

⎚θ

Effacez le canevas et imprimez la variable enregistrée. (Merci à @ ASCII uniquement pour la correction de Charcoal.)

Neil
la source
2

Python 2 , 85 84 octets

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

Essayez-le en ligne!

Astuce du chapeau à M. Xcoder pour 1 octet.

Chas Brown
la source
2

Charbon de bois , 50 49 46 34 33 26 octets

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

Essayez-le en ligne

Le lien est vers la version détaillée du code

L'entrée doit être N sur sa propre ligne, puis les lignes du tableau sur des lignes distinctes après cela.

Toutes les façons de supprimer les octets sont les bienvenues et recherchées, car je ne suis pas un bon golfeur au charbon de bois!

-12 octets grâce à @Neil! -1 octet grâce à @ ASCII uniquement! -7 octets grâce à @ ASCII uniquement (modification d'un bug qui provoquait la Clearréinitialisation des variables)

Zacharý
la source
1

Rouge , 145 octets

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]

Essayez-le en ligne!

Plus lisible:

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
la source
1

Perl 6 , 62 octets

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

Essayez-le en ligne!

Prend la matrice sous forme de liste plate et de largeur.

nwellnhof
la source
1

Nettoyer , 141 octets

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

Essayez-le en ligne!

Définit la fonction ? :: {#{#Int}} -> Int, en prenant un tableau sans boîte de tableaux d'entiers sans boîte et en retournant le résultat.

Οurous
la source
1

Java 8, 121 octets

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

Essayez-le en ligne.

Alternative avec le même nombre d' octets de 121 octets :

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

Utilise try-finally au lieu de vérifier si la x,ycoordonnée est toujours dans les limites.

Essayez-le en ligne.

Explication:

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
la source
0

Perl 5 , 92 octets

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

Essayez-le en ligne!

Comment?

L'ensemble des cartes imbriquées et la jointure produisent ceci:

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

qui est ensuite évalué pour déterminer si la boucle se termine. Étant donné que le booléen est évalué de gauche à droite, la valeur de $nchange réellement (jusqu'à) quatre fois au cours de l'évaluation. Parce que la logique booléenne court-circuite en Perl, la valeur de $nest la berceuse à la sortie de la boucle.

Xcali
la source
0

Python 3 , 85 84 octets

xcoder: -1 (je ne me souviens jamais de l'astuce + ~)

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

Essayez-le en ligne!

Au lieu de se déplacer dans des directions différentes (E, S, W, N), cette solution se déplace toujours vers l'est et fait pivoter la grille dans le sens antihoraire après chaque déplacement. Après la rotation, ce qui était la dernière colonne est maintenant la première ligne, donc si l'index de la ligne est inférieur à zéro, cela signifie que nous avons quitté le tableau.

RootTwo
la source
84 octets : -d-1=>+~d
M. Xcoder
0

Rétine , 161 octets

.
 $.%`*_#$&*
(?<=(.+¶)+|^)
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

Essayez-le en ligne!

TwiNight
la source