您的车只向右转!


49

介绍

您有被困在障碍道上的失控汽车中的不幸。除了损坏的转向系统外,汽车的所有功能均无响应。它可以直行,也可以向右转。可以引导汽车安全吗?

机械学

您的汽车从8x8地图的左上角开始,并试图在右下角实现安全。赛车的方向(最初是向右)以90度为增量进行测量。汽车可以执行以下两项操作之一:

  1. 向前开一个方块,或者
  2. 顺时针旋转90度,然后向前驱动一个方块

请注意,汽车无法足够急转弯以在单个广场上执行180度转弯。

一些广场是障碍。如果汽车进入障碍物广场,它将坠毁。假定8x8航道之外的所有物体都是障碍物,因此驶离航道等同于坠毁。

右下角的正方形是安全正方形,它使汽车能够逃脱障碍物路线。假定起始正方形和安全正方形不是障碍。

任务

您必须编写一个程序或函数,以8x8数组(矩阵,列表列表等)为输入,表示障碍物路线。程序返回或打印一个布尔值或类似的真值。如果汽车有可能在不撞车的情况下到达安全广场(即,如果地图可解决),则输出为True,否则为False

计分

标准代码高尔夫规则-获胜者是字节最少的代码。

奖金:

  • 如果对于一张可解决的地图,您的代码输出了一系列有效的驾驶员输入来引导汽车驶入安全广场,请从得分中减去10个百分点。示例输出格式可能是SRSSR(指示“直”,“右”,“直”,“直”,“右”)。该输出将替代标准True输出。

  • 如果对于无法解决的地图,代码的输出区分不可避免的崩溃情况和可能永远绕过障碍物路线的情况,请从分数中减去10个百分点。Crash如果无法避免发生碰撞,或者Stuck汽车永远卡在障碍物路线中,则可能是示例输出。这些输出将替代False无法解决的地图的标准输出。

如果给程序一个8x8数组,例如:

[[0, 0, 0, 0, 0, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0], 
 [1, 1, 0, 0, 0, 0, 0, 0], 
 [0, 1, 0, 1, 0, 0, 0, 0], 
 [0, 0, 1, 1, 0, 0, 0, 0], 
 [0, 0, 0, 0, 1, 0, 1, 0], 
 [0, 0, 0, 0, 0, 0, 1, 0], 
 [0, 1, 1, 0, 0, 0, 1, 0]]

它将被解释为这样的地图,黑色方块表示障碍物:

在此处输入图片说明

可能的解决方案可能是:

在此处输入图片说明

由于存在解决方案,因此程序应True为该地图返回/打印。此处显示的移动顺序为SSSSRSRRRSRSSRRRSSRSSS


2
我为和编写了一些非常简单的测试用例。他们在这里是因为他们待了多久。第2行已填满,其他所有内容均为空-> 。第7排填满,一切空- >CrashStuckCrashStuck
undergroundmonorail

3
我感到困惑个百分点(而不是百分比)。获得这两种奖金都会使您的分数乘以0.9。两者都乘以0.8或0.9 ^ 2吗?
地下

3
当然,S和C都可以。我的输出仅是建议。
光气2014年

13
“有两个错误并不能使一个权利,但是有三个左度却不能。” 爸爸
hoosierEE 2014年

2
“您的车只能剩零或三个左!”
feersum

Answers:


17

的JavaScript(ES6) - 122 124 148 162 172 178 187 190 193 208字节

非常感谢Optimizer和DocMax提供了有关如何改进此代码的有用建议:

F=a=>(D=(x,y,d)=>!D[i=[x,y,d]]&&(D[i]=1,x-=~d%2,y-=~-~d%2,x*y==49||!((x|y)&8||a[y][x])&&(D(x,y,d)||D(x,y,~-d%4))),D(-1,0))

true对于可解决的,返回(真),false对于不可解决的,返回(虚假)。

由于JavaScript 1.7的功能,目前仅在Firefox中有效。

测试板


