飞机上的有效蛇


23

受到Vi Hart的视频之一启发(这些视频充满了潜在的挑战想法)

蛇由相同长度的线段组成,每个线段之间的连接可以是直的,也可以是90度的。
我们可以通过记下一条滑行器(它所需要的转弯方向(直/左/右))来编码这样一条蛇(最多旋转一次,具体取决于初始方向)。从左上方开始,指向右侧

-+    +--+    SR    RSSR
 |  +-+  |     S  RSL  S
 +--+  --+     LSSL  SSR

将由滑行者代表 SRSLSSLRLRSSRSRSS

当然,一条平面蛇不能相交(如中的SSSSLLLSS),这将导致可怕的像素化游戏结束。

您的任务是确定滑行器是否有效(导致至少一个自相交)

输入
的字符串由字母构成的SLR2 < length < 10000
输出
的东西Truthy如果它是一个有效的滑行和东西Falsey如果它不是。

测试用例

__Valid__
SSLSLSRSRSSRSSSLLSSSRRLRSLRLLSSS
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR (A hilbert curve)
RLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRR
SRRSRSRSSRSSRSSSRSSSRSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS (Spiral)
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS (bigger, squigglier spiral)
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLL

__Invalid__
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

您可以在此处绘制滑条(R和L翻转,但是不影响有效性)


输入必须在程序中完成还是可以从文件中读取?
MI赖特

1
SRRR应该是对还是错?它连接但不相交。
orlp 2015年

碰蛇挑战NSFW?
伊万2015年

3
如果您SRRR在每段上有一个正方形的方格纸上画图,则它会重叠,因此是无效的,只是简单地RRR,它将恰好占据一个2x2的正方形而没有重叠(就像在经典游戏中一样)
DenDenDo 2015年

相似但不重复(由于不同的目标和不同的构造规则)。
trichoplax 2015年

Answers:


20

Pyth,22 20字节

ql{m+=Z*=T^.j)hCdzlz

自己尝试或运行测试套件

请注意SRL的ASCII值分别为83、76、82。我滥用以下事实:

i 83 +1 = 1
i 76 +1 = i
i 82 +1 = -i

从这里,我只保留当前位置和当前方向的变量。对于每个字符,我将当前方向乘以上述复数,然后将其添加到当前位置。

最后,我检查所有拜访的职位是否都是唯一的。


SRRR = true吗????
伊万2015年

@Ewan经过仔细检查-我不确定这是否应该是错误的。头和尾连接,但不相交。
orlp 2015年

SRRRS呢?
伊万2015年

@Ewan同样的故事-连接但没有交集。问题尚不清楚这些应该返回什么。
orlp 2015年

1
您将如何提取SRRR?
伊万2015年

6

CJam,30个字节

q{iF%U+:U[XWe4W1e4]=T+:T}%__&=

即将进行解释。

在此处在线尝试运行整个套件


该死的,那太快了。我什至没有想到自己解决问题的算法。
DenDenDo'5

SRRRS = true ???
伊万2015年

@Ewan umm,我们是否假设0最初被填充并计数?
Optimizer

1
我想我将其解释为蛇的游戏,移动占据了空间。你们中的一些人将其解释为零宽度线
Ewan,2015年

@Ewan我的问题虽然有些不同。举个例子说S,这是否意味着这条蛇已经同时占据了(0,0)和(1,0)?
Optimizer 2015年

6

JavaScript(ES6),84 89

在Firefox中运行代码段进行测试。

一些注意事项:

  • 蛇在f数组内移动。未访问的单元格具有价值undefined。第一次访问时,代字号运算符将其更改为-1,这是事实。最终,在第二次访问时,值更改为0,这是虚假的,并且every循环终止并返回false。
  • 在JS中,具有非规范索引(非数字或负数)的数组元素某种程度上是“隐藏的”,但它们确实存在。在这里,我使用负索引没有问题。

F=s=>[...s].every(c=>f[p+=[1,1e5,-1,-1e5][d=d+{R:1,L:3,S:0}[c]&3]]=~f[p],d=p=0,f=[])

//TEST
$('#S').on('keyup mouseup change', Draw);

function Draw(){
  var s = S.value.toUpperCase();
  if (!s) {
    C.width = C.height = 0;
    return
  }
  C.width = 600;
  C.height = 400;
  
  var ctx = C.getContext("2d");  
  var px, py, int=0;
  
  ctx.strokeStyle = '#008';
  ctx.lineWidth = 2;
  ctx.translate(300,200);
  ctx.beginPath();
  ctx.moveTo(0,0);
  
  [...s].forEach(c=>{
    (f[p+=[1,1e4,-1,-1e4][d=d+{R:1,L:3,S:0}[c]&3]]=~f[p])
    ? 1 
    : (++int)
    if (int==1) ctx.stroke(), ctx.strokeStyle = '#800', ctx.beginPath(), ctx.moveTo(10*px,10*py);
    
    py = (p / 1e4 | 0) - 5e3;
    px = (p % 1e4) -5e3
    ctx.lineTo(10*px, 10*py);
  }, d=0,p=50005000,f=[]);
  ctx.stroke();
  
}

