揭开一维迷宫的秘密


41

背景

您醒来后发现自己迷失在一维迷宫中!出现一个神秘的精灵(或其他东西),并解释说出口位于您的面前,但是您与出口之间的挑战是一系列的。当您前行时,您会意识到所有所谓的挑战仅仅是锁着的门。首先,您会看到带有T形钥匙孔的门,而自己却没有这样的钥匙,请后退步伐,寻找具有T形状的钥匙。

沮丧的是,您在地面上发现了字母键的汤,这些汤都不符合您遇到的门。出于某种天才(或愚蠢)的考虑,您决定如果将小写字母t形的钥匙塞入足够的强度,则它可能可以装入该插槽中。当您用t手握小写字母的方式接近门时,T孔会发出绿色的光,并且门会在您面前溶解。

一倒,还有更多...

挑战

挑战的目标是标记退出迷宫需要花费多少步骤。

挑战的输入是迷宫:一个仅包含字符的字符串[A-Za-z^$ ]。词汇表:

  • ^-起始空间。输入将只包含一个^
  • $-出口(自由!)。输入将只包含一个$
  • [A-Z]-大写字母表示大门。如果您已经收集了必需的密钥,则只能通过此门。
  • [a-z]-小写字母表示按键。通过走到包含密钥的空间中来收集这些密钥。

输入中每个大写字母最多包含一个。这意味着门的总数将在0-26之间(含0和26)。

每个锁着的门上[A-Z]都有一个对应的小写钥匙[a-z]。输入中可以有任意数量的空格()。

所有的门将在起点的右侧,在出口的左侧。这样就不会有多余的门。所有输入都是可解的。

此挑战的输出将是一个数字,即退出迷宫所采取的步骤数。

算法

您退出这个令人毛骨悚然的地方的有条理的方法如下:

  • 从开头(^)开始,然后向前(向右)收集遇到的所有键。
  • 当您碰到一扇门时,如果您拥有正确的钥匙,则可以继续前进到门上。如果没有正确的钥匙,您将向后走(左)收集碰到的钥匙,直到找到您无法打开的最新门的钥匙。
  • 收集到当前麻烦门的钥匙后,您将返回右侧并继续前进。
  • 重复此过程,直到您进入出口($)。

有经验的高尔夫球手会理解,只要您的代码输出的结果与运行此算法相同,就不必实施此特定算法。

数数

每次您从一个正方形移到另一个正方形时,这都算是一个步骤。转动180º不会产生任何附加步骤。如果没有必需的钥匙,您将无法前进到门上。您必须踩到钥匙才能捡起来,并且必须踩到出口才能赢。首次移动后,起始空格(^)的行为与其他任何常规空格相同。

例子

在这些示例中,我将空格留作下划线以供人类阅读。

输入为_a_^_A__$__。输出为11。您1往前走,注意没有A门钥匙,然后没有脸。您向后走,直到占据了包含a3向后走,现在4总计)的空间。然后,您可以向前走直到占据包含出口的空间(7向前走,11总计)。

输入为b__j^__a_AJB_$。输出是,41您在迷宫的后面进行了两次单独的行程,一次行程获取j钥匙,而下一次行程获取b钥匙。

输入为__m__t_^__x_T_MX_$____。输出为44x从头到门的途中捡起钥匙,您将不需要花费额外的时间就可以拿到钥匙T

输入为g_t_^G_T$。输出为12。如果G没有钥匙,您将无法直接进入空间。您很幸运在拿到t钥匙的路上拿起g钥匙,从而在通往自由的道路上打开了两扇门。

输入为_^_____$。输出为6。那很简单。

I / O准则和制胜标准

适用标准I / O规则。这是一个挑战。


17
除了不错的挑战之外,我想说一下措辞和解释的很好
Luis Mendo

4
“因此,不会有多余的门。” 我认为AbA^aB$不会是多余的要么。;)
Martin Ender

