这就是我们滚动的方式


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 '17

4
@ mbomb007 啊哈 你看这个
克里斯托弗

7
令我感到非常失望的是,这丝毫没有涉及到里克滚动
Christopher

2
@ mbomb007我在标签描述中或在meta的快速搜索中都没有看到它,所以我认为情况并非如此。
Mike Bufardeci

2
@ mbomb007如果您想让我更改它,请提供一些论点,而不是一遍又一遍地说“您错了,我是正确的”。您无视此事的先例,没有任何地方说挑战只需要一个获胜者,或者必须接受答案。
Mike Bufardeci

Answers:


8

Haskell64 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 ll在索引处拆分列表nmod计算除法余数,++并连接列表。


1
我认为您可以通过定义中(%)=splitAt缀来减少2个字节。
xnor

@xnor哦,我不知怎么说服自己,是行不通的
与Orjan约翰森

8

JavaScript(ES6),49 47字节

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

编辑:通过将堆栈元素作为单独的参数,感谢@Shaggy节省了2个字节。说明:

  • 当转弯是深度的倍数时,什么也不会发生。因此,第一步是计算转弯模数深度。由于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

Mathematica,58个 50字节

编辑:感谢Martin Ender节省了8个字节。

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

说明:

纯函数,它期望一个列表,其中列表的开头代表堆栈的顶部。我们将列表的元素传递给pure函数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]&

这串infix函数确实让我们感到满意。将第一个元素t,第二个元素d和其余元素替换为列表,x结果是将的第一个d元素{x}向左旋转t并连接的剩余元素{x}


1
真好!您可以使用±替换规则的一字节前缀函数insetad 节省3个字节,并通过利用TakeDrop以下内容来节省1个字节: ±{t_,d_,x___}:=#~RotateLeft~t~Join~#2&@@{x}~TakeDrop~d
Greg Martin

我只是想评论与格雷格相同的事情,但实际上您可以更短一些。要么做一个未命名的可变参数函数(尽管有点狡猾,因为它需要输入...&[1, 1, 3, 4]和返回,{3, 4}或者Apply在开始时用a手动完成:(请Take[x={##3},#2]~RotateLeft~#~Join~Drop[x,#2]&@@#&注意,我的第一个建议忽略了@@#&。)
Martin Ender

5

Ruby,40个字节

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

在线尝试!

将输入作为列表,返回列表。内置的rotate既可以处理正向旋转也可以处理负向旋转的事实使此变得微不足道。


5

Python,141 98 87 74字节

@Cole节省了11个字节

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)(输入是整个堆栈)。
Uriel'4

关于打包的很棒的主意,尽管我不认为您应该为此而赞叹(我建议只是将变量分开考虑)。输入规范似乎可以让您更深入地了解和旋转堆栈中的独立变量:“输入和输出可以在列表,数组,带定界符的字符串中,一次传入一个元素或任何其他合理格式。输出的格式必须与输入的格式相同。”
科尔

您可以使用保存1个字节r=-t%d-d。同样,用替换s*0**d可以s*(d<1)保持字节数,但可能会提高可读性(这不是目标)。但是我不知道0**0==1在Python中有意思。
本·弗兰克尔

@BenFrankel我不能保存-t%d-d为一个值(像我一样)之前,因为当d0这会触发师零例外。
Uriel

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,则退出循环。

splice(a,b)函数以数组的起始索引a返回长度为b的子数组,并保留原始数组中没有这些元素的子数组。

当与原始数组的其余部分连接时,这是数组在深度索引处的单个旋转。

通过执行此操作n次,其中n是匝数,结果数组是滚动运算符的结果。



2

TI-Basic,141150字节(非竞争)

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长度列表,因此该方法不适用于2长度输入。

说明:

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变量之前,该变量接收所有其他参数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.