Slither Like a Snake

21

L'idée

Nous avons déjà fait des spirales matricielles, et des rotations complètes, et même des rotations diagonales , mais pas, autant que je sache, des rotations de serpents !

Qu'est-ce qu'une rotation de serpent?

Imaginez les rangées d'une matrice serpentant d'avant en arrière, avec des séparateurs entre eux comme les séparateurs d'une longue file d'attente:

    +--------------+
      1  2  3  4  5|
    +------------  |
    |10  9  8  7  6|
    |  +-----------+
    |11 12 13 14 15|
    +------------  |
     20 19 18 17 16|
    +--------------+

Imaginez maintenant faire pivoter ces éléments par 2. Chaque élément avance, comme les personnes se déplaçant en ligne, et les éléments à la fin se répandent et reviennent au début:

    +--------------+
-->  19 20  1  2  3|
    +------------  |
    | 8  7  6  5  4|
    |  +-----------+
    | 9 10 11 12 13|
    +------------  |
<--  18 17 16 15 14|
    +--------------+

S'il y a un nombre impair de lignes, il sortira par la droite, mais continuera au début. Par exemple, voici une rotation de 3:

    +--------------+
      1  2  3  4  5|
    +------------  |
    |10  9  8  7  6|
    |  +-----------+
    |11 12 13 14 15
    +--------------+


    +--------------+
-->  13 14 15  1  2|
    +------------  |
    | 7  6  5  4  3|
    |  +-----------+
    | 8  9 10 11 12  -->
    +--------------+

Une rotation négative vous fera reculer. Voici une rotation de -2:

    +--------------+
<--   3  4  5  6  7|
    +------------  |
    |12 11 10  9  8|
    |  +-----------+
    |13 14 15  1  2  <--
    +--------------+

Le défi

Votre fonction ou programme prendra 2 entrées, dans n'importe quel format pratique:

  • Une matrice
  • Un entier (positif ou négatif) indiquant le nombre d'emplacements pour le faire pivoter.

Il renverra:

  • La matrice tournée

Remarques:

  • Code golf. Le moins d'octets gagne.
  • Les matrices n'ont pas besoin d'être carrées, mais contiendront au moins 2 lignes et 2 colonnes
  • Les entiers positifs feront pivoter la ligne 1 vers la droite
  • Les entiers négatifs feront pivoter la ligne 1 vers la gauche
  • Vous pouvez inverser la signification des nombres de rotation positifs / négatifs, si cela vous convient
  • Le numéro de rotation peut être supérieur au nombre d'articles. Dans ce cas, il se terminera. Autrement dit, il sera équivalent au nombre modulo le nombre d'articles.
  • La matrice ne contiendra que des entiers, mais elle peut contenir des entiers, y compris des répétitions

Cas de test

Format:

  • Matrice
  • Numéro de rotation
  • Valeur de retour attendue

4 5
6 7

1

6 4
7 5

2  3  4  5
6  7  8  9
10 11 12 13

-3

5  9  8  7
12 11 10 6
13 2  3  4 

8 8 7 7
5 5 6 6

10

5 5 8 8
6 6 7 7
Jonas
la source
4
Inverser le sens de +/- est très bien. Je pense cependant que l'entrée doit rester en haut à gauche.
Jonah
7
Cela nécessite définitivement une réponse en Python.
640 Ko

Réponses:

7

Gelée , 10 octets

UÐeẎṙṁ⁸UÐe

Un lien dyadique acceptant le marix à gauche et l'entier de rotation à droite (utilise le sens inverse de positif / négatif)

Essayez-le en ligne!

Comment?

UÐeẎṙṁ⁸UÐe - Link: matrix of integers, M; integer, R
 Ðe        - apply to even indices of M:
U          -   reverse each
   Ẏ       - tighten
    ṙ      - rotate left by R
     ṁ     - mould like:
      ⁸    -   chain's left argument, M
        Ðe - apply to even indices:
       U   -   reverse each
Jonathan Allan
la source
6

R , 121 110 101 octets

function(m,n,o=t(m)){o[,j]=o[i<-nrow(o):1,j<-c(F,T)];o[(seq(o)+n-1)%%sum(1|o)+1]=o;o[,j]=o[i,j];t(o)}

Essayez-le en ligne!

Procédure pas à pas

function(m,n) {           # Input: m - matrix, n - shift
  o <- t(m)               # Transpose the matrix, since R works in column-major order
                          # while our snake goes in row-major order
  i <- nrow(o):1          # Take row indices in reverse
  j <- c(F,T)             # Take even column indices (FALSE, TRUE, FALSE, TRUE, ...)
  o[,j] <- o[i,j]         # "Normalize" the matrix by reversing every second column
  o[(seq(o)+n-1) %%       # Perform the shift: add n-1 to indices,
    length(o)+1] <- o     # Modulo sequence length, and +1 again
  o[,j] <- o[i,j]         # Reverse even columns again to return to snake form
  t(o)                    # Transpose the matrix back to orginal shape and return
}
Kirill L.
la source
3