4
@orlp我更感兴趣的是看看人们如何打高尔夫。最好的解决方案“去获取所有钥匙然后打开所有门”似乎微不足道。
turbulencetoo

2
@PeterTaylor和turbulencetoo不,不是的,谁能说所有的钥匙都在左侧,而所有的门都在右侧?多余的钥匙/门也会很有趣。这将非常有趣,因为这将意味着解决依赖关系图。
orlp

5
每扇门都有一把钥匙。每个钥匙都有门吗?
user2357112 '16

Answers:


3

果酱,45岁

1q_'$#<'^/~\W%:A;ee{~32+A#)_T>{:T+2*+}&]0=)}/

在线尝试

说明:

1         initial step count; this 1 is actually for the last step :)
q_'$#<    read the input and only keep the part before the '$'
'^/~      split by '^' and dump the 2 pieces on the stack
\W%:A;    take the first piece, reverse it and store it in A
ee        enumerate the other piece (making [index char] pairs)
{…}/      for each [index char] pair
  ~32+    dump the index and character on the stack, and add 32 to the character;
           uppercase letters become lowercase and other chars become garbage
  A#)     find the index of this character in A and increment it (not found -> 0)
  _T>     check if this index (number of steps from '^' back to the key)
           is greater than T (which is initially 0)
  {…}&    if that's true (we need to go back), then
    :T    store that index in T (keeping track of how far we go back before '^')
    +     add to the other index (from the pair, number of steps we took after '^')
    2*    double the result (going back and forth)
    +     add it to the step count
  ]0=     keep only the first value from the bottom of the stack (step count)
           (if the condition above was false, we'd have 2 extra values)
  )       increment the step count (for the current step)

7

Pyth,51个字节

JxQ"^"K-xQ"$"JVQI&}NrG1>JxQrN0=JxQrN0=+K*2t-xQNJ;pK

将门与其钥匙之间的距离相加(加倍,以进行往返行程),而忽略“嵌套”钥匙以及从起点到终点的距离:

JxQ"^"                                              #Initialize the farther point with the starting position
      K-xQ"$"J                                      #Initialize the step counter with the difference between the exit and the start
              VQ                                    #iterate over the input
                I&}NrG1>JxQrN0                      #check if is upper and if the keys is father than one stored (to eliminate nested keys)
                              =JxQrN0               #update the farther key
                                     =+K*2t-xQNJ;   #update step counter with the round trip door<>key
                                                 pK #print the step counter

python2.7中的相同算法:

lab=raw_input()
farther_key=lab.index('^')
steps = lab.index('$') - farther_key
for i in lab:
    if i.isupper():
        if farther_key> lab.index(i.lower()):
            farther_key=lab.index(i.lower())
            steps+=((lab.index(i) - farther_key)-1)*2
print steps

5

Python 2中,155个 154 134 128字节

编辑:感谢@ user2357112和@loovjo的意见,这些意见帮助我从解决方案中节省了20 26字节!

def f(l):
 i=l.index;b=i('^');t=i('$')-b
 for d in filter(str.isupper,l):
  k=i(d.lower())
  if k<b:b=k;t+=2*(i(d)-k-1)
 print t

1
您可以将第二和第三行与分号合并,以节省一个字节。另外,循环中不需要i变量。
Loovjo

同意在第二行和第三行@Loovjo,但是为什么说i不必要? i跟踪当前正在处理的门的位置,如果还没有拿起它的钥匙,则需要跟踪(例如,如果k-钥匙的位置-小于f-我们走过的最远的门-那么我们需要添加2*(i-k-1)到我们的总步数(向左走以获取钥匙,然后向右走回门)...?
Ken'Joey'Mosher

1
但是不能在第五行i替换为l.index(d),在第四行删除分配吗?
Loovjo

分隔符ef变量看起来很多余。另外,您可以通过保存l.index到变量来保存一堆字符。
user2357112 '16

@loovjo:是的,您是对的……起初我误解了您的评论。@ user2357112:绝对正确。 x也是多余的。猜猜我的高尔夫运动正在表现出来。:) 谢谢您的帮助!
Ken'Joey'Mosher

