Ini adalah cara kami menggulung

18

Piet adalah bahasa pemrograman yang menarik karena sejumlah alasan. Hari ini kita akan fokus pada satu alasan: perintah roll . Perintah roll awalnya dari PostScript dan merupakan cara yang ampuh untuk memanipulasi tumpukan.

Perintah roll memunculkan dua elemen teratas stack dan menggunakannya sebagai parameter. Kami akan memanggil nilai pertama yang muncul turnsdan yang kedua depth. Beralih ke kedalaman n akan mengambil elemen paling atas dari tumpukan, menjadikannya elemen ke-n dalam tumpukan, dan memindahkan setiap elemen di atasnya ke atas satu. Jika turns negatif ini dilakukan dalam arah yang berlawanan. Artinya, elemen ke-n dipindahkan ke atas dan elemen lainnya dipindahkan ke bawah. Ini berulang abs(turns)kali.

Tantangan

Tulis program atau fungsi yang mengambil tumpukan dan mengembalikan tumpukan itu setelah menjalankan gulungan.

Aturan

  • Input dan output mungkin dalam daftar, array, string dengan pembatas, diteruskan dalam satu elemen pada suatu waktu, atau format lain yang masuk akal. Output harus dalam format yang sama dengan input.
  • depth tidak akan pernah menjadi negatif dan tidak akan pernah lebih besar dari panjang tumpukan.
  • Tumpukan input akan selalu mengandung setidaknya dua elemen.
  • Ini adalah sehingga jawaban terpendek dalam setiap bahasa menang. Karena itu, saya tidak akan menerima jawaban.
  • Celah standar dilarang.

Uji Kasus

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
sumber
2
jawaban terpendek di setiap bahasa menang , itu bukan cara [kode-golf] bekerja. Jawaban terpendek menang. Titik.
mbomb007
4
@ mbomb007 ahem bagaimana dengan ini
Christopher
7
Saya sangat kecewa bahwa ini sama sekali tidak melibatkan rick rolling
Christopher
2
@ mbomb007 Saya tidak melihat itu dalam deskripsi tag atau dalam pencarian cepat pada meta jadi saya tidak berpikir itu masalahnya.
Mike Bufardeci
2
@ mbomb007 Jika Anda ingin saya mengubahnya, berikan beberapa argumen selain mengatakan "Anda salah dan saya benar" berulang-ulang. Ada preseden untuk ini, yang Anda tolak, dan tidak ada yang mengatakan bahwa tantangan membutuhkan tepat satu pemenang atau bahwa jawaban harus diterima.
Mike Bufardeci

Jawaban:

8

Haskell , 64 62 byte

Sunting: -2 byte: @xnor melihat sesuatu yang saya pikir salah tentang.

rmengambil dan mengembalikan daftar Ints.

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

Cobalah online!

splitAt n lmembagi daftar lpada indeks n, modmenghitung sisa divisi, ++daftar gabungan.

Ørjan Johansen
sumber
1
Saya pikir Anda dapat memotong 2 byte dengan mendefinisikan (%)=splitAtinfix.
xnor
@xnor Oh, entah bagaimana saya meyakinkan diri saya bahwa itu tidak akan berhasil
Ørjan Johansen
8

JavaScript (ES6), 49 47 byte

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

Sunting: Disimpan 2 byte berkat @Shaggy dengan mengambil elemen stack sebagai parameter terpisah. Penjelasan:

  • Ketika belokan merupakan kelipatan dari kedalaman, tidak ada yang terjadi. Karena itu, langkah pertama adalah menghitung kedalaman modulo turn. Karena JavaScript hanya tahu cara menghitung sisanya, saya harus melakukan ini dalam dua langkah.
  • Pergantian 1memindahkan elemen atas ke depthelemen. Giliran 2menggerakkan dua elemen teratas, dll. Namun, Anda juga dapat mencapai ini dengan menggerakkan elemen antara belokan dan kedalaman ke depan. splicemenghapus elemen-elemen itu dan concatmenambahkannya ke elemen lainnya. (Saya bisa menggunakan pemahaman array bukan karena panjangnya sama.)
  • Tidak seperti slice, parameter kedua spliceadalah jumlah elemen yang dihapus.
Neil
sumber
Tidak (t%d+d)%dsama dengan t%d?
Luke
@ Lukas Tidak, %adalah sisa, sehingga memberikan jawaban negatif ketika tnegatif.
Neil
Anda bisa menyimpan 2 byte dengan menggunakan (t,d,...a)=>aturan yang memungkinkan input untuk dilewatkan dalam satu elemen pada satu waktu.
Shaggy
@Shaggy Terima kasih, saya tidak memperhatikan itu.
Neil
7

CJam, 31 byte

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

Input dan output adalah array pada stack, dengan elemen terakhir mewakili bagian atas stack.

Jejak tumpukan:

                   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]
Buah Esolanging
sumber
6

Mathematica, 58 50 byte

Sunting: Terima kasih kepada Martin Ender karena telah menyimpan 8 byte.

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

Penjelasan:

Fungsi murni yang mengharapkan daftar di mana bagian awal daftar mewakili bagian atas tumpukan. Kami melewati elemen daftar ke dalam fungsi murni Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&. xdiatur ke urutan elemen dimulai dengan argumen ketiga., lalu kita putar pertama #2(argumen kedua) elemen xke kiri #(argumen pertama) kali, laluJoin elemen yang tersisa dari x.