Python 3.8 (pré-version SSSS) , 119 octets

lambda m,r,n=-1:[[m[(k:=(j+(s:=r+i)//w)%h)][::n**k][s%w]for i in range(w:=len(m[0]))][::n**j]for j in range(h:=len(m))]

Une fonction sans nom acceptant matrix, rotationqui donne la nouvelle matrice.
Utilise le signe de rotation opposé.

Essayez-le en ligne!

Comment?

Nous avons configuré n=-1upfront pour économiser sur les parenthèses plus tard et prendre la matrice comme met la rotation comme r.

Une nouvelle matrice est construite avec les mêmes dimensions que m- avec une largeur de w( w:=len(m[0])) et une hauteur de h( h:=len(m)).

Toutes les autres lignes de cette matrice sont inversées ( [::n**j]).

Les valeurs sont recherchées en calculant leur ligne et leur colonne dans l'original, en mutilisant la ligne d'éléments actuelle,, iet la colonne, j...

Nous nous sommes mis sà r+iet kà (j+s//w)%h. kest la ligne de l'original à laquelle accéder pour notre élément actuel.

Afin d'accéder facilement aux lignes indexées impaires à partir de la droite, nous inversons ces lignes avant d'accéder à leurs éléments (avec [:n**k]), cela signifie que l'élément d'intérêt est à s%w.

Jonathan Allan
la source
3

J , 41 30 21 octets

-11 octets grâce à Jonah!

-9 octets grâce à FrownyFrog & ngn!

$@]t@$(|.,@t=.|.@]/\)

Essayez-le en ligne!

Renversé +/-

Galen Ivanov
la source
1
30 octets, +/- non inversé, mais utilise toujours helper: $@]t@$(|.,@(t=.#\,`(|.@,)/.]))( Essayez-le en ligne! )
Jonah
correction: +/- toujours inversée.
Jonah
@Jonah Maintenant c'est J! Je me souviens de vous avoir vu appliquer la même astuce avec l'inversion alternée récemment, mais apparemment vous l'avez oublié. Merci! Lorsque j'essayais de &.perdre l'argument de gauche tout le temps, c'est pourquoi j'ai abandonné.
Galen Ivanov le
1
21 octets , thx @ngn
FrownyFrog
@FrownyFrog Wow, c'est maintenant la moitié de la taille initiale. Je me sens stupide ... Merci!
Galen Ivanov
2

JavaScript (Node.js) , 102 octets

Prend l'entrée comme (matrix)(integer). La signification du signe de l'entier est inversée.

m=>n=>(g=m=>m.map(r=>r.sort(_=>~m,m=~m)))(m.map(r=>r.map(_=>a[(l+n++%l)%l]),l=(a=g(m).flat()).length))

Essayez-le en ligne!

Fonction d'assistance

g

g = m =>        // m[] = input matrix
  m.map(r =>    // for each row r[] in m[]:
    r.sort(_ => //   sort r[]:
      ~m,       //     using either 0 (don't reverse) or -1 (reverse)
      m = ~m    //     and toggling m before each iteration
                //     (on the 1st iteration: m[] is coerced to 0, so it yields -1)
    )           //   end of sort()
  )             // end of map()

Fonction principale

m => n =>                    // m[] = matrix, n = integer
  g(                         // invoke g on the final result
    m.map(r =>               //   for each row r[] in m[]:
      r.map(_ =>             //     for each entry in r[]:
        a[(l + n++ % l) % l] //       get the rotated value from a[]; increment n
      ),                     //     end of inner map()
      l = (                  //     l is the length of a[]:
        a = g(m).flat()      //       a[] is the flatten result of g(m)
      ).length               //       (e.g. [[1,2],[3,4]] -> [[1,2],[4,3]] -> [1,2,4,3])
    )                        //   end of outer map()
  )                          // end of call to g
Arnauld
la source
2

05AB1E , 16 octets

εNFR]˜²._¹gäεNFR

Essayez-le en ligne!

Merci à Emigna pour -5. Malheureusement, je ne vois pas comment jouer la partie redondante. :(

Erik le Outgolfer
la source
1

Fusain , 36 octets

FEθ⎇﹪κ²⮌ιιFι⊞υκIE⪪Eυ§υ⁻κηL§θ⁰⎇﹪κ²⮌ιι

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

Eθ⎇﹪κ²⮌ιι

Inversez les lignes alternées de l'entrée.

F...Fι⊞υκ

Aplatissez le tableau.

Eυ§υ⁻κη

Faites pivoter le réseau aplati.

⪪...L§θ⁰

Divisez le tableau en lignes.

E...⎇﹪κ²⮌ιι

Inversez les rangées alternées.

I...

Convertissez chaque entrée en chaîne et sortez dans le format de sortie par défaut qui est un nombre par ligne avec des lignes à double interligne. (Le formatage avec un séparateur coûterait la longueur du séparateur.)

Neil
la source
1

Pyth, 20 octets

L.e_W%k2bbyclQ.>syQE

Essayez-le en ligne ici .

Sok
la source
1

Japt , 28 octets

mÏ%2©XÔªX
c éV òUÎl
W©UªßV1V

Essayez-le

Réponse du port d' Arnauld . Le plus grand défi était de créer une fonction réutilisable. En particulier, il existe une fonction d'aide pour inverser toutes les autres lignes. L'approche que je prends est de faire un appel récursif et selon qu'une variable est définie ou non.

Transpiled JS:

// U: first input argument (matrix)
// m: map it through a function
U = U.m(function(X, Y, Z) {
  // if the row index is even, don't alter it
  // if the row index is odd, reverse it (w)
  return Y % 2 && X.w() || X
});
V = U
  // flatten the matrix
  .c()
  // shift by the amount specified in second argument
  .é(V)
  // partition back to matrix
  .ò(
    // the number of columns should be the same as input
    U.g().l()
  );
// if W is specified, return the result from the first line
W && U ||
  // otherwise, make a recursive call with the shifted matrix
  rp(V, 1, V)
dana
la source
1

Python 3 , 94 octets

lambda m,n:g(roll(g(m),n))
g=lambda b:[b[i][::(-1)**i]for i in r_[:len(b)]]
from numpy import*

Essayez-le en ligne!

Utilisé l'inversion de ligne impaire de la réponse de Jonathan Allan .

lambda m,n:g(roll(g(m),n))  #reverse odd rows, shift elements, then reverse odd rows again.
g=lambda b:[b[i][::(-1)**i] #reverse odd rows
    for i in r_[:len(b)]]   #r_[:x] = range(x)
from numpy import*          #roll() and r_[]
attinat
la source
1

C # (Visual C # Interactive Compiler) , 141 octets

a=>n=>{for(dynamic l=a.Length,w=a.GetLength(1),i=l,j,b=a.Clone();i-->0;)a[(j=(i+n%l+l)%l)/w,j/w%2<1?j%w:w-j%w-1]=b[i/w,i/w%2<1?i%w:w-i%w-1];}

Essayez-le en ligne!

-5 octets au total grâce à @someone!

Fonction anonyme qui effectue une modification sur place de la matrice d'entrée.

Une boucle unique parcourt les cellules. Vous pouvez numériser de haut en bas et de gauche à droite en utilisant les formules suivantes:

  • row=i/w
  • col=i%w

iest un compteur de boucles et wle nombre de colonnes. Cela varie légèrement lors de la numérisation dans un motif de serpent.

  • row=i/w
  • col=i%w (0e, 2e, 4e, etc. rangée)
  • col=w-i%w-1 (1ère, 3ème, 5ème, etc. rangée)

Une autre chose à noter est que %dans C # ne se convertit pas en une valeur positive comme il le fait dans certains autres langages. Quelques octets supplémentaires sont nécessaires pour tenir compte de cela.

// a: input matrix
// n: number of cells to rotate
a=>n=>{
  for(
    // l: total number of cells
    // w: number of columns
    // i: loop index
    // j: offset index
    // b: copy of input matrix
    dynamic
      l=a.Length,
      w=a.GetLength(1),
      i=l,j,
      b=a.Clone();
    // iterate from i down to 0
    i-->0;
  )
    // calculate the offset `j` and use
    // the above formulas to index
    // into `a` for setting a value
    a[
      (j=(i+n%l+l)%l)/w,
      j/w%2<1?j%w:w-j%w-1
    ]=
    // use the un-offset index `i` and
    // the above formulas to read a
    // value from the input matrix
    b[
      i/w,
      i/w%2<1?i%w:w-i%w-1
    ];
}
dana
la source
Vous pouvez économiser 3 octets en fusionnant les déclarations avec dynamic; commenter aussi l. Essayez-le en ligne!
mon pronom est monicareinstate
Nice :) Cette déclaration peut également être déplacée dans la boucle. J'ai tendance à utiliser varpour le golf qui ne vous permet pas de déclarer une liste de variables. Probablement pourquoi j'ai raté ça. Bonne prise!
dana
Débarrassez-vous yentièrement pour économiser 2 octets: essayez-le en ligne!
mon pronom est monicareinstate
@quelqu'un - merci!
dana
TIO 135 avec tableau 1d et entrée de largeur.
mon pronom est monicareinstate