一只蚂蚁在多维数据集


33

一只蚂蚁沿着线框立方体的边缘(而不是面)行走。它遇到的每个顶点都有一个叉,两个新的边从中分支出来。蚂蚁选择转向的方式- leftright。这些方向是相对于面向顶点且在立方体外部的蚂蚁而言的。您的目标是根据left/ right选择蚂蚁的顺序,确定蚂蚁是否在开始的位置结束。

例如,如果蚂蚁向左转四次(left left left left),则它将逆时针移动一个正方形,并在开始的位置结束。但是,如果继续left left left left right下去,它将终止于多维数据集的其他位置。同样,如果它走了left right right right left,它将终止于其起始边缘,但朝向相反的顶点,该顶点不算作同一位置。

蚂蚁的路径可能会重复边缘,包括其开始的边缘,但重要的是在整个序列之后它的终止位置。

编写一个命名函数,该函数接受蚂蚁的转弯序列并输出蚂蚁在序列之后是否回到其起始位置。为变量分配一个未命名的函数足以使其成为一个命名函数。

(编辑:如果您的语言无法创建命名函数,则可以通过STDIN /打印或堆栈使用输入和输出来实现该函数。如果无法实现,请使其成为将输入和输出保存在其中的代码段变量。)

输入项

长度为left/ 包含在内的一系列/ right决策,031您选择的格式表示。这可能是字母字符串R/ L,数字列表1/ -1或布尔数组。别让它们成为方法名称或对您的代码有用的字符串。

如果与以下测试用例不同,请以您的格式发布测试用例。

输出量

True/ False0/ 1或您所用语言的类似物。

获奖标准

最少的字节数获胜。请记住,您需要提供一个命名函数。您可以在函数之外使用代码,但是这些字节也可以计数。如果多次调用,您的函数应正确运行。

测试用例

True 情况(每行一个,第二个是空列表):

1 1 1 1

-1 -1 -1 -1
1 -1 1 -1 1 -1
1 1 -1 -1 1 1 -1 -1
-1 1 1 -1 -1 1 1 -1
1 1 1 -1 -1 -1 -1 1
1 -1 -1 1 -1 -1
1 1 1 1 -1 -1 -1 -1 1 -1 -1 1 -1 -1
-1 -1 -1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

False 情况(每行一个):

1
1 1
1 1 1
-1 1
1 -1 -1 -1 1
1 -1 -1 1 1
-1 1 -1 1
1 1 1 1 -1
-1 -1 1 -1 1 -1 -1 1
1 -1 1 1 1 1 -1 -1 -1 1 1 -1 -1 -1

这是与Ls和Rs 相同的测试用例。

True 情况:

RRRR

LLLL
RLRLRL
RRLLRRLL
LRRLLRRL
RRRLLLLR
RLLRLL
RRRRLLLLRLLRLL
LLLRLLRRLRLRRRRRRRRRRRRRRRRR

False 情况:

R
RR
RRR
LR
RLLLR
RLLRR
LRLR
RRRRL
LLRLRLLR
RLRRRRLLLRRLLL

额外的信用挑战

同样,只是十二面体而不是立方体。有关想法,请参见《追捕乌鸦》。


这是否排除了不使用命名函数的语言的使用?
Mike Precup 2014年

@MikePrecup您能给我一些这样的语言的例子吗?我将研究替代方案。
xnor 2014年

我在> <>中完成所有我的高尔夫球代码提交,这就是为什么要问。它有一个堆栈,您可以将args加载到堆栈的顶部,然后将结果保留在堆栈上,但这并不是一个精确的命名函数。
Mike Precup 2014年

@MikePrecup好吧,我为此预留了一笔津贴。如果某些语言仍然存在问题,请告诉我,我不想排除任何语言。
xnor 2014年

我可以想到befunge和> <>以及这类语言
骄傲的haskeller 2014年

Answers:


21

GolfScript,24个字符(仅19个用于函数体)

数学FTW!

{3,.@{[+~@\{@}*~]}/=}:f;

在线测试该解决方案。

此函数将二进制数组作为输入(0表示左侧,1表示右侧),并返回1表示true,0表示false。

从概念上讲,它的工作原理是旋转立方体,以便蚂蚁始终保持相同的位置和方向,并检查立方体是否最终以与开始时相同的方向结束。

特别是,我们可以将左转和右转表示为三个维度的两个线性映射,其中左转对应于围绕x轴旋转90° ,即映射(xyz)→(xz, - ÿ),和右转弯对应于绕一个90°旋转ÿ轴,即,图(Xÿž)→(žÿ, - X)。