Itu akan menghemat 3 byte jika kita hanya melewatkan elemen stack sebagai argumen untuk fungsi secara langsung daripada berada di daftar pada awalnya, tetapi kemudian format input dan output tidak cocok.

Solusi asli:

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

Ada sesuatu yang sangat memuaskan tentang rangkaian fungsi infiks ini. Mengganti daftar dengan elemen pertama t, elemen kedua d, dan elemen yang tersisa xdengan hasil memutar delemen pertama {x}ke waktu kiri tdan bergabung dengan elemen yang tersisa dari {x}.

ngenisis
sumber
1
Bagus! Anda dapat menyimpan 3 byte dengan menggunakan fungsi awalan satu byte ±insetad dari aturan penggantian, dan 1 byte lainnya dengan mengeksploitasi TakeDropsebagai berikut: ±{t_,d_,x___}:=#~RotateLeft~t~Join~#2&@@{x}~TakeDrop~d
Greg Martin
Saya hanya akan berkomentar hal yang sama dengan Greg, tetapi Anda benar-benar bisa lebih pendek. Entah membuat fungsi variadik yang tidak disebutkan namanya (walaupun itu agak cerdik karena butuh input ...&[1, 1, 3, 4]dan kembali {3, 4}atau melakukannya secara manual dengan sebuah Applydi awal: Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&@@#&(hanya untuk menjadi jelas, saran pertama saya menghilangkan @@#&.)
Martin Ender
5

Ruby, 40 byte

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

Cobalah online!

Mengambil input sebagai daftar, mengembalikan daftar. Fakta bahwa ada built-in rotateyang dapat menangani rotasi positif dan negatif membuat ini sepele.

Ventero
sumber
5

Python, 141 98 87 74 byte

11 byte disimpan berkat @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]

Menerima input sebagai daftar, di mana elemen terakhir adalah bagian atas tumpukan.

Gunakan trik 0ⁿ untuk memfilter operator modulo penyesuaian-kedalaman nol dan python, untuk menentukan bagian daftar yang akan dipotong.

Uriel
sumber
Kenapa tidak mengambil saja f(s,t,d)?
cole
@Cole Terima kasih atas pembongkarannya! Namun, saya tidak dapat melihat apa yang Anda maksud dengan f(s,t,d)(input adalah seluruh tumpukan).
Uriel
ide luar biasa untuk membongkar, meskipun saya tidak berpikir Anda harus kredit saya untuk itu (saya menyarankan hanya untuk mengambil variabel secara terpisah). Spek input tampaknya membiarkan Anda mengambil kedalaman dan berubah sebagai variabel terpisah dari tumpukan: "Input dan output mungkin ada dalam daftar, array, string dengan pembatas, diteruskan dalam satu elemen pada suatu waktu, atau format wajar lainnya. Output harus dalam format yang sama dengan input. "
cole
Anda dapat menyimpan 1 byte dengan r=-t%d-d. Juga, mengganti s*0**ddengan s*(d<1)mempertahankan jumlah byte tetapi mungkin meningkatkan keterbacaan (bukan itu tujuannya). Saya tidak tahu itu 0**0==1di Python, itu menarik.
Ben Frankel
@BenFrankel Saya tidak bisa menyimpan -t%d-dsebagai nilai (seperti yang saya lakukan sebelumnya), karena ketika dsedang 0ini akan memicu pengecualian divisi-by-nol.
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}

Cobalah online!

Menerima input dalam bentuk array bilangan bulat.
Juga memiliki hitungan untuk panah: P

Penjelasan:

Kode menggunakan fungsi shift untuk mengekstraksi dua elemen pertama dari daftar.

Kemudian mendapat nilai absolut dari elemen pertama, yaitu jumlah putaran.

Karena Javascript nol diindeks, indeks kedalaman perlu dikurangi 1.

Jika indeks kedalaman 0 atau 1, tidak ada yang berubah, tetapi karena penurunan, indeks 0 akan menyebabkan perubahan. Karena itu keluar dari loop jika indeks kedalaman tidak <= 0.

Fungsi splice (a, b) mengembalikan sub-array dengan panjang b dengan indeks awal a dari array dan meninggalkan array asli tanpa elemen-elemen tersebut.

Ketika digabungkan dengan sisa array asli, ini adalah satu putaran array pada indeks kedalaman.

Dengan melakukan operasi ini n kali, di mana n adalah jumlah belokan, array yang dihasilkan adalah hasil dari operator roll.

fəˈnɛtɪk
sumber
3

Python 2 , 48 byte

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

Cobalah online!

Keerthana Prabhakaran
sumber
2

TI-Basic, 141 150 byte (tidak bersaing)

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

Edit: kasus tetap di mana kedalamannya nol (+9 byte)

TI-Basic tidak mendukung daftar panjang 0, sehingga pendekatan ini tidak akan berfungsi untuk input dua panjang.

Penjelasan:

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
pizzapants184
sumber
Saya pikir Anda perlu kode untuk menangani kasus daftar 2-elemen juga; saat ini akan terjadi kesalahan pada seq(.
lirtosiast
1

Batch, 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%

Mengambil input sebagai parameter baris perintah dan menampilkan daftar yang dipisahkan oleh spasi. Parameter antarat dan ddiekstraksi ke dalam rvariabel sehingga mereka dapat ditambahkan ke svariabel, yang menerima semua parameter lainnya.

Neil
sumber