1
这是193个字节:D=(x,y,d,t,a)=>!t[i=x+y*8+d*64]&&(t[i]=1,x+=d==0?1:d==2?-1:0,y+=d==1?1:d==3?-1:0,x==7&&y==7||!((x|y)&~7||a[y][x])&&G(x,y,d,t,a));G=(x,y,d,t,a)=>D(x,y,d,t,a)||D(x,y,d+1&3,t,a);F=a=>G(0,0,0,[],a)
Optimizer

1
172:D=d=>!t[i=x+y*8+d/4]&&(t[i]=1,x+=d?d^2?0:-1:1,y+=d^1?d^3?0:-1:1,x==7&&y==7||!((x|y)&~7||b[y][x])&&G(x,y,d));G=(X,Y,d)=>D(d,x=X,y=Y)||D(d+1&3,x=X,y=Y);F=a=>G(0,0,0,b=a,t={})-经过测试。
Optimizer

1
@Optimizer对于第二个测试用例,我仍然是正确的[[0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]。那应该是假的。
我和我的猫

2
这是因为由于xy都是全局变量,因此无法在重新加载页面之前运行两个测试用例...
Optimizer

1
替换x+=d?d^2?0:-1:1x+=d&1?0:1-dy+=d^1?d^3?0:-1:1,总共可以节省9多个y+=d&1&&2-d
DocMax 2014年

10

Python 2-123125133133146148150154160

True成功,False失败。

def f(h=1,v=0,b=0,x=0,y=0,c=[]):s=x,y,h,v;a=b,x+h,y+v,c+[s];return(s in c)==(x|y)&8==b[y][x]<(x&y>6or f(h,v,*a)|f(-v,h,*a))

您必须提供类似的输入f(b=var_containing_board)

Lambda版本-154

0如果失败,则返回(虚假),如果True成功,则返回。

F=lambda b,x=0,y=0,h=1,v=0,c=[]:0if[x,y,h,v]in c or x|y>7or x|y<0 or b[y][x]else x&y==7or F(b,x+h,y+v,h,v,c+[[x,y,h,v]])or F(b,x+h,y+v,-v,h,c+[[x,y,h,v]])

感谢Will和Brandon使该函数比lambda短。也用于添加更多水平滚动:D

感谢xnor提供出色的位扑和逻辑功能!

编辑说明:我有理由相信,b[y][x]超出范围时将永远不会执行。由于我们不在董事会范围内,因此历史记录检查s in c将为False。然后边界检查(x|y)&8将是8。然后python甚至不会检查的最后一个值,==因为前两个已经不同。


1
功能版本可以将两个同时返回的if结合起来;作为回报独自返回None这是falsy,你也不必返回0。刚返回的青睐;)
威尔

如果翻转检查,你可以结合这两种IFS太
威尔

您可以结合两个return语句吗?
布兰登

1
@Will谢谢,我知道有一种更好的方法:D Um,我找不到要删除的空格,不会引起语法错误。我真的不明白为什么x|y>7or行得通,但x|y<0or不能...
FryAmTheEggman 2014年

1
您可以以开头的八进制文字0o
feersum

9

C(GNU-C),163字节* 0.9 = 146.7

#C(GNU-C),186字节* 0.9 = 167.4

我的新版本使用有符号而不是无符号整数。之前,我担心有标志的右移,但我意识到由于标志位是目标方,因此之后发生的情况无关紧要。

该函数采用一个64位整数形式的位数组(一个代表块状正方形)。这些位的排列方式与阅读本书时相同,从最低到最高。对于崩溃,它返回-1,对于永久行驶返回0,或者对于逃逸到右下角返回1。

g(long long o) {
    typeof(o) a=0,i=255,r=1,u=0,l=0,d=0,M=~0LLU/i,D;
    for( ;i--;d = D<<8&~o)
        a |= D = d|r,
        r = (r|u)*2&~M&~o,
        u = (u|l)>>8&~o,
        l = ((l|d)&~M)/2&~o;
    return a<0?:-!(d|r|u|l);
}

测试程序