在函数开始时,我们只需要简单地设置一个包含三个不同元素的正值(1、2、3)的三元向量,并对其应用旋转映射序列,然后检查所得向量是否等于初始向量。

(实际上,为了节省一些字符,我实际上对坐标进行了转换,以使初始向量为(0,1,2),映射为(xyz)→(xz,-1− y)和(xyz)→(zy,-1− x),但最终结果是相同的。)

附言 感谢自豪的haskeller发现该解决方案原始版本中的错误。


Perl,58个字符

根据注释中的要求,这是移植到Perl的相同解决方案。(此版本实际上使用未转换的坐标,因为转换在Perl中不保存任何字符。)

sub f{@a=@b=1..3;@a[$_,2]=($a[2],-$a[$_])for@_;"@a"eq"@b"}

在线测试该解决方案。


奖励:十二面体上的蚂蚁(GolfScript,26个字符)

{5,.@{{2*2%[~\]}*(+}/=}:f;

在线测试该解决方案。

像上面的ant-on-a-cube函数一样,此函数将二进制数组作为输入(0表示左侧,1表示右侧),如果ant最终以与开始时相同的位置和方向返回1,则返回0。除此以外。

与上面的多维数据集解决方案相比,此解决方案使用的抽象表示稍多一些。具体地,其利用以下事实:十二面体旋转对称基团交变基团 A 5(即五个元素的偶数排列的组)同构。因此,十二面体的每个可能的旋转(即映射边缘的边和顶点到顶点)可以唯一表示为一个置换一个五元件阵列,具有对应于序列施加对应排列的连续旋转。

因此,我们要做的就是找到两个可以表示左右旋转的置换LR。具体而言,这些置换需要是5个周期(以便将它们应用于五次返回到原来的状态)时,它们必须不彼此(即,功率- [R大号ñ任何Ñ),并且他们需要满足关系(LR5 =(1),其中(1)表示身份置换。(实际上,此标准指出路径LRLRLRLRLR必须返回到原始位置。)

L置换固定为向左的简单桶形移位,即映射(abcde)→(bcdea),因为它可以在GolfScript中仅用两个实现chars((+),我们发现R排列有五个可能的选择。从这些中,我选择了映射(abcde)→(cedba),因为它也具有相对紧凑的GolfScript实现。(实际上,我通过首先与元素交织2*2%以获得(acebd),然后与交换最后两个元素[~\],最后无条件应用L置换以将a移到末尾来实现它。)

上面的在线演示链接包括十二面体上返回原点的有效路径的一些测试案例,例如:

           # empty path
1 1 1 1 1  # clockwise loop
0 0 0 0 0  # counterclockwise loop
1 0 0 0 0 1 1 0 0 0 0 1  # figure of 8
1 0 1 0 1 0 1 0 1 0      # grand circle
1 0 0 0 1 0 0 0          # loop around two faces 
1 0 0 0 1 1 1 0 1 0 1 0 0 0 1 1 1 0 1 0  # Hamilton cycle

不错的解决方案!这是否排除了蚂蚁从另一个方向返回相同顶点的情况?
xnor 2014年

我不明白-基本上您在这里所做的工作是使用3位来表示蚂蚁的位置,但是有24个可能的位置。怎么样?
自豪的haskeller 2014年

1
@proudhaskeller:感谢您发现错误。我已经修复它,并将您的反例添加到我的测试套件中。
Ilmari Karonen 2014年

1
@xnor:也添加了十二面体的解决方案。
Ilmari Karonen 2014年

1
十二面体的一对不错的排列。我在Hunt the Wumpus中使用的字符会再增加一个字符:{[~@]-1%}*[~@]或者){[~@]-1%}*-1%替换您的{2*2%[~\]}*(+
Peter Taylor

7

Python,68岁

接受1和-1的列表。基于3D旋转:在应用一系列旋转后,检查点(3,2,1)是否在同一位置结束。有两种可能的旋转,分别对应于1和-1。通过排列两个坐标并更改其中一个的符号来完成每个坐标。要更改的确切坐标以及要替换的符号并不重要。

def f(l):
 p=[3,2,1]
 for d in l:p[d],p[0]=-p[0],p[d]
 return[3,2]<p

编辑:这实际上是与“ Perl,58”相同的解决方案。


你是对的,的确是。
骄傲的haskeller 2014年

+1,它仍然比我尝试使用Python解决方案的时间短。不过,看一下我拥有的内容,我认为您可以通过将输入作为0和1并将的最后一个元素拆分p为一个单独的变量来节省一些字符。
Ilmari Karonen 2014年

3
哇,我在测试解决此问题时写了完全相同的解决方案,一个字符一个字符,除了变量名!
xnor14 2014年

5

Mathematica

受Ilmari Karonen解决方案的启发。立方体的旋转对称组与S 4同构。

多维数据集,51字节

Fold[Part,r=Range@4,{{2,3,4,1},{3,4,2,1}}[[#]]]==r&

1s和-1s 的列表作为输入。

在线尝试!

十二面体,55字节

Fold[Part,r=Range@5,{{2,3,4,5,1},{3,5,4,2,1}}[[#]]]==r&

1s和-1s 的列表作为输入。

在线尝试!


我正在搜索如何发现它与S3同构?
骄傲的haskeller 2014年

糟糕,我的意思是“如何找到/证明它与S4同构?
骄傲的haskeller 2014年

@proudhaskeller您可以在这里找到它:en.wikipedia.org/wiki/Octahedral_symmetry
alephalpha 2014年

5

C(GCC) 118个 116 107 105字节

-2个字节归功于ceilingcat

f(char*s){char*p,n[]="@ABCDEFG",y;for(;*s;s++)for(p=n;*p;*p++^=*s^82?y%2+1:4-(y&2))y=*p/2^*p;y=n[2]==66;}

在线尝试!

假设我们给立方体以下坐标:

            (1,1,1)       (1,1,0)
          G +--------------+ C
           /|             /|
          / |            / |
         /  |    (0,1,0)/  |
(0,1,1) +--------------+ D |
      H |   |          |   |
        |   |          |   |
        | F +----------|---+ (1,0,0)
        |  /(1,0,1)    |  / B           x
        | /            | /           y / 
        |/             |/            |/  
      E +--------------+ A      z ---*   
        (0,0,1)       (0,0,0)

如果我们从D角开始,那么可以考虑移动到C或H就是围绕我们旋转立方体。向右移动表示绕Z轴逆时针旋转,向左移动表示绕X轴顺时针旋转。这是我们唯一需要关注的两个轮换。由于每个旋转正好是90度,我们可以想象拐角沿边缘“滑动”。对于右移,这意味着A-> B,B-> C,C-> D,D-> A,另一侧是E-> F等。对于左移,我们得到的是A-> E,E- > H等

由于每个角仅沿边缘滑动,因此,每次旋转仅改变每个点的尺寸之一。当B移至C时,仅其y分量发生变化,而当H移至D时,仅其z分量发生变化,依此类推。此外,由于坐标限制为0和1,我们可以将每个点视为二进制数,并在移动时翻转适当的位。

我们可以看到,向右移动时,A和C翻转其x,而D和B翻转其y。如果我们改变视角以在立方体头的那一侧看,而忽略z分量(无论如何旋转,z分量都不会改变),我们得到:

D (0,1)         C (1,1)
 +-------------+
 |             |
 |             |
 |             |
 |             |
 |             |
 |             |
 +-------------+
A (0,0)         B (1,0)

出现一种模式:对于翻转其x的点,x == y,而翻转其y的点则相反。这适用于其他类型的旋转,但是使用z而不是x。

换一种说法:

Right
    if (x == y) x = !x
    if (x != y) y = !y

Left
    if (z == y) z = !z
    if (z != y) y = !y

现在我们可以轻松地进行所有旋转,最后查看最终D是否与我们的初始D相匹配。

将每个点存储为单个数字是给定的,但是在C语言中,分配char数组比int数组紧凑得多。我们要小心选择低三位匹配000..111的字符,从而可以忽略其余位。翻转坐标只是与适当的位掩码进行异或运算。


1
非常感谢您冗长的解释,其他答案并没有完全引起我的注意,但是这个答案立刻就有意义了。
Nit

4

蟒蛇-110,150

接受一个整数列表,其中带有-1左转,1右转。

多维数据集,110:

def f(l):
    c,p='07'
    for d in l:a="100134462634671073525275"[int(c)::8];c,p=a[(a.index(p)+d)%3],c
    return'1'>c

测试:

l=map(int,'1 1 1 1'.split())
print f(l)

十二面体150:

def f(l):
    c,p='0J'
    for d in l:a="I5H76E8BBA8F76543100JI0J21D3A5C7E9CJI2132H4GF94C6D98AHGBEDGF"[int(c,36)::20];c,p=a[(a.index(p)+d)%3],c
    return'1'>c

1
您如何在三分钟内写下这些内容,真是令人印象深刻:-P
xnor

6
已经等待了很长一段时间,这个老板问题才产生出来。;-)
2014年

当我在Python 3.2中运行此代码时,我收到“ TypeError:期望对象带有缓冲接口”。
xnor

@xnor编辑,现在在python 2中。希望它能起作用。
2014年

4

万宝龙 188

Ilmari Karonen算法的无耻盗窃,目的是炫耀一种新语言。

此脚本在stdin上期望字符串为0x00,左边为0x01,右边为0x0A(换行符)。对于失败的案例,输出“ 0”,对于成功的案例,输出“ 1”。

......@5@3FF
@0@1@2\\]]@5
010203@4=A@4
&0&0&0&0/\
MVMVMVMV..
@0@1@2@3..!!
:MV
}2}2}1}0}1}0}3
&0&1&0&1~~~~<A@P
{0{1{1{0&1&0=0&1
}0}1}2@P{2{2&030
=1=2=3&2FF}3..//
&2&2&231&2{3
\/\/\/&2!!..//

示例运行:

# echo -e "\x0\x0\x0\x1\x0\x0\x1\x1\x0\x1\x0\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1" | marbelous.py ant-on-a-cube.mbl
1

1
直到我阅读了语言说明,我才意识到这个答案有多么疯狂。对于高尔夫语言来说,这真是一个很酷的概念!
xnor 2014年

@xnor不可能永远是高尔夫领域的重要竞争对手,但它仍然有些有趣:)
Sparr 2014年

4

Python 2,57字节

f=lambda l:reduce(lambda n,x:n%4*64+n/4*16**x%63,l,27)<28

在线尝试!

这使用排列表示

0: abcd -> dabc
1: abcd -> dcab

其中,左和右(0和1)对应于4个元素的长度为4的循环。我们使用指定的排列对输入进行迭代,并检查结果是否等于初始值。

我们从a,b,c,d四元素列表开始0,1,2,3。我们将它们压缩为一个单数为4的数字n=abcd,其初始值n=27对应于0123以4为底的数字。我们在上通过算术实例化每个排列n

由于这两个结果都是以开头d,因此我们可以n%4提取出来d,然后n%4*64将其移到正确的位置d___。其他数字abc提取为n/4。我们需要将它们插入较低的三个位置值。

对于方向x=0,我们abc按原样插入,对于方向,我们按原样x=1旋转它们cab。可以实现作为旋转*16%63,这需要abcabc00cab。(%63将会出错a==b==c==3,但是这些值是不可能的。)由于只是%63禁止操作,所以与方向相关的表达式*16**x%63给出abccab要求。


Python 2,55个字节

f=lambda l:reduce(lambda n,x:n^(n*8%63|7*8**x),l,10)<11

在线尝试!


3

Haskell中,104 103 99 97 96/ 67 64个字符

我觉得右/左等效于数据类型Direction,如下所示:

Direction = R | L

因此我在回答中假设它们可用。
编辑:实际上意识到布尔值会导致代码更短。True表示向左转,而False表示向右转(尽管从技术上讲,如果代码被翻转,它的工作原理是相同的;它是对称的)

96个字符:

m[p,l,r]b|b=[p%l,7-r-l,r]|0<1=[p%r,l,7-r-l]
p%x|odd$div p x=p-x|0<1=p+x
g l=foldl m[0..2]l<[0,2]

g是一个函数,给出给定的Direction列表将返回不返回到其位置的蚂蚁的天气。

位置表示的解释: 蚂蚁的位置编码为三个整数的元组。第一个整数表示蚂蚁要去的顶点。第一位表示顶点是在上/下半部,第二位是左/右半部,第三位是后/前半部。这样做是为了可以通过翻转一位来完成从顶点到相邻顶点的移动。

第二个整数是蚂蚁顶点向左移动会改变的数量。例如,如果蚂蚁在顶点3处,并且第二个整数是4,那么向左转后顶点将是7。请注意,这始终是2的幂,因为通过移动一个顶点恰好翻转了一位。

第三个整数是相同的,只是右移;我知道这是可以通过前两个计算的,但是我不知道该怎么做。如果您有个主意,请告诉我。

需要注意的是,当向左转时,第三个整数将保持不变,而第二个将变为1 2和4之间的那个,而不是第二个整数或第三个整数,恰好与7相同-第二个整数-第三个整数。

我选择这种表示位置的方式是因为(如前一段所述)计算下一个位置很简单。

功能说明:

(%)函数是采用当前顶点及其数量进行更改并对其进行更改的函数。它到达将要改变的位并将其翻转(以非常数值的方式)。

m函数是一个函数,它获取蚂蚁的位置和方向,并通过使用前面提到的注释返回新的位置。

然后,使用foldl(类似于reducejavascript,但更具表达性)组合m函数,以创建函数g(此问题的答案)。


Haskell,64个字符

受@alphaalpha的答案启发,这是移植到haskell的版本:

m[a,b,c,d]p|p=[b,c,d,a]|0<1=[b,d,a,c]
g l=foldl m[0..3]l<[0,1,3]



编辑: 由于lmari Karonen的回答,我现在感到非常愚蠢。也许我会把他的答案移植给Haskell。 另一个编辑:没有感觉那么愚蠢他的答案错了
编辑:从实际使用的元组切换到使用列表作为他们的Ord实例和[ ... ]语法糖使得短


1
这看起来非常优雅,尤其是褶皱。可能会节省更多的字符分配[0,1,2,3]给变量,并将其用作表达式的输入和结果的检查吗?
xnor 2014年

@xnor,因为您的意见我决定将golfng提出来[0..3]……我不知道为什么我没有早一点注意到。谢谢。但是现在你的把戏不起作用了。那好吧。
自豪的haskeller 2014年




3

Bash71 65字节

f()(a=1234;for i;{ a=`tr 1-4 4$[$i?123:312]<<<$a`;};((a==1234));)

在线尝试!

像许多先前的答案一样,使用由1234-> 4123和1234-> 4312生成的多维数据集旋转组的表示。使用数字而不是字母,以便我可以对算术扩展使用三元运算符。期望其输入为0和1,并用空格分隔,并通过退出代码输出。

感谢@manatwork的评论,节省了6个字节!


1
有关遍历参数列表的信息,请参见DennisBash技巧
manatwork

3

brainfuck,119字节,137字节

小号4

多维数据集,119字节

++++>+++>++>+>,[+++[->+++<]<<<<[->>>>+<<<<]>[>]<+[[-]<[->+<]<<<[->>>+<<<]>[>]],]<[[<]>[->]<[>>]<]<[>>-<]-[----->+<]>--.

在线尝试!

++++>+++>++>+    Initialize tape as 4 3 2 1

>,[              For each input byte:

  +++[->+++<]       Add 3 and multiply by 3; if input is R, this will be 255

  <<<<[->>>>+<<<<]  Move first number to end (BCDA)

  >[>]<+[           If input wasn't R:

    [-]                Zero input cell (which is now negative 18)

    <[->+<]            Move previously moved number one slot further (BCD_A)

    <<<[->>>+<<<]      Move first number into vacated slot (CDBA)

  >[>]]

,]

<[[<]>[->]<[>>]<]     Determine whether tape is still 4 3 2 1

<[>>-<]               If not: subtract 1 from output cell

-[----->+<]>--.       Create "1" in output cell and output

十二面体,137字节

+++++>++++>+++>++>+>,[+++[->+++<]<<<<<[>>>>>+[<]>-]>[>]<+[[-]<<[[->>+<<]<<]>[>>>>>>+[<]<-]>>[>]],]<[[<]>[->]<[>>]<]<[>>-<]-[----->+<]>--.

在线尝试!

这两个程序之间的唯一区别是设置和排列。此处使用的左置换为DCAEB,这似乎是可获得的最高尔夫球的共轭。


1

果冻,14字节

3RðW;ṙN1¦ṚƊ/⁼⁸

在线尝试!

1=左转,0=右转。基于我的Dyalog解决方案。

不幸的是,Jelly没有命名函数。如果我不能使用隐式输入并且需要假定它在变量中,则此相同长度的版本将执行以下操作:

3RµW;®ṙN1¦ṚƊ/⁼

假定输入在寄存器(©/®)中。


0

Perl-120,214

接受布尔值的数组(列表)。

立方体(120):

sub e{$a=$b=0;for$c(@_){$_=(13,62,53,40,57,26,17,'04')[$b];$d=s/$a/($b-1)%8/e;($a,$b)=($b,substr($_,$c^$d,1))}return!$b}

十二面体(214):

sub e{$a=$b='00';for$c(@_){$_=('01041102090307040500061807160308091502101114121019131714151016081706131819051200'=~/\d{4}/g)[$b];$d=s/$a/sprintf'%02d',($b-1)%20/e;($a,$b)=($b,substr($_,($c^$d)*2,2));}return!($b+0)}

2
魔术数字编码是什么?
xnor 2014年
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.