1次元の迷宮の秘密を解き明かす


41

バックグラウンド

あなたは目覚めて、一次元の迷宮で迷子になっていることに気づきます!神秘的な魔神(または何か)が現れ、出口があなたの前にあることを説明しますが、あなたと出口の間には一連の課題があります。歩き回ると、いわゆるチャレンジはすべて施錠されたドアに過ぎないことに気付くでしょう。最初に、T字型の鍵穴のあるドアを見て、自分でそのような鍵を持っていない場合、ステップをたどって、T形のある鍵を探します。

イライラして、あなたは地面に鍵のアルファベットのスープを見つけます、どれもあなたが出くわしたドアにマッチしません。天才(または馬鹿げた)のストロークで、小文字のt形をしたキーが十分に強くジャムするとスロットに収まる可能性があると判断します。小文字のtキーを手に持ってドアに近づくと、T穴が緑色に光り、ドアが目の前で消えます。

あと1つ、もっとたくさん...

チャレンジ

この課題の目標は、迷路から抜け出すまでに必要なステップ数をマークすることです。

このチャレンジの入力は迷路です:文字のみを含む1つの文字列[A-Za-z^$ ]です。用語集:

  • ^-開始スペース。入力には正確に1つが含まれます^
  • $-出口(自由!)。入力には正確に1つが含まれます$
  • [A-Z]-大文字はドアを意味します。必要なキーをすでに収集している場合にのみ、このドアを通過できます。
  • [a-z]-小文字はキーを示します。これらのキーを収集するには、キーを含むスペースに歩いて行きます。

入力に含まれる大文字は最大で1つです。これは、ドアの合計数が0〜26の間であることを意味します。

すべてのロックされたドアに[A-Z]は、対応する小文字のキーが1つだけあります[a-z]入力には任意の数のスペース()を含めることができます。

すべてのドアは、スタートの右側と出口の左側にあります。したがって、余分なドアはありません。すべての入力は解決可能です。

このチャレンジの出力は、ラビリンスを抜けるまでにかかったステップの数です。

アルゴリズム

この惨めな場所を出るための系統的なアプローチは次のとおりです。

  • 最初から始め(^)、前方(右)に移動して、出会ったキーを収集します。
  • ドアに出くわしたとき、正しいキーがあれば、ドアに向かって進みます。正しいキーを持っていない場合は、後方(左)に歩いて、開いていない最新のドアのキーが見つかるまで、出会ったキーを収集します。
  • 現在の面倒なドアの鍵を集めたら、右に戻り、先に進みます。
  • 出口($)に進むまで、このプロセスを繰り返します。

経験豊富なゴルファーは、このアルゴリズムを実行した場合と同じ結果を出力する限り、コードがこの特定のアルゴリズムを実装する必要がないことを理解します。

カウント

1つの正方形から別の正方形にステップするたびに、それが1つのステップとしてカウントされます。180º回転しても追加のステップは発生しません。必要なキーがないと、ドアに足を踏み入れることはできません。あなたはそれを拾うためにキーに足を踏み入れなければならず、勝つために出口に足を踏み入れなければなりません。最初の移動の後、開始スペース(^)は他の通常のスペースと同じように動作します。

これらの例では、人間が読みやすいようにスペースをアンダースコアとして残しています。

入力は_a_^_A__$__です。出力は11です。あなたは1一歩前進し、Aドアの鍵がないことに気付き、それから顔について。を含むスペースを占めるまで後方に歩きますa3後方に進み、現在は4合計)。次に、出口を含むスペースを占有するまで前方に歩きます(前方に進み711合計)。

入力はb__j^__a_AJB_$です。出力は41、1つはjキーを取得し、次のキーはキーを取得するために、ラビリンスの裏側に2回旅行しbます。

入力は__m__t_^__x_T_MX_$____です。出力は44です。x鍵を手に入れるために余分な旅行をすることはありませんT。最初からドアまでの途中で鍵を手にしたからです。

入力はg_t_^G_T$です。出力は12です。あなたはGキーなしで、すぐに顔を合わせてスペースに移動することはできません。あなたは幸運にも、t鍵に向かう途中で鍵を手に取り、g自由に向かう途中で両方の扉を開くことができます。

入力は_^_____$です。出力は6です。それは簡単でした。

I / Oガイドラインと勝利基準

標準のI / Oルールが適用されます。これは挑戦です。


17
別に素敵な挑戦から、私は言葉遣いや説明がどのように良い発言をしたいのですが
ルイスMendo

4
「したがって、余分なドアはありません。」どちらかというと余計なことAbA^aB$はないと思います。;)
マーティン・エンダー

4
@orlp私は、人々がこの闇のさまようアルゴリズムをどのようにゴルフするかを見ることにもっと興味があります。「すべてのキーを取得してからすべてのドアを開く」という最適なソリューションを実行するのは簡単なことのようです。
turbulencetoo

2
@PeterTaylor and turbulencetooいいえ、そうではありません。すべてのキーが左側にあり、すべてのドアが右側にあると言えますか?そして、余分なキー/ドアも興味深いでしょう。依存関係グラフを解くことを意味するので、それはかなり興味深いでしょう。
-orlp

5
すべてのドアには鍵があります。すべてのキーにはドアがありますか?
user2357112

回答:


3

CJam、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

「ネストされた」キーと開始から終了までの距離を無視して、ドアとそのキーの間の距離を合計します(往復して2倍になります)。

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

パイソン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
2行目と3行目をセミコロンで結合して、1バイト節約できます。また、ループではi変数は不要のようです。
-Loovjo

2行目と3行目、@ Loovjoに同意しましたが、なぜi不要であると言うのですか? i現在処理されているドアの位置を追跡し、そのキーがまだ取得されていない場合に必要です(つまり、k-キーの位置-より小さいf-歩いた最も左の場合-追加する必要があります2*(i-k-1)私たちの合計へのステップ(キーを取得するために左に歩いて、ドアに戻って右に歩く)...?
ケン 'ジョーイ'モッシャー

1
しかし、5行目でi置き換えl.index(d)、4行目で割り当てを削除することはできませんか?
-Loovjo

別のeand f変数は冗長に見えます。また、l.index変数に保存することで文字の束を保存できます。
user2357112

@loovjo:そうだね...最初はあなたのコメントを誤解していた。@ user2357112:絶対に正しい。 x同様に冗長です。私のゴルフ初心者が表示されていると思います。:) 助けてくれてありがとう!
ケン 'ジョーイ'モッシャー

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 =方向(trueは迷路の中で前方です)

b =バックトラックするときに検索するキー

c =頻繁に使用するためにいくつかのバイトを保存するm [j]のプレースホルダー

j =調べる文字列のcharインデックス

t =カウント

ゴルフはまだ比較的新しいので、どこかで見かけたらスリムにできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.