f(long long o){typeof(o)a=0,i=255,r=1,u=0,l=0,d=0,M=~0LLU/i,D;for(;i--;d=D<<8&~o)a|=D=d|r,r=(r|u)*2&~M&~o,u=(u|l)>>8&~o,l=((l|d)&~M)/2&~o;return a<0?:-!(d|r|u|l);}
{
    char* s[] = {"Crash", "Stuck", "Escape"};
    #define P(x) puts(s[f(x)+1])
    L ex = 0x4640500C0A034020;
    P(ex);
    L blocked = 0x4040404040404040;
    P(blocked);

    L dead = 0x10002;
    P(dead);

    return 0;
}

输出量

Escape
Stuck
Crash

Python数组到十六进制转换器:

a2b=lambda(A):"0x%X"%sum(A[i/8][i%8]<<i for i in range(64))

1
memset(&M,~1,8)(15个字符)替换为M=~(-1ULL/255)(14个字符)。
R..14年

@R ..好人!-4个字节。
feersum 2014年

2
我喜欢输入格式-非常酷!
光气2014年

我得到了“崩溃” P(0x00fefefefefefefe);=(应该是直枪向右上角,一个转弯,直边角同为。P(0x00eeeeeeeeeeeeee);在第4栏(死胡同)我不认为你需要分配。a最初,

@tolos您已经调换了行/列的主要顺序。要打开第一行和右列,应该为0x7f7f7f7f7f7f7f00。另外,还需要初始化,a因为以后只能通过对其他位进行“或”运算来进行修改,因此我一开始无法设置不需要的位。
feersum 2014年

6

Python中,187 213

207个字符,打印路径的奖金为10%

b=map(ord," "*9+" ".join("".join("o "[i]for i in j)for j in input())+" "*9)
def r(p,d,s):
 p+=(1,9,-1,-9)[d]
 if b[p]&1<<d:b[p]^=1<<d;return(s+"S")*(p==79)or r(p,d,s+"S")or r(p,(d+1)%4,s+"R")
print r(8,0,"")

在测试输入上,它找到一条稍微不同的路径: SSSSRSRSRRSSRSSRRSRSSRSSSSS

一般的方法是首先将输入变成空格和os。空格的十六进制为20,因此所有四个低位均未设置。 o的十六进制为6F,因此低四位都已设置。

o板子的边框为s,因此我们不必担心索引错误。

当我们越过木板时,我们使用每个图块中的位来查看是否允许从该边通过时通过。这样,我们避免了无限循环。每个磁贴只有一个布尔值是不够的,因为您的退出方向取决于输入方向,因此磁贴可以被访问两次。

然后,我们对安全路径进行递归搜索。


3
“您的汽车从8x8地图的左上角开始”-您不能用硬编码9代替w=len(b[0])+1等等吗?
FryAmTheEggman 2014年

@FryAmTheEggman谢谢,我怎么可能忽略了这一点?:D
2014年

您可以反转三元语句并替换p==79p-79。双向执行此操作时遇到语法错误,在else。之前没有空格。我认为那招只能用if
FryAmTheEggman,2014年

@FryAmTheEggman我认为深度测试必须在递归之前进行?我一直在玩布尔运算。
2014年

7
我刚刚发现了一个非常整洁的把戏。您可能知道-~x==,x+1但是两个一元运算符都比乘法,除法和模数具有更高的优先级!所以(d+1)%4可以-~d%4!这也可以使用,x-1但只能使用~-x
FryAmTheEggman 2014年

6

Javascript- 270-20%= 216262-20%= 210字节

由于应该至少有一个解决方案可以同时获得这两项奖励(并且不会导致可笑的堆栈深度;)...

缩小:

V=I=>{n=[N=[0,0,0]];v={};v[N]='';O='C';for(S='';n[0];){m=[];n.map(h=>{[x,y,d]=h;D=i=>[1,0,-1,0][d+i&3];p=v[h];for(j=2;j--;){O=v[c=[X=x+D(j),Y=y+D(3-3*j)),d+j&3]]?'K':O;J=X|Y;J<0||J>7||I[Y][X]||v[c]?O:(m.push(c),v[c]=p+'SR'[j])}S=(x&y)>6?p:S});n=m;}return S||O;};

展开:

V = I => {
    n = [N=[0,0,0]];
    v = {};
    v[N] = '';
    O = 'C';

    for( S = ''; n[0]; ) {
        m = [];
        n.map( h => {
            [x,y,d] = h;
            D = i => [1,0,-1,0][d+i&3];
            p = v[h];
            for( j = 2; j--; ) {
                O = v[c = [X = x+D(j),Y = y+D(3-3*j),d+j&3]] ? 'K' : O;
                J = X|Y;
                J<0 || J>7 || I[Y][X] || v[c] ? O : (
                    m.push( c ),
                    v[c] = p + 'SR'[j]
                );
            }

            S = (x&y) > 6 ? p : S;
        } );
        n = m;
    }
    return S || O;
};

v是一个哈希表,其键为状态三元组,(x,y,d)对应于(x,y)坐标和进入方向d。每个键都有一个关联的值,该值是达到键表示的状态所需的S(直线)和R(向右转)移动的字符串。

该代码还维护了一个n尚未处理的三元组(在变量中)。堆栈最初仅包含三元组(0,0,0),对应于汽车在(0,0)单元中面向右的状态。在外部循环中,for( S = ... )例程检查是否还有未处理的三元组。如果是这样,它将通过内部循环运行每个未处理的三元组n.map( ...

内循环执行五件事:

  1. 计算当前状态之外的两个可能的移动(直线行驶,向右转)
  2. 如果这些移动中的任何一个导致已在哈希表中注册的状态,则将其忽略以进行进一步处理。K但是,我们将FALSE输出标记为(卡住),因为我们发现至少一个循环,在该循环中,汽车可以继续循环永远而不会撞车。
  3. 如果状态是合法且新颖的,则将其添加到哈希表(v)和未处理的三元组(m)的堆栈中,以进行外循环的下一次传递
  4. 当在其中注册新状态时v,其值将设置为原始状态的值(移动顺序)加上RS基于当前移动
  5. 如果xy7,则将原始状态的值(达到原始状态所采取的移动顺序)的值复制到S,因为此移动顺序是解决问题的方法

内部循环终止后,n(堆栈)将被m(新堆栈)替换。

外循环终止后(未达到新状态),该函数返回其输出。如果到达(7,7)单元格,S则将包含导致此单元格的一系列移动,并将其输出。如果未到达该单元格,则为S空字符串,并且例程进入输出OK如果且仅当找到循环时该例程将包含(卡住),或者C如果汽车不可避免地发生碰撞,则将包含(撞车)。


1
从OP得到确认,您可以将“崩溃”和“卡住”重命名为“ C”和“ S”。
FryAmTheEggman 2014年

啊。这样可以节省一点。谢谢。;)
COTO 2014年

您能解释一下您的代码在做什么吗?我不能做它的正面或反面。
光气2014年

@phosgene:我已经在内嵌了详细的解释。
COTO 2014年

这是一个聪明的过程。没有浪费。
光气2014年

4

Python 339-10%= 305字节

我使用了深度优先的递归搜索,搜索成功后会通过提前终止exit。同时打印成功路径的形式000010101010101010101011101001110010000直,1右。答案将比最佳答案长,因为它是深度优先的。我敢肯定,对算法的某些优化可以使字节数减少很多。

b=input()
D=[(-1,0),(0,-1),(1,0),(0,1)]
def a(l):
 x,y=0,0
 v=2
 for d in l:
  if d=='1':v=(v+1) % 4
  x+=D[v][0]
  y+=D[v][1]
  if x<0 or x>7 or y<0 or y>7:return 0,x,y
  if b[y][x]:return -1,x,y
 return 1,x,y
def c(l):
 if len(l) < 39:
  t,x,y=a(l)
  if t==1:
   if (x,y)==(7,7):
    print l;exit(0)
   c(l+"0")
   c(l+"1")
c("")
print 0

3
由于这是Python 2,因此您可以混合使用制表符和空格来缩进,例如in afor循环中。您也不需要在运算符周围加空格,例如(v+1) % 4-> (v+1)%4。您还可以通过使用一行;上是否没有iffor,将多个语句连接到一行上,例如c(l+"0");c(l+"1")。其他一些打高尔夫球:x,y,v=0,0,2x|y>7 or x|y<0x==y==7。祝您好运:)
FryAmTheEggman 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.