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.