Вот как мы катимся

18

Piet - интересный язык программирования по ряду причин. Сегодня мы остановимся на одной причине: команда крена . Команда 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
самый короткий ответ на каждом языке выигрывает , это не так [код-гольф] работает. Кратчайший ответ выигрывает. Период.
mbomb007
4
@ mbomb007 хм, как насчет этого
Кристофер
7
Я был очень разочарован тем, что это никоим образом не связано с
Кристофер
2
@ mbomb007 Я не вижу этого в описании тега или в быстром поиске по мета, поэтому я не думаю, что это так.
Майк Буфардечи
2
@ mbomb007 Если вы хотите, чтобы я изменил его, пожалуйста, приведите какой-нибудь аргумент, кроме как сказать «вы ошибаетесь, и я прав» снова и снова. Для этого есть прецедент, который вы отклонили, и нигде не говорится, что для испытаний требуется ровно один победитель или что ответ должен быть принят.
Майк Буфардечи

Ответы:

8

Haskell , 64 62 байта

Изменить: -2 байта: @xnor увидел то, что я думал неправильно.

rпринимает и возвращает список Intс.

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 О, я как-то убедил себя, что это не сработает
Орджан Йохансен,
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, вторым параметром spliceявляется количество удаляемых элементов.
Нил
источник
Разве не так (t%d+d)%dже, как t%d?
Люк
@ Люк Нет, %это остаток, поэтому он дает отрицательный ответ, когда 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]
Esolanging Fruit
источник
6

Mathematica, 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}.

ngenisis
источник
1
Ницца! Вы можете сохранить 3 байта, используя однобайтовую префиксную функцию, ±вставленную в правило замены, и еще один байт, используя 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которая может обрабатывать как положительные, так и отрицательные вращения, делает это тривиальным.

Ventero
источник
5

Python, 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 Спасибо за распаковку! Тем не менее, я не понимаю, что вы имели в виду 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

Объяснение:

Код использует функцию сдвига для извлечения первых двух элементов списка.

Затем он получает абсолютное значение первого элемента, которое является числом витков.

Поскольку Javascript индексируется нулем, индекс глубины необходимо уменьшить на 1.

Если бы индекс глубины был 0 или 1, ничто не должно измениться, но из-за уменьшения индекс 0 вызовет изменения. Поэтому выйдите из цикла, если индекс глубины не равен <= 0.

Функция splice (a, b) возвращает подмассив длины b с начальным индексом a из массива и оставляет исходный массив без этих элементов.

При объединении с остальной частью исходного массива это один поворот массива по индексу глубины.

Выполняя эту операцию n раз, где n - число оборотов, результирующий массив является результатом оператора крена.

fənɛtɪk
источник
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
pizzapants184
источник
Я думаю, что вам нужен код, чтобы иметь дело и со списком из двух элементов; в настоящее время это будет ошибка в 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переменной, которая получает все остальные параметры.

Нил
источник