あなたの車は右に曲がるだけです!


49

前書き

障害物コースで暴走した車に閉じ込められているという不幸があります。車のすべての機能は応答しません。損傷したステアリングシステムを除きます。直進することも、右折することもできます。車を安全に誘導できますか?

力学

あなたの車は8x8マップの左上隅から始まり、右下隅で安全になろうとしています。車の向きは(最初は右)、90度単位で測定されます。車は次の2つのアクションのいずれかを実行できます。

  1. 1マス先に進む、または
  2. 時計回りに90度回転してから、1マス先に進みます

車は、1つの広場で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
私はいくつか書いた信じられないほどのための簡単なテストケースをCrashStuck。彼らがいるのは彼らがここにいるからです。行2が満たされ、他はすべて空-> Crash。行7が満たされ、他はすべて空->Stuck
地下

3
(パーセンテージではなく)パーセンテージポイントについて混乱しています。いずれかのボーナスを取得すると、スコアが0.9倍になります。両方を取得すると、0.8または0.9 ^ 2倍になりますか?
地下

3
もちろん、SとCは問題ありません。私の出力は単なる提案でした。
ホスゲン14年

13
「2つの間違いは権利を与えませんが、3つの左は権利を与えます。」- パパ。
hoosierEE 14年

2
「あなたの車はゼロか3つの左しか作ることができません!」
feersum

回答:


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)
オプティマイザー

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={})-テスト済み。
オプティマイザー14年

1
@Optimizer私はまだ2番目のテストケースに当てはまります[[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]]。それは偽を与えるはずです。
私と私の猫14年

2
以来だからであるxyの両方のグローバルがあり、ページをリロードする前に2つのテストケースを実行することはできません...
オプティマイザ

1
とを置き換えることx+=d?d^2?0:-1:1x+=d&1?0:1-d、さらに合計9個節約できます。y+=d^1?d^3?0:-1:1y+=d&1&&2-d
DocMax 14年

10

Python 2-123125133146148150154160

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)

ラムダバージョン-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に感謝します。さらに水平スクロールを追加するためにも:D

優れたビットバッシングとロジックを提供してくれたxnorに感謝します!

注の編集:b[y][x]範囲外になったときに実行されることはないと確信しています。私たちは取締役会の外にいるので、履歴チェックs in cはになりますFalse。その後、境界チェック(x|y)&8はになります8。その後==、最初の2つはすでに異なるため、Pythonは最後の値をチェックしません。


1
機能バージョンでは、両方が返される2つのifを組み合わせることができます。falsyあるリターンのみを返すなしとして、あなたも好意を返す.just 0を返す必要はありません。)
ウィル

あなたがチェックを反転した場合、あなたはあまりにも両方IFSを組み合わせることができます
ウィル

両方のreturnステートメントを組み合わせることができますか?
ブランドン14年

1
@ウィルありがとう、私はそれを行うためのより良い方法があることを知っていました:Dうーん、私は構文エラーを引き起こさない削除するスペースを見つけることができませんでした。なぜ私は本当に得ることはありませんx|y>7or動作しますがx|y<0or...ない
FryAmTheEggman

1
で始まる8進リテラルを作成でき0oます。
feersum 14年

9

C(GNU-C)、163バイト* 0.9 = 146.7

#C(GNU-C)、186バイト* 0.9 = 167.4

私の新しいバージョンでは、符号なし整数ではなく符号付き整数を使用しています。以前、私は符号付き右シフトを恐れていましたが、符号ビットがゴールスクエアであるため、その後に何が起こるかは関係ありません。

この関数は、64ビット整数の形式でビットの配列(1つはブロックされた正方形を表します)を取ります。あなたが本を読むのと同じように、ビットは最小から最大まで並べられます。クラッシュの場合は-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配列から16進数へのコンバーター:

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 14年

2
私は入力フォーマットが好きです-非常にクールです!
ホスゲン14年