valid=["SSLSLSRSRSSRSSSLLSSSRRLRSLRLLSSS",
"SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"RLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRR",
"SRRSRSRSSRSSRSSSRSSSRSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS",
"SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS",
"LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLL"];
invalid=["SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS",
"SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS",
"LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"];

V.innerHTML=valid.map(s=>F(s)+' '+s).join('\n')
I.innerHTML=invalid.map(s=>F(s)+' '+s).join('\n')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Type to check and draw <input id=S>
(better full page)<br>
<canvas id=C width=1 height=1 ></canvas><br>
Valid<pre id=V></pre>
Invalid<pre id=I></pre>


6

TI-BASIC,49 56 53 51字节

abs(e^(i)-cumSum(i^cumSum(seq(inString("SL",sub(Ans,X,1))-1,X,1,length(Ans→X
SortA(∟X
min(ΔList(∟X

与orlp的方法类似,这会创建一条从原点开始的蛇所访问的复杂平面中所有点的列表。如果列表中没有重复的元素,则代码返回一些正值。请注意,在超过999个元素的字符串上,计算器将无法生成足够长的列表,并且会出错。

编辑:以丑陋为代价保存了两个字节,因为复杂平面上没有两个晶格点可以与e ^ i距离相等。


5

TI-BASIC,60 58字节

编辑:忽略下面的所有内容:thomas-kwa 在这里提供有效的基本解决方案。去投票吧!

[(-)]关键,而Ans是[2ND]->[(-)]。通过将蛇的指令括在引号([ALPHA]->[+])中,然后加上冒号和程序名称来运行它。例如,如果您将程序命名为“ SNAKE”,则将在OP中运行测试用例"SRSLSSLRLRSSRSRSS":prgmSNAKE

seq(inString("SRL",sub("0"+Ans,I,1)),I,1,length(Ans
Disp 0<sum(⁻1+2seq(Ans(I)≠(Ans(I-1),I,2,dim(Ans

编辑:失败SRRLSLLRRRS。我有一个61字节的修订版,但是在第一个无效的测试用例上失败了:

seq(inString("SRL",sub("0"+Ans,I,1)),I,1,length(Ans
cumSum(⁻1+2seq(Ans(I)≠(Ans(I-1),I,2,dim(Ans
Disp 0<Ans(dim(Ans

我明天尝试修复。


更新:所以问题实际上是我的算法有缺陷。如果我使用了For()循环而不是seq((实现相同的东西)),则它(实际上是上述两种算法)可以这样描述:

  1. 将计数器变量初始化为1。
  2. 读取字符串。如果符号更改,请增加计数器变量。如果该符号重复,则将其递减。
  3. 如果计数器变量大于0,则显示1(有效)。否则,显示0(无效)。

但是,这对于无效的滑行器()失败SRLRLRLRLRRRSS。我现在将尝试提出一种更好的算法...或从另一个答案中窃取。


我90%确信实际上可以用一个seq(命令替换它,但是就目前而言,这已经很小了。如果你打算建立这使用8xp Sourcecoder而不是实际打字出来,注意应改为!=⁻1+位应改为~1+


1

红宝石87 89

F=->s{d=[1,w=1e4,-1,-w]
v=[w]+s.chars.map{|c|w+=d.rotate!(c<?R?-1:c>?R?0:1)[0]}
v==v&v}

在线测试:http//ideone.com/pepeW2

非高尔夫版本:

F = -> input {
  # Coordinates are expressed using one number,
  # that is computed using the formula `y + x*max_x`.
  # Assume max horizontal field width (max_x) to be 10000,
  # since that's the max length of the input.
  position = max_x = 1e4

  # These are possible directions to move to (coordinate deltas).
  # The current direction is always the first in the array.
  directions = [1,max_x,-1,-max_x]

  visited = [position]

  visited += input.chars.map{|c|
    # adjust current direction...
    directions.rotate! case c
    when ?L
      -1
    when ?R
      1
    when ?S
      0
    end

    # ...and move there
    position += directions[0]
  }

  # Return `true` if `visited` only contains distinct elements, `false` otherwise
  visited == visited & visited
}

0

高尔夫脚本48 49 50

[10.4?:z-10z~)]z*z@{'R L S'?@>(@+.`n}%n/@;\;..&=

期望字符串存​​在于堆栈中并返回01

您可以在线测试有效无效的蛇。

这基本上与我的Ruby回答中的想法相同。只是方向数组的处理方式有所不同,因为AFAIK Golfscript没有Arary旋转功能。在这种情况下,我将构建一个足够大的方向数组,方法是将其乘以10000次,然后根据当前命令(S,R或L)从其开头的0、1或3个元素开始进行修剪。当前要移动的“方向”始终是数组中的第一项。

这是带有注释的:

# Build the direction array and set current position
[1 10000:z-1z~)]z*z

@{
  # For each character in the input:

  # set current direction by cutting 0, 1 or 3 elements 
  # from the beginning of the directions array
  'SR L'?
  @>

  # move to current direction
  .0=@+.

  # format as number and addd newline
  `n
}%

# split by newlines
n/

# cleanup
@;\;

# return 1 if array contains distinct elements, 0 otherwise
..&=

编辑:

通过修改使用“ directions”数组的方式节省了1个字符。

编辑:

通过使用10而不是1的增量来节省1个字符,以使用?(power)语法。

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.