Ecco come andiamo


18

Piet è un linguaggio di programmazione interessante per una serie di motivi. Oggi ci concentreremo su un motivo: il comando roll . Il comando roll era originariamente di PostScript ed è un modo efficace per manipolare lo stack.

Il comando roll apre i primi due elementi dello stack e li utilizza come parametri. Chiameremo il primo valore spuntato turnse il secondo depth. Una virata alla profondità n prenderà l'elemento più in alto della pila, lo renderà l'ennesimo elemento nella pila e sposterà ciascuno degli elementi sopra di esso su di uno. Se turns è negativo, ciò viene fatto nella direzione opposta. Cioè, l'ennesimo elemento viene spostato verso l'alto e gli altri elementi vengono spostati verso il basso. Questo è ripetuto abs(turns)volte.

Sfida

Scrivi un programma o una funzione che accetta uno stack e restituisce quello stack dopo aver eseguito un lancio.

Regole

  • L'input e l'output possono essere in un elenco, in una matrice, in una stringa con un delimitatore, passati in un elemento alla volta o in qualsiasi altro formato ragionevole. L'output deve essere nello stesso formato dell'input.
  • depth non sarà mai negativo e non sarà mai maggiore della lunghezza della pila.
  • Lo stack di input conterrà sempre almeno due elementi.
  • Questo è quindi vince la risposta più breve in ogni lingua. Come tale, non accetterò una risposta.
  • Sono vietate le scappatoie standard .

Casi test

in:  out:
2    
4    
1    3
2    4
3    1
4    2
5    5
6    6

in:  out:
-2   
3
1    2
2    3
3    1

in:  out:
-42
0
1    1
2    2
3    3
4    4
5    5

2
vince la risposta più breve in ogni lingua , non è così che funziona [code-golf]. Vince la risposta più breve. Periodo.
— mbomb007,

4
@ mbomb007 ahem che dire di questo
— Christopher

7
Ero molto deluso dal fatto che ciò non implicasse in alcun modo il rick roll
— Christopher,

2
@ mbomb007 Non lo vedo nella descrizione del tag o in una rapida ricerca su meta, quindi non penso che sia così.
— Mike Bufardeci,

2
@ mbomb007 Se desideri che lo cambi, ti preghiamo di fornire una sorta di argomento diverso dal dire "hai torto e ho ragione" più e più volte. C'è un precedente per questo, che hai respinto, e da nessuna parte dice che le sfide richiedono esattamente un vincitore o che una risposta deve essere accettata.
— Mike Bufardeci,

Risposte:


8

Haskell , 64 62 byte

Modifica: -2 byte: @xnor ha visto qualcosa su cui avevo pensato di sbagliato.

rprende e restituisce un elenco di Ints.

r(t:d:l)|d<1=l|(x,y)<-d%l,(z,w)<-mod t d%x=w++z++y
(%)=splitAt

Provalo online!

splitAt n ldivide un elenco lall'indice n, modcalcola il resto della divisione, ++concatena gli elenchi.


1
Penso che puoi tagliare 2 byte definendo (%)=splitAtinfix.
— xnor

@xnor Oh, in qualche modo mi ero convinto che non avrebbe funzionato
— Ørjan Johansen,

8

JavaScript (ES6), 49 47 byte

(t,d,...a)=>a.splice(t=(t%d+d)%d,d-t).concat(a)

Modifica: salvato 2 byte grazie a @Shaggy prendendo gli elementi dello stack come parametri separati. Spiegazione:

  • Quando la virata è un multiplo della profondità, non accade nulla. Il primo passo è quindi calcolare la profondità del modulo di virata. Dato che JavaScript sa solo calcolare il resto, devo farlo in due passaggi.
  • Un giro di 1sposta l'elemento superiore depthsull'elemento. Una svolta di 2sposta i due elementi superiori, ecc. Tuttavia, è possibile ottenere ciò anche spostando gli elementi tra svolta e profondità in avanti. splicerimuove quegli elementi e concatli antepone agli elementi rimanenti. (Avrei potuto usare una comprensione dell'array invece perché ha la stessa lunghezza.)
  • A differenza slicedel secondo parametro, spliceè il numero di elementi da rimuovere.

Non è (t%d+d)%dlo stesso di t%d?
— Luca,

@Luke No, %è resto, quindi dà una risposta negativa quando tè negativa.
— Neil,

È possibile salvare 2 byte utilizzando (t,d,...a)=>come le regole consentono il passaggio dell'input in un elemento alla volta.
— Shaggy,

@Shaggy Grazie, non me ne ero accorto.
— Neil,

7

CJam, 31 byte

)\):N@\,0a|={NW*1$1$>)\+@@<\+}*

L'input e l'output sono array sullo stack, con l'ultimo elemento che rappresenta la parte superiore dello stack.