私はのための「クラッシュ」取得していますP(0x00fefefefefefefe);(ストレートコーナーに、右上に1ターンストレートショットであるべき=をため同じ。P(0x00eeeeeeeeeeeeee);第四COL上(デッドエンド)私はあなたが割り当てる必要はないと思います。a最初は。

@tolos行/列優先の順序が入れ替わっています。上の行と右の列を開くには、にする必要があります0x7f7f7f7f7f7f7f00。また、初期化する必要がありますa。これは、後で追加ビットのOR処理によってのみ変更されるため、最初に不要なビットを設定する余裕がないためです。
feersum 14年

6

パイソン、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に変換することです。スペースの16進数は20であるため、下位4ビットはすべて未設定です。 oのhexは16進数な6Fので、下位4ビットはすべて設定されています。

os の境界線がボードの周りに配置されているため、不良インデックスを心配する必要はありません。

ボードを歩きながら、各タイルのビットを使用して、その側から来るときに通過が許可されているかどうかを確認します。このようにして、無限ループを回避します。出口方向は入口方向に依存するため、タイルごとにブール値を1つ持つだけでは十分ではないため、タイルに2回アクセスできます。

次に、安全なパスを再帰的に検索します。


3
「あなたの車は8x8マップの左上隅から始まります」-の9代わりにハードコーディングすることはできませんw=len(b[0])+1か?
FryAmTheEggman 14年

@FryAmTheEggmanありがとう、どうしてそれを見落とすことができたの?:D
ウィル

あなたの三元の文を逆にして置き換えることができますp==79p-79。の前にスペースなしでこれを行うと、構文エラーが発生しましたelse。このトリックはでしか機能しないと思いますif
FryAmTheEggman 14年

@FryAmTheEggman再帰の前に深度テストが必要だと思いますか?私は代わりにブール値による乗算で遊んでいます。
ウィル

7
本当にすてきなトリックを見つけました。あなたはおそらく-~x==を知っていますx+1が、両方の単項演算子は乗算、除算、モジュラスよりも高い優先順位を持っています!そう(d+1)%4かもしれない-~d%4!これも動作しますx-1が、~-x代わりに使用します。
FryAmTheEggman 14年

6

Javascript- 270-20%= 216262-20%= 210バイト

両方のボーナスを獲得する解決策が少なくとも1つあるべきであるため(そして、ばかげたスタックの深さをもたらすことはありません;)...

縮小:

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( ...ます。

内側のループは5つのことを行います。

  1. 現在の状態から2つの可能な動き(直進、右折)を計算します
  2. これらの移動のいずれかがハッシュテーブルにすでに登録されている状態になった場合、以降の処理では無視されます。Kただし、車がクラッシュせずに永久に旋回し続けるループが少なくとも1つ見つかったため、FALSE出力に(スタック)のフラグが付けられます。
  3. 状態が正当で斬新な場合、外側のループの次のパスのために、ハッシュテーブル(v)および未処理のトリプルのスタック()に追加されmます
  4. 新しい状態がに登録されるとv、その値は元の状態の値(一連の移動)に加えて、RまたはS現在の移動に基づいて設定されます
  5. 場合xyされ7、元の状態(元の状態に達するのに要する移動の配列)の値がコピーされS、この移動シーケンスが問題を解決するため、

内側のループが終了すると、n(スタック)はm(新しいスタック)に置き換えられます。

外側のループが終了した(新しい状態に到達しなかった)後、関数はその出力を返します。(7,7)セルに到達した場合、Sこのセルに至る一連の動きが含まれ、これが出力されます。セルに到達しなかった場合、S空の文字列になり、ルーチンはoutputにフォールスルーし、ループが見つかった場合にのみ(スタック)、または車が必然的にクラッシュする場合に(クラッシュ)Oが含まれます。KC


1
OPから確認を得て、「クラッシュ」と「スタック」の名前を「C」と「S」に変更できます。
FryAmTheEggman 14年

あ。それで少し節約できます。ありがとう。;)
COTO

あなたのコードが何をしているのか説明できますか?頭や尻尾を作ることはできません。
ホスゲン14年

@phosgene:詳細な説明をインラインに含めました。
COTO 14年

それは賢い手順です。無駄はありません。
ホスゲン14年

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なので、aforループのように、インデント用にタブとスペースを混在させることができます。また、演算子の周りのスペースも必要ありません(例:(v+1) % 4->)(v+1)%4。行にor ;がないif場合forなどを使用して、複数のステートメントを1行に結合することもできc(l+"0");c(l+"1")ます。いくつかの他のgolfs: 、x,y,v=0,0,2、。x|y>7 or x|y<0 x==y==7幸運:)
FryAmTheEggman 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.