Slither Like a Snake


21

L'idea

Abbiamo già fatto spirali di matrice in precedenza, rotazioni complete e persino rotazioni diagonali , ma non, per quanto posso trovare, rotazioni di serpenti !

Che cos'è una rotazione del serpente?

Immagina le file di una matrice che serpeggia avanti e indietro, con divisori tra loro come i divisori di una lunga coda:

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

Ora immagina di ruotare questi oggetti di 2. Ogni oggetto avanza, come le persone che si muovono in una linea, e gli oggetti alla fine si riversano e ritornano all'inizio:

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

Se c'è un numero dispari di righe, uscirà da destra, ma andrà comunque a capo all'inizio. Ad esempio, ecco una rotazione 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  -->
    +--------------+

Una rotazione negativa ti porterà indietro. Ecco una rotazione -2:

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

La sfida

La tua funzione o programma prenderà 2 ingressi, in qualsiasi formato conveniente:

  • Una matrice
  • Un numero intero (positivo o negativo) che indica il numero di posizioni in cui ruotarlo.

Restituirà:

  • La matrice ruotata

Gli appunti:

  • Codice golf. Vince il minor numero di byte.
  • Le matrici non devono necessariamente essere quadrate, ma conterranno almeno 2 righe e 2 colonne
  • Gli interi positivi ruotano la riga 1 verso destra
  • Gli interi negativi ruotano la riga 1 verso sinistra
  • È possibile invertire il significato dei numeri di rotazione positivi / negativi, se conveniente
  • Il numero di rotazione può essere maggiore del numero di elementi. In tal caso, andrà a capo. Cioè, sarà equivalente al numero modulo il numero di elementi.
  • La matrice conterrà solo numeri interi, ma può contenere numeri interi, comprese le ripetizioni

Casi test

Formato:

  • Matrice
  • Numero di rotazione
  • Valore di ritorno atteso

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

4
Il significato inverso di +/- va bene. Penso che l'ingresso dovrebbe rimanere in alto a sinistra però.
Giona

7
Questo ha sicuramente bisogno di una risposta in Python.
640 KB

Risposte:


7

Gelatina , 10 byte

UÐeẎṙṁ⁸UÐe

Un collegamento diadico che accetta il marix a sinistra e il numero intero di rotazione a destra (usa il significato inverso di positivo / negativo)

Provalo online!

Come?

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

6

R , 121 110 101 byte

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

Provalo online!

Procedura dettagliata

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
}

3

Python 3.8 (pre-releaseSse) , 119 byte

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

Una funzione senza nome matrix, rotationche accetta che produce la nuova matrice.
Utilizza il segno di rotazione opposto.

Provalo online!

Come?

Abbiamo impostato in n=-1anticipo per salvare le parentesi in un secondo momento e prendere la matrice come me la rotazione come r.

Una nuova matrice è costruita con le stesse dimensioni di m- con una larghezza di w( w:=len(m[0])) e un'altezza di h( h:=len(m)).

Ogni altra riga di questa matrice è invertita ( [::n**j]).

I valori vengono cercati calcolando la loro riga e colonna nell'originale, musando gli elementi correnti riga i, e colonna, j...

Abbiamo impostato ssu r+ie ksu (j+s//w)%h. kè la riga dell'originale a cui accedere per il nostro elemento corrente.

Per accedere facilmente alle righe indicizzate dispari da destra, invertiamo tali righe prima di accedere ai loro elementi (con [:n**k]), questo significa che l'elemento di interesse è a s%w.


3

J , 41 30 21 byte

-11 byte grazie a Giona!

-9 byte grazie a FrownyFrog & ngn!

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

Provalo online!

Reversed +/-


1
30 byte, +/- non invertito, ma utilizza ancora l'helper: $@]t@$(|.,@(t=.#\,`(|.@,)/.]))( Provalo online! )
Giona

correzione: +/- ancora invertito.
Giona il

@Jonah Questo è J! Ricordo di averti visto applicare di recente lo stesso trucco con l'inversione alternata, ma a quanto pare me ne sono dimenticato. Grazie! Quando provavo &.perdevo continuamente l'argomento sinistro, ecco perché ho rinunciato.
Galen Ivanov,

1
21 byte , thx @ngn
FrownyFrog,

@FrownyFrog Wow, ora è la metà della dimensione iniziale. Mi sento stupido ... Grazie!
Galen Ivanov

2

JavaScript (Node.js) , 102 byte

Accetta input come (matrix)(integer). Il significato del segno dell'intero è invertito.

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))

Provalo online!

Funzione di aiuto

g viene utilizzata per "snakify" o "unsnakify" una matrice invertendo le righe con indici dispari.

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()

Funzione 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


1

Carbone , 36 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

Eθ⎇﹪κ²⮌ιι

Invertire righe alternate dell'input.

F...Fι⊞υκ

Appiattire l'array.

Eυ§υ⁻κη

Ruota l'array appiattito.

⪪...L§θ⁰

Dividi nuovamente l'array in righe.

E...⎇﹪κ²⮌ιι

Inverti righe alternate.

I...

Converti ogni voce in stringa e output nel formato di output predefinito che è un numero per riga con righe a spaziatura doppia. (La formattazione con un separatore costerebbe la lunghezza del separatore.)


1

Pyth, 20 byte

L.e_W%k2bbyclQ.>syQE

Provalo online qui .


1

Japt , 28 byte

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

Provalo

Porto di La risposta Arnauld . La sfida più grande era creare una funzione riutilizzabile. In particolare, esiste una funzione di supporto per invertire ogni altra riga. L'approccio che sto adottando è quello di effettuare una chiamata ricorsiva e dipende dall'impostazione di una variabile.

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)

1

Python 3 , 94 byte

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

Provalo online!

Ho usato l'inversione delle righe dispari dalla risposta di 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_[]


1

C # (compilatore interattivo Visual C #) , 141 byte

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

Provalo online!

-5 byte in totale grazie a @someone!

Funzione anonima che esegue una modifica sul posto della matrice di input.

Un singolo ciclo scorre le celle. È possibile eseguire la scansione dall'alto verso il basso e da sinistra a destra utilizzando le seguenti formule:

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

Dov'è iun contatore di loop ed wè il numero di colonne. Questo varia leggermente quando si esegue la scansione in modo serpente.

  • row=i/w
  • col=i%w (0a, 2a, 4a, ecc. Fila)
  • col=w-i%w-1 (1a, 3a, 5a, ecc. Fila)

Un'altra cosa da notare è che %in C # non viene convertito in un valore positivo come in altre lingue. Per tener conto di questo sono necessari un paio di byte extra.

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

È possibile salvare 3 byte unendo le dichiarazioni con dynamic; commenta anche io. Provalo online!
mio pronome è monicareinstate il

Bello :) Anche quella dichiarazione può essere spostata nel loop. Tendo a usarlo varper il golf che non ti consente di dichiarare un elenco di variabili. Probabilmente perché mi sono perso questo. Buona pesca!
dana,

Sbarazzati del ytutto per salvare 2 byte: provalo online!
mio pronome è monicareinstate il

@someone - grazie!
dana,

TIO 135 con array 1d e input di larghezza.
mio pronome è monicareinstate
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.