Traccia dello stack:

                   e# Stack:                [6 5 4 3 2 1 4 2]
)                  e# Take out first value: [6 5 4 3 2 1 4] 2
\                  e# Swap:                 2 [6 5 4 3 2 1 4]
)                  e# Take out first value: 2 [6 5 4 3 2 1] 4
:N                 e# Store in N:           2 [6 5 4 3 2 1] 4; N=4
@                  e# Rotate:               [6 5 4 3 2 1] 4 2
\                  e# Swap:                 [6 5 4 3 2 1] 2 4
,                  e# Range:                [6 5 4 3 2 1] 2 [0 1 2 3]
0                  e# Push 0:               [6 5 4 3 2 1] 2 [0 1 2 3] 0
a                  e# Wrap in array:        [6 5 4 3 2 1] 2 [0 1 2 3] [0]
|                  e# Logical or:           [6 5 4 3 2 1] 2 [0 1 2 3]
                   e# (This will replace an empty array with [0] to handle a special case of n=0)
=                  e# Get array value:      [6 5 4 3 2 1] 2
{NW*1$1$>)\+@@<\+} e# Push block:           [6 5 4 3 2 1] 2 {NW*1$1$>)\+@@<\+}
*                  e# Preform n times:      [6 5 4 3 2 1]
  N                e# Push N:               [6 5 4 3 2 1] 4
  W*               e# Negate:               [6 5 4 3 2 1] -4
  1$               e# Copy element 1 back:  [6 5 4 3 2 1] -4 [6 5 4 3 2 1]
  1$               e# Copy element 1 back:  [6 5 4 3 2 1] -4 [6 5 4 3 2 1] -4
  >                e# Slice a[-4:]          [6 5 4 3 2 1] -4 [4 3 2 1]
  )                e# Take first value:     [6 5 4 3 2 1] -4 [4 3 2] 1
  \                e# Swap:                 [6 5 4 3 2 1] -4 1 [4 3 2]
  +                e# Append:               [6 5 4 3 2 1] -4 [1 4 3 2]
  @@               e# Rotate twice:         [1 4 3 2] [6 5 4 3 2 1] -4
  <                e# Slice a[:-4]:         [1 4 3 2] [6 5]
  \                e# Swap:                 [6 5] [1 4 3 2]
  +                e# Append:               [6 5 1 4 3 2]
e# Preform the block again:                 [6 5 2 1 4 3]

6

Mathematica, 58 50 byte

Modifica: grazie a Martin Ender per aver salvato 8 byte.

Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&@@#&

Spiegazione:

Funzione pura che prevede un elenco in cui l'inizio dell'elenco rappresenta la parte superiore dello stack. Passiamo gli elementi dell'elenco nella funzione pura Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&. xè impostato sulla sequenza di elementi che iniziano con il terzo argomento., quindi ruotiamo i primi #2(secondo argomento) elementi xa sinistra #(primo argomento) volte, quindi Joini restanti elementi di x.

Salverebbe 3byte se avessimo passato direttamente gli elementi dello stack come argomenti alla funzione anziché essere inizialmente in un elenco, ma i formati di input e output non corrisponderebbero.

Soluzione originale:

#/.{t_,d_,x___}:>{x}~Take~d~RotateLeft~t~Join~Drop[{x},d]&

C'è qualcosa di veramente soddisfacente in questa catena di funzioni infix. Sostituisce un elenco con il primo elemento t, il secondo elemento de gli elementi rimanenti xcon il risultato di ruotare i primi delementi {x}verso sinistra te unire gli elementi rimanenti di {x}.


1
Bello! È possibile salvare 3 byte utilizzando una funzione di prefisso a un byte ±all'interno di una regola di sostituzione e un altro 1 byte sfruttando TakeDropcome segue: ±{t_,d_,x___}:=#~RotateLeft~t~Join~#2&@@{x}~TakeDrop~d
— Greg Martin