4

C,136字节

q,x,p[300],z,c,k;main(i){for(;p[c=getchar()]=++i,c-36;z&&(k+=(x=p[c+32])&&x<q?(q=q>x?x:q,2*i-2*x-1):1))z=p[94],q||(q=z);printf("%d",k);}

4

PHP 5.3,123字节

这是我在Code Golf上的第一篇文章,希望这对于第一篇文章而言具有足够高的高尔夫质量。绝对是一个有趣的挑战和一个令人敬畏的问题!

function n($m){while('$'!=$o=$m[$i++])$o=='^'?$b=$i+$c=0:$o>'Z'||$b<=$k=stripos($m,$o))?$c++:$c+=2*$i-3-2*$b=$k;return$c;}

该程序很好地滥用了以下事实:PHP不需要您在使用变量之前预先声明任何变量。

在我的最终解决方案中,结果也证明要短几个字节,以便从0开始并在找到起始字符时重置步数,​​而不是从'^'开始。

任何提示都绝对欢迎!


3

JavaScript(ES6),110个字节

s=>(i=c=>s.indexOf(c),p=i`^`,l=i`$`-p,s.replace(/[A-Z]/g,(c,j)=>p>(t=i(c.toLowerCase()))?l+=j-(p=t)-1<<1:0),l)

@Rob的Pyth答案的端口。


2

Python 2.7版,234 199 179

a=raw_input()
x=a.index
v=x('^')
b=x('$')-v
l=filter(str.islower,a[:v])[::-1]
for i in filter(str.isupper,a):
 k=i.lower()
 if k in l:b+=(x(i)-x(k)-1)*2;l=l[l.index(k)+1:]
print b

1

AWK,174字节

func f(xmS){x+=S
c=a[x]
if(c~/^[A-Z]/&&!k[c]){C=c
S=-S
s--}else{c=toupper(c)
k[c]=1
s++
if(c==C){S=-S;C=9}}if(c=="$"){print s}else f(x,S)}{split($0,a,"")
f(index($0,"^"),1)}

可能有一个更严格的算法,但这就是我想出的。

请注意,我正在使用gawk。的某些实现AWK可能不会以""这种方式拆分字符串。


1

C#,309个字节

class P{static void Main(string[]a){string m=Console.ReadLine(),k="";var f=true;char b,c=b=' ';int j=m.IndexOf('^'),t=0;for(;m[j]!='$';j+=f?1:-1){c=m[j];if(char.IsUpper(c)){if(k.IndexOf(char.ToLower(c))<0){f=!f;b=c;t--;}}if(char.IsLower(c)){k+=c;if(char.ToUpper(c)==b){f=!f;t--;}}t++;}Console.WriteLine(t);}}

非高尔夫版本:

    class P
{
    static void Main(string[] a)
    {
        string m = Console.ReadLine(), k = "";
        var f = true;
        char b, c = b = ' ';
        int j = m.IndexOf('^'), t = 0;
        for (; m[j] != '$'; j += f ? 1 : -1)
        {
            c = m[j];
            if (char.IsUpper(c))
            {
                if (k.IndexOf(char.ToLower(c)) < 0)
                {
                    f = !f; b = c; t--;
                }
            }

            if (char.IsLower(c))
            {
                k += c;
                if (char.ToUpper(c) == b) { f = !f; t--; }
            }


            t++;
        }
        Console.WriteLine(t);
        Console.ReadKey();

    }
}

这里没什么特别的,只需要遍历字符串并根据字符以及密钥是否包含在密钥字符串中来改变方向即可。

m =迷宫弦

k =键串

f =方向(迷宫中正确的方向)

b =回溯时要搜索的键

c = m [j]的占位符,由于频繁使用而节省了一些字节

j =要查看的字符串的char索引

t =计数

在打高尔夫球方面还相对较新,所以如果您看到我可以将其修整的地方,请告诉我!

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.