Ось як ми котимось


18

Piet - цікава мова програмування з кількох причин. Сьогодні ми зупинимося на одній причині: команді roll . Команда roll була спочатку від PostScript і є потужним способом маніпулювання стеком.

Команда roll вискакує два верхні елементи стека і використовує їх як параметри. Ми будемо називати перше значення спливаючим, turnsа друге depth. Поворот на глибину n займе верхній елемент стека, зробить його n-м елементом в стеку і перемістить кожен з елементів над ним вгору по одному. Якщо turns негативно, це робиться у зворотному напрямку. Тобто, n-й елемент переміщується вгору, а інші елементи переміщуються вниз. Це повторюється abs(turns)раз.

Виклик

Напишіть програму або функцію, яка займає стек і повертає її після виконання рулону.

Правила

  • Введення та вихід можуть бути у списку, масиві, рядку з роздільником, що передаються в одному елементі, або будь-якому іншому розумному форматі. Вихід повинен бути у тому ж форматі, що і вхідний.
  • depth ніколи не буде негативним і ніколи не буде більше довжини стека.
  • Вхідний стек завжди буде містити щонайменше два елементи.
  • Це тому найкоротша відповідь на кожній мові виграє. Я не буду приймати відповідь.
  • Стандартні лазівки заборонені.

Випробування

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
найкоротша відповідь на кожній мові виграє , це не так, як [code-golf] працює. Найкоротша відповідь виграє. Період.
mbomb007

4
@ Mbomb007 гм , що про це
Christopher

7
Я був дуже розчарований, що це ніяк не передбачає катання рикків
Крістофер

2
@ mbomb007 Я не бачу цього в описі тегів або у швидкому пошуку мета, тому я не думаю, що це так.
Майк Буфардечі

2
@ mbomb007 Якщо ви хочете, щоб я його змінив, будь ласка, будь ласка, наведіть якийсь аргумент, окрім того, щоб говорити "ви неправі, і я правий" знову і знову. У цьому є прецедент, який ви звільнили, і ніде не сказано, що для викликів потрібен рівно один переможець або що відповідь повинна бути прийнята.
Майк Буфардечі

Відповіді:


8

Haskell , 64 62 байт

Редагувати: -2 байти: @xnor побачив щось, про що я думав не так.

rбере і повертає список Ints.

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

Спробуйте в Інтернеті!

splitAt n lрозбиває список lна індекс n, modобчислює залишок поділу, ++об'єднує списки.


1
Я думаю, ви можете вирізати 2 байти, визначивши (%)=splitAtінфікс.
xnor

@xnor О, я якось переконав себе, що це не вийде
Ørjan Johansen

8

JavaScript (ES6), 49 47 байт

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

Редагувати: збережено 2 байти завдяки @Shaggy, взявши елементи стека як окремі параметри. Пояснення:

  • Коли поворот кратний глибині, нічого не відбувається. Таким чином, перший крок - обчислити глибину модуля повороту. Оскільки JavaScript знає лише, як обчислити залишок, я повинен це зробити у два етапи.
  • Поворот 1переміщає верхній елемент до depthелемента. Поворот 2переміщає два верхні елементи і т. Д. Однак ви також можете досягти цього, переміщаючи елементи між поворотом і глибиною вперед. spliceвидаляє ці елементи іconcat додає їх до решти елементів. (Я міг би використати розуміння масиву замість того, що він однакової довжини.)
  • На відміну від цього slice, другий параметр to splice- кількість елементів, які потрібно видалити.

Це не (t%d+d)%dте саме, що t%d?
Лука

@Luke Ні, %це залишок, тому він дає негативну відповідь, коли tнегативний.
Ніл

Ви можете зберегти 2 байти, використовуючи, (t,d,...a)=>оскільки правила дозволяють вводити вхід по одному елементу за раз.
Кудлатий

@Shaggy Спасибі, я цього не помічав.
Ніл

7

CJam, 31 байт

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

Вхід і вихід - це масиви на стеку, останній елемент представляє верхню частину стека.

Слід стека:

                   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

Математика, 58 50 байт

Редагувати: Дякую Мартіну Ендеру за збереження 8 байт.

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

Пояснення:

Чиста функція, яка очікує на список, де початок списку представляє верхню частину стека. Передаємо елементи списку в чисту функцію Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&. xвстановлюється послідовність елементів, починаючи з третього аргументу., потім ми повертаємо перші #2(другий аргумент) елементи xлівого #(перший аргумент) разів, потімJoin решта елементів x.

Це врятувало б 3 байти, якби ми просто передали елементи стека в якості аргументів функції безпосередньо, а не були в списку спочатку, але тоді формати введення та виведення не збігалися.

Оригінальне рішення:

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

Щось справді задовольняє цей ланцюжок функцій інфікування. Замінює список першим елементом t, другим елементом dта рештою елементами xв результаті обертання перших dелементів {x}до лівих tчасів та приєднання до решти елементів {x}.


1
Приємно! Ви можете зберегти 3 байти, скориставшись однобайтною функцією префікса, ±заміщеною правилом заміни, та іншим 1 байтом, використовуючи TakeDropнаступне: ±{t_,d_,x___}:=#~RotateLeft~t~Join~#2&@@{x}~TakeDrop~d
Грег Мартін

Я просто збирався коментувати те саме, що і Грег, але ви насправді можете піти ще коротше. Або зробіть неназвану варіативну функцію (хоча це трохи хитро, тому що вона приймає введення ...&[1, 1, 3, 4]та повернення, {3, 4}або виконайте це вручну з Applyна початку: Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&@@#&(щоб було зрозуміло, моя перша пропозиція не відповідає @@#&.)
Мартін Ендер

5

Рубін, 40 байт

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

Спробуйте в Інтернеті!

Приймає введення як список, повертає список. Те, що існує вбудований rotateмодуль, який може обробляти як позитивні, так і негативні обертання, робить це дрібницею.


5

Пітон, 141 98 87 74 байт

11 байт збережено завдяки @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]

Отримує вхід у вигляді списку, де останній елемент - це верхня частина стека.

Використовує трюк 0ⁿ для фільтрації нульової глибини та оператора модуля регулювання знаків python для визначення частини списку, що підлягає рубанню.


Чому б просто не взяти f(s,t,d)?
cole

@Cole Дякую за розпакування! Однак я не бачу, що ти мав на увазі під собою f(s,t,d)(вхід - це весь стек).
Уріель

дивовижна ідея розпакування, хоча я не думаю, що ви повинні мені це заслуговувати (я пропонував просто взяти змінні окремо). Спеціальна інформація про введення дозволяє здавати глибину і перетворюється як окремі змінні зі стека: "Введення та вихід можуть бути в списку, масиві, рядку з роздільником, переданим в одному елементі за раз, або будь-якому іншому розумному форматі. Вихід повинен бути у тому ж форматі, що і вхідний. "
Коул

Ви можете зберегти 1 байт за допомогою r=-t%d-d . Крім того, заміна s*0**dна s*(d<1)підтримує кількість байтів, але, можливо, покращує читабельність (не те, що це мета). Я не знав, що 0**0==1в Python це цікаво.
Бен Франкель

@BenFrankel я не можу зберегти в -t%d-dякості значення (як я робив раніше), тому що , коли dце 0це спричинить за собою виключення поділу на нуль.
Уріель

3

JavaScript ES6, 109 92 байт

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}

Спробуйте в Інтернеті!

Отримує введення у вигляді масиву цілих чисел.
Також має відлік стрілки: P

Пояснення:

Код використовує функцію shift для вилучення перших двох елементів списку.

Потім воно отримує абсолютне значення першого елемента, що становить кількість витків.

Оскільки Javascript індексується нулем, індекс глибини потрібно зменшити на 1.

Якщо індекс глибини становив 0 або 1, нічого не повинно змінюватися, але через зменшення індекс 0 спричинив би зміни. Тому вийдіть з циклу, якщо індекс глибини не <= 0.

Функція сплайсингу (a, b) повертає масив довжини b із початковим індексом a з масиву та залишає початковий масив без цих елементів.

При з'єднанні з залишком вихідного масиву це одиночне обертання масиву в індексі глибини.

Виконуючи цю операцію n разів, де n - кількість витків, отриманий масив є результатом оператора рулону.



2

TI-Basic, 141 150 байт (неконкурентоспроможний)

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

Редагувати: фіксований випадок, коли глибина дорівнює нулю (+9 байт)

TI-Basic не підтримує списки довжиною 0, тому такий підхід не працюватиме для двовпливного введення.

Пояснення:

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

Я думаю, що вам потрібен код і для вирішення 2-елементного списку; в даний час це помилка на seq(.
lirtosiast

1

Пакетна, 163 байти

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

Приймає введення як параметри командного рядка та виводить список, розділений пробілом. Параметри між змінною tі dвитягуються в rзмінну, щоб їх можна було зробити попередньо sзмінною, яка приймає всі інші параметри.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.