Stavo per commentare la stessa cosa di Greg, ma in realtà puoi andare ancora più breve. O esegui una funzione variadica senza nome (anche se è un po 'complicata perché richiede input ...&[1, 1, 3, 4]e return {3, 4}o lo fa manualmente con un Applyall'inizio: Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&@@#&(solo per essere chiari, il mio primo suggerimento omette il@@#& .)
— Martin Ender

5

Rubino, 40 byte

x=->s{n,d,*s=s;s[0,d]=s[0,d].rotate n;s}

Provalo online!

Prende l'input come elenco, restituisce un elenco. Il fatto che rotateesista un built-in in grado di gestire rotazioni sia positive che negative rende questo banale.


5

Python, 141 98 87 74 byte

11 byte salvati grazie a @Cole

def f(s):*s,d,t=s;n=len(s)-d;return s*0**d or s[:n]+s[-t%d-d:]+s[n:-t%d-d]

Riceve input come un elenco, in cui l'ultimo elemento è in cima allo stack.

Utilizza il trucco 0ⁿ per filtrare l'operatore modulo di regolazione del segno a profondità zero e python per determinare la parte dell'elenco da tagliare.


Perché non prenderlo e basta f(s,t,d)?
— Cole

@Cole Grazie per il disimballaggio! Tuttavia, non riesco a capire cosa intendevi f(s,t,d)(l'input è l'intero stack).
— Uriel,

fantastica idea per il disimballaggio, anche se non credo che dovresti credermi (stavo suggerendo solo di prendere le variabili separatamente). Le specifiche di input sembrano permetterti di prendere la profondità e girare come variabili separate dallo stack: "Input e output possono essere in un elenco, array, stringa con un delimitatore, passato in un elemento alla volta o in qualsiasi altro formato ragionevole. L'output deve essere nello stesso formato dell'input. "
— Cole

È possibile salvare 1 byte con r=-t%d-d. Inoltre, la sostituzione s*0**dcon s*(d<1)mantiene il conteggio dei byte ma forse migliora la leggibilità (non è questo l'obiettivo). 0**0==1Tuttavia non lo sapevo in Python, è interessante.
— Ben Frankel,

@BenFrankel non posso salvare -t%d-dcome un valore (come ho fatto prima), perché quando dviene 0questo sarebbe innescare un'eccezione di divisione per zero.
— Uriel,

3

JavaScript ES6, 109 92 byte

x=>{for(i=x.shift(),i=i>0?i:-i,j=x.shift();i-->0&&j>0;)x=x.splice(j,1).concat(x);return x}

Provalo online!

Riceve input sotto forma di un array di numeri interi.
Ha anche il conteggio per la freccia: P

Spiegazione:

Il codice utilizza la funzione shift per estrarre i primi due elementi dell'elenco.

Ottiene quindi il valore assoluto del primo elemento, che è il numero di turni.

Poiché Javascript è a zero, l'indice di profondità deve essere ridotto di 1.

Se l'indice di profondità fosse 0 o 1, nulla dovrebbe cambiare, ma a causa della diminuzione, l'indice di 0 causerebbe cambiamenti. Pertanto uscire dal loop se l'indice di profondità non è <= 0.

La funzione splice (a, b) restituisce l'array secondario di lunghezza b con l'indice iniziale a dall'array e lascia l'array originale senza quegli elementi.

Se concatenato con il resto dell'array originale, si tratta di una singola rotazione dell'array in corrispondenza dell'indice di profondità.

Eseguendo questa operazione n volte, dove n è il numero di giri, l'array risultante è il risultato dell'operatore del rotolo.



2

TI-Basic, 141 150 byte (non competitivo)

Prompt L1
L1(1→T
L1(2→D
seq(L1(C),C,3,dim(L1→L1
If TD>0
Then
For(A,1,T
L1(1→B
For(C,2,D
L1(C→L1(C–1
End
B→L1(D
End
End
If TD<0
Then
For(A,1,-T
L1(D→B
For(C,D,2,-1
L1(C–1→L1(C
End
B→L1(1
End
End
L1

Modifica: caso fisso in cui la profondità è zero (+9 byte)

TI-Basic non supporta elenchi di lunghezza 0, quindi questo approccio non funziona per un input di due lunghezze.

Spiegazione:

Prompt L1                # 4 bytes, input list
L1(1→T                   # 7 bytes, turns
L1(2→D                   # 7 bytes, depth
seq(L1(C),C,3,dim(L1→L1   # 18 bytes, remove turns and depth from list
If TD>0                  # 6 bytes, if turns is positive and depth is nonzero (can't be negative)
Then                     # 2 bytes
For(A,1,T                # 7 bytes, do this 'turns' times
L1(1→B                    # 7 bytes, backup the first item
For(C,2,D                # 7 bytes, shuffle the rest along
L1(C→L1(C–1               # 12 bytes
End                      # 2 bytes
B→L1(D                   # 7 bytes, restore the backup to where it should be
End                      # 2 bytes
End                      # 2 bytes
If TD<0                  # 6 bytes, if T is negative and D is nonzero
Then                     # 2 bytes
For(A,1,-T               # 8 bytes, do this -'turns' times
L1(D→B                   # 7 bytes, backup the Dth item
For(C,D,2,-1             # 10 bytes, shuffle the items the other way
L1(C–1→L1(C              # 12 bytes
End                      # 2 bytes
B→L1(1                   # 7 bytes, restore backup to where it belongs
End                      # 2 bytes
End                      # 2 bytes
L1                       # 2 bytes, implicitly return

Penso che anche tu abbia bisogno di codice per gestire il caso dell'elenco a 2 elementi; attualmente si verificherà un errore al seq(.
— lirtosiast,

1

Lotto, 163 byte

@set s=
@set r=
@set/ad=%2,t=(%1%%d+d)%%d
:l
@shift
@set/af=t-=1,f^^=d-=1
@if %f% lss 0 (set r=%r% %2)else set s=%s% %2
@if not "%3"=="" goto l
@echo%r%%s%

Accetta input come parametri della riga di comando e genera un elenco separato da spazi. I parametri tra te dvengono estratti nella rvariabile in modo che possano essere anteposti alla svariabile, che riceve tutti gli altri parametri.

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.