Tak się toczymy

18

Piet jest interesującym językiem programowania z wielu powodów. Dzisiaj skupimy się na jednym celu: poleceniu rzutu . Polecenie roll pochodziło z PostScript i jest potężnym sposobem na manipulowanie stosem.

Polecenie roll wyświetla dwa górne elementy stosu i używa ich jako parametrów. Nazwiemy pierwszą wartość pop up turnsi drugą depth. Obrót do głębokości n zajmie najwyższy element stosu, uczyni go n-tym elementem stosu i przesunie każdy z elementów powyżej jednego o jeden. Jeśli turns jest ujemne, dzieje się to w przeciwnym kierunku. Oznacza to, że n-ty element jest przenoszony na górę, a pozostałe elementy są przenoszone w dół. To się powtarza abs(turns).

Wyzwanie

Napisz program lub funkcję, która pobiera stos i zwraca ten stos po wykonaniu rzutu.

Zasady

  • Dane wejściowe i wyjściowe mogą być w postaci listy, tablicy, ciągu z ogranicznikiem, przekazywanych w jednym elemencie na raz lub w innym rozsądnym formacie. Dane wyjściowe muszą być w tym samym formacie co dane wejściowe.
  • depth nigdy nie będzie ujemny i nigdy nie będzie większy niż długość stosu.
  • Stos wejściowy zawsze będzie zawierał co najmniej dwa elementy.
  • To jest więc wygrywa najkrótsza odpowiedź w każdym języku. W związku z tym nie przyjmę odpowiedzi.
  • Standardowe luki są zabronione.

Przypadki testowe

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
Mike Bufardeci
źródło
2
wygrywa najkrótsza odpowiedź w każdym języku , nie tak działa [code-golf]. Najkrótsza odpowiedź wygrywa. Kropka.
mbomb007
4
@ mbomb007 ahem co z tym
Christopher
7
Byłem bardzo rozczarowany, że w żaden sposób nie wiązało się to z rick rollowaniem
Christopher
2
@ mbomb007 Nie widzę tego w opisie tagu ani w szybkim wyszukiwaniu meta, więc nie sądzę, że tak jest.
Mike Bufardeci,
2
@ mbomb007 Jeśli chcesz, żebym to zmienił, podaj jakiś argument inny niż powtarzanie „jesteś w błędzie, a ja mam rację”. Jest to precedens, który odrzuciłeś i nigdzie nie jest powiedziane, że wyzwania wymagają dokładnie jednego zwycięzcy lub że odpowiedź musi zostać zaakceptowana.
Mike Bufardeci,

Odpowiedzi:

8

Haskell , 64 62 bajtów

Edycja: -2 bajty: @xnor widział coś, o czym myślałem źle.

rpobiera i zwraca listę Ints.

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

Wypróbuj online!

splitAt n ldzieli listę lna indeks n, modoblicza pozostałą część podziału, ++łączy listy.

Ørjan Johansen
źródło
1
Myślę, że możesz wyciąć 2 bajty, definiując (%)=splitAtinfix.
xnor
@xnor Och, jakoś przekonałem się, że to nie zadziała
Ørjan Johansen
8

JavaScript (ES6), 49 47 bajtów

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

Edycja: Zapisano 2 bajty dzięki @Shaggy, biorąc elementy stosu jako osobne parametry. Wyjaśnienie:

  • Kiedy zakręt jest wielokrotnością głębokości, nic się nie dzieje. Pierwszym krokiem jest zatem obliczenie głębokości modułu obrotu. Ponieważ JavaScript umie tylko obliczyć resztę, muszę to zrobić w dwóch krokach.
  • Kolejność 1przesuwa górny element do depthelementu. Kolejność 2przesuwa dwa górne elementy itp. Można to jednak osiągnąć, przesuwając elementy między zakrętem a głębokością do przodu. spliceusuwa te elementy i concatdołącza je do pozostałych elementów. (Mógłbym zamiast tego użyć rozumienia tablicowego, ponieważ ma on tę samą długość.)
  • W przeciwieństwie slicedo drugiego parametru spliceto liczba elementów do usunięcia.
Neil
źródło
Czy to nie (t%d+d)%dto samo co t%d?
Łukasza
@Luke Nie, %jest resztą, więc daje negatywną odpowiedź, gdy tjest negatywna.
Neil,
Możesz zapisać 2 bajty, używając (t,d,...a)=>reguł, które pozwalają na przekazywanie danych wejściowych w jednym elemencie na raz.
Kudłaty
@Shaggy Dzięki, nie zauważyłem tego.
Neil,
7

CJam, 31 bajtów

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

Dane wejściowe i wyjściowe są tablicami na stosie, przy czym ostatni element reprezentuje górę stosu.

Ślad stosu:

                   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]
Esolanging Fruit
źródło
6

Mathematica, 58 50 bajtów

Edycja: Podziękowania dla Martina Endera za zapisanie 8 bajtów.

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

Wyjaśnienie:

Czysta funkcja, która oczekuje listy, w której początek listy reprezentuje górę stosu. Przekazujemy elementy listy do czystej funkcji Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&. xjest ustawiony na sekwencję elementów zaczynającą się od trzeciego argumentu., następnie obracamy pierwsze #2(drugi argument) elementy xw lewo #(pierwszy argument) razy, a następnie Joinpozostałe elementy x.

Oszczędzałoby to 3bajty, gdybyśmy po prostu przekazali elementy stosu jako argumenty bezpośrednio do funkcji, zamiast początkowo znajdować się na liście, ale wtedy formaty wejściowe i wyjściowe nie pasowałyby.

Oryginalne rozwiązanie:

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

Jest coś naprawdę satysfakcjonującego w tym łańcuchu funkcji infix. Zamienia listę na pierwszy element t, drugi element di pozostałe elementy, xw wyniku czego pierwsze delementy zostają obrócone {x}w lewo ti połączone z pozostałymi elementami {x}.

ngenisis
źródło
1
Ładny! Możesz zapisać 3 bajty, używając ±wstawionej jednobajtowej funkcji prefiksu reguły zastępowania, a kolejny 1 bajt, wykorzystując TakeDropw następujący sposób: ±{t_,d_,x___}:=#~RotateLeft~t~Join~#2&@@{x}~TakeDrop~d
Greg Martin
Chciałem po prostu skomentować to samo co Greg, ale tak naprawdę możesz iść nawet krócej. Albo utwórz nienazwaną funkcję wariadyczną (choć jest to nieco podejrzane, ponieważ wymaga wejścia ...&[1, 1, 3, 4]i powrotu, {3, 4}lub wykonaj to ręcznie Applyna początku: Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&@@#&(aby być jasnym, moja pierwsza sugestia pomija @@#&.)
Martin Ender
5

Rubinowy, 40 bajtów

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

Wypróbuj online!

Pobiera dane wejściowe jako listę, zwraca listę. Fakt, że istnieje wbudowany system rotate, który może obsługiwać zarówno dodatnie, jak i ujemne obroty, czyni to banalnym.

Ventero
źródło
5

Python, 141 98 87 74 bajty

11 bajtów zapisanych dzięki @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]

Pobiera dane wejściowe jako listę, gdzie ostatni element jest na górze stosu.

Używa sztuczki 0ⁿ do filtrowania zerowej głębokości i operatora modulo dopasowującego znaki w pythonie, aby określić część listy do pocięcia.

Uriel
źródło
Dlaczego nie wziąć f(s,t,d)?
cole
@Cole Dzięki za rozpakowanie! Nie rozumiem jednak, co miałeś na myśli f(s,t,d)(dane wejściowe to cały stos).
Uriel
świetny pomysł na rozpakowanie, choć nie sądzę, że powinieneś mi to przypisać (sugerowałem, aby wziąć zmienne osobno). Wydaje się, że specyfikacja wejściowa pozwala wziąć głębię i zwroty jako oddzielne zmienne ze stosu: „Dane wejściowe i wyjściowe mogą znajdować się w liście, tablicy, ciągu znaków z separatorem, przekazywane w jednym elemencie na raz lub w innym rozsądnym formacie. Dane wyjściowe muszą być w tym samym formacie co dane wejściowe. ”
cole
Możesz zapisać 1 bajt za pomocą r=-t%d-d. Również zastąpienie s*0**dprzez s*(d<1)zachowuje liczbę bajtów, ale może poprawia czytelność (nie to, że to jest cel). Nie wiedziałem tego jednak 0**0==1w Pythonie, to interesujące.
Ben Frankel,
@BenFrankel nie mogę Zapisz -t%d-djako wartość (jak ja wcześniej), bo gdy djest 0to ten wywoła wyjątek dzielenie przez zero.
Uriel
3

JavaScript ES6, 109 92 bajtów

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}

Wypróbuj online!

Odbiera dane wejściowe w postaci tablicy liczb całkowitych.
Ma również liczbę do strzałki: P

Wyjaśnienie:

Kod używa funkcji shift do wyodrębnienia pierwszych dwóch elementów listy.

Następnie otrzymuje wartość bezwzględną pierwszego elementu, czyli liczbę zwojów.

Ponieważ Javascript jest indeksowany na zero, indeks głębokości należy zmniejszyć o 1.

Jeśli wskaźnik głębokości wynosiłby 0 lub 1, nic nie powinno się zmienić, ale ze względu na spadek wskaźnik 0 spowodowałby zmiany. Dlatego wyjdź z pętli, jeśli indeks głębokości nie jest <= 0.

Funkcja łączenia (a, b) zwraca pod-tablicę o długości b z początkowym indeksem a z tablicy i pozostawia oryginalną tablicę bez tych elementów.

Po połączeniu z resztą oryginalnej tablicy, jest to pojedynczy obrót tablicy przy indeksie głębokości.

Wykonując tę ​​operację n razy, gdzie n jest liczbą zwojów, wynikowa tablica jest wynikiem operatora przechyłu.

Fəˈnɛtɪk
źródło
3

Python 2 , 48 bajtów

lambda r:r[2:r[1]+2][r[0]:]+r[2:r[0]]+r[r[1]+2:]

Wypróbuj online!

Keerthana Prabhakaran
źródło
2

TI-Basic, 141 150 bajtów (niekonkurencyjny)

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

Edycja: naprawiono wielkość liter, w której głębokość wynosi zero (+9 bajtów)

TI-Basic nie obsługuje list o długości 0, więc to podejście nie zadziała dla danych wejściowych o dwóch długościach.

Wyjaśnienie:

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
pizzapanty184
źródło
Myślę, że potrzebujesz kodu, aby poradzić sobie również z 2-elementową listą; obecnie będzie to błąd na seq(.
lirtosiast
1

Partia, 163 bajty

@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%

Pobiera dane wejściowe jako parametry wiersza polecenia i wyświetla listę rozdzieloną spacjami. Parametry pomiędzy ti dsą wyodrębniane do rzmiennej, aby można je było dodać do szmiennej, która odbiera wszystkie pozostałe parametry.

Neil
źródło