グリッド上のダイスパス

Sep 23 2020

標準のダイを、すべての方向に無限に伸びる2Dグリッドの原点に配置します。次の図に示すように、1が上を向き、2が負のy方向を向き、3が正のx方向を向くようにダイを配置します。

次に、ダイを移動方向に90度回転させて、ダイを使用して一連の移動を実行します。たとえば、最初にダイを負のx方向に回転させる場合、3は上向き、2は負のy方向、6は正のx方向を向きます。

一連の動き+y, +y, +x, +x, -yは、明確にするためにダイのネットとともに下の図に示されています(ネットは「右利きのダイ」と呼ばれることもあります)。

次に、移動するたびにダイの上面を読み取ります。この場合、それは読み取ります2, 6, 4, 1, 2。これをダイスパスと呼びます。ダイの上面は初期位置には含まれていませんが、常に1であることに注意してください。

ダイスのパスが、移動の終了時に開始した正方形に戻るようなものである場合、これを原点に戻るダイスパスと呼びます。

チャレンジ

空でないダイスパスを(リストまたはその他の適切な形式で)入力として指定すると、ダイスパスが原点に戻る場合は真の値を出力し、それ以外の場合は偽の値を出力します。ご了承ください:

  • 出力する真の値と偽の値は一貫している必要はありませんが、それらを交換することはできません(たとえば、原点に戻るパスの偽の値を出力し、そうでない場合は真の値を出力します)。
  • 入力は整形式であり、有効なサイコロのパスを表します。
  • ダイが原点からどれだけ離れることができるかに制限はありません。

テストケース

Path                            -> Output
2,1                             -> true
3,1                             -> true
5,4,1,5                         -> true
2,4,1,2                         -> true
4,2,4,1                         -> true
2,4,6,2,4,6,5,4                 -> true
2,4,5,1,4,5,3,6,5,1             -> true
5,6,2,3,5,4,6,3,1,5,6,2         -> true
2,4,1,3,5,1,3,5,6,3,5,6,4,5,6,2 -> true
2                               -> false
4,5                             -> false
5,1,2                           -> false
5,6,2,1                         -> false
5,4,6,5,4,6                     -> false
5,6,4,1,5,4,2,6,5,4             -> false
5,1,2,1,5,6,5,1,2,6,4           -> false
4,6,3,1,5,6,2,1,3,6,4,1         -> false

スコアリング

バイト単位の最短コードが優先されます。

回答

12 Arnauld Sep 23 2020 at 17:24

JavaScript(ES6)、 142 ...  122121バイト

文字の配列が必要['5','1','2']です。例:。0または1を返します。

a=>a.map(n=>D=D.map((_,i)=>D['504405076067'[d*6+i>>1]^i],p+=[w=a.length,-w,1,-1][d=D.indexOf(n)]),p=0,D=[...'254316'])|!p

オンラインでお試しください!

どうやって?

配列D[]は、次の順序で面の値を保持します。

 index |    0   |    1   |    2   |    3   |    4   |    5
-------+--------+--------+--------+--------+--------+--------
 face  |  front | behind |  left  |  right |   top  | bottom

D = ['2','5','4','3','1','6']このエンコーディングを使用して、チャレンジで説明したダイの初期方向である、から始めます。

d次の移動の方向は、次の新しい上面の0インデックス位置ですD[]。

 index (d) |   0   |   1   |   2   |   3
-----------+-------+-------+-------+-------
 direction |  up   |  down | right |  left

方向dに向かって移動するiと、更新されたダイの-番目の面は、前のダイの次の位置にある面になります。

   i = | 0 | 1 | 2 | 3 | 4 | 5
-------+---+---+---+---+---+---
 d = 0 | 5 | 4 | 2 | 3 | 0 | 1
 d = 1 | 4 | 5 | 2 | 3 | 1 | 0
 d = 2 | 0 | 1 | 5 | 4 | 2 | 3
 d = 3 | 0 | 1 | 4 | 5 | 3 | 2

このテーブルは、次の式でエンコードされています。

'504405076067'[d * 6 + i >> 1] ^ i

オンラインでお試しください!

各反復でD[]、位置を更新しpます。\を追加します$\pm 1\$に\$p\$水平に移動する場合、または\$\pm w\$垂直に移動する場合、ここで\$w\$入力配列の長さ(単一方向に移動できる距離の上限)です。プロセスの最後に開始点に戻っているかどうかをテストします。

8 xash Sep 23 2020 at 18:01

J、79バイト

ボックス化された0から5の逆リストとしてサイコロのパスを取ります。

0 0-:[:+/(0,(,-@|.)=i.2){~]i.~&>[:}.(]A.~0 224 283 389 489{~i.~)&.>/\.@,&(<i.6)

オンラインでお試しください!

使い方

リストとして最初のサイコロがあります0 1 2 3 4 5。次の上位桁を探すと、1 2 3 4インデックスとしてどちらかがあります(0そして5違法な動きになります)。アナグラムインデックス224 283 389 489を使用してリストを並べ替え、サイコロの移動を実行します。パス全体に対してこれを行い、中間結果を収集します0 1 2 3 4 5│4 0 2 3 5 1│3 0 4 1 5 2。繰り返しますが、インデックスを探した後、それらを調整の変更にマッピングし、それらを_1 0, 0 _1, 1 0, 0 1合計して、最終的にがになるかどうかを確認し0 0ます。

サイコロ番号6から4、5から3、…、1から5を再マッピングしてバイトを節約し、可能なインデックスをにシフトして2つのダミーゼロ(0,および0 )を節約する必要があり0 1 2 3ます。しかし、これは非常に間違っていると感じているので、最初に別の解決策を考えてみます。:-)

7 Neil Sep 23 2020 at 19:18

木炭、55の48バイト

≔324516θFS«≔⌕θιιM✳⊗ι≔⭆§⪪”)⊟?2p}Þ↔~>”⁶ι§θIκ軬∨ⅈⅉ

オンラインでお試しください!リンクは、コードの詳細バージョンへのリンクです。入力を数字の文字列として受け取り、チャコールブール値を出力します。つまり-、原点に戻る場合は空白、そうでない場合は空白(空白を削除するには+2バイト)。説明:

≔324516θ

ダイの数字は、右、上、左、下、上、下の順です。

FS«

入力桁をループします。

≔⌕θιι

サイコロが転がされた方向を見つけます。

M✳⊗ι

その方向に移動します。

≔⭆§⪪”)⊟?2p}Þ↔~>”⁶ι§θIκ軬∨ⅈⅉ

514302 052413 415320 042531方向に応じてルックアップテーブルを使用して、数字を新しい位置に並べ替えます。

»¬∨ⅈⅉ

原点に戻ったのでしょうか?

6 xnor Sep 25 2020 at 15:52

Python 2、91バイト

a=b=1
t=0
for c in input():t=1+t*1j**(a*c*(a*a-c*c)*b**5%7*2/3+2*(a==c));a,b=b,c
print t==0

オンラインでお試しください!

アイデアは、示されている連続するダイ面の各トリプレットを、ダイのパスによって作成された対応するターンに変換することです。可能な方向転換は、左、右、直線、または逆方向であり、すべてダイの前の動きを基準にしています。一連のターンから、ダイの現在の座標を追跡し、それが原点に戻るかどうかを確認します。サイコロの向きを追跡する代わりに、回転時に座標系全体を回転させてから移動します。

このようにすることで、ダイ自体の状態を追跡する必要がなくなります。入力シーケンスのローカルスニペットを確認するだけで十分です。また、ハードコードされた値やマジックナンバーも使用しません。

トリッキーなビットは、3つの連続するダイ面からターン方向を抽出することです。これらは、最初の面から2番目の面へ、次に2番目の面から3番目の面へと這うバグと考えることができます。これを行うには、2番目の面をオンにする必要がある方向はどれですか。1番目と3番目の面が等しい場合は2倍に戻り、1番目と3番目の面が反対の場合はまっすぐ進むことが検出できるため、7になります。

残りのケースでは、バグが左から右に曲がるかどうか、つまり、顔のトリプルが左利きか右利きかを検出する必要があります。このために、CWソリューションから代数的トリックを借りて、側面からサイコロの値を決定します。式3*a*c*(a*a-c*c)は、トリプルが右利きであるか左利きであるかに応じて、いずれかbまたは-b7を法として等しくなります。そこから、いくつかのマッサージは、4を0,1,2,3法とする数に方向転換の4つのケースを取ります1j**。これにより、複素指数を使用して正しい複素回転を得ることができます。

5 JonathanAllan Sep 24 2020 at 05:30

ゼリー、35バイト

6RW;⁸œ?@\ḊḢ€⁼
“§ṫ²G‘×J$ṗLçƇ:19Ḣı*S¬

\ $ [1,6] \ $内の面のリストとして1ダイスパスを受け入れるモナドリンク。これは、最初に戻った場合は0(true)、それ以外の場合は(falsey)になります。

オンラインでお試しください!または、テストスイートを参照してください(メソッドが非効率的であるため、6つが最も長く削除されています)。

どうやって?

次の状態の順列インデックスとして、4つの可能な方向から形成された指定されたサイコロパスの長さのすべての可能なパスを形成します。
これらをフィルタリングして、指定されたサイコロパスの表向きの番号に一致するものを見つけます。
順列インデックスを複素数として4つのデカルト方向に変換します。
これらの合計がゼロかどうかを確認します。

“§ṫ²G‘×J$ṗLçƇ:19Ḣı*S¬ - Main Link: dice-path
“§ṫ²G‘                - list of code-page indices = [225,245,130,71]
      ×J$             - multiply by their indices = [225,490,390,284]
                        (these correspond to [up, down, right, left])
          L           - length (of the dice-path)
         ṗ            - Cartesian power (all lists of that length using {225,490,390,284})
            Ƈ         - filter keep those for which:
           ç          -   call Link 1 as a dyad - f(potential-path, dice-path)
             :19      - integer divide by 19 (225,490,390,284 -> 11,25,20,14)
                Ḣ     - head (get the single path that filering found)
                        (having Ḣ here rather than before the :19 saves a byte)
                 ı*   - i exponentiate (that) (11,25,20,14 -> -i,i,1,-1)
                        (yep we've mirrored but it makes no difference)
                   S  - sum
                    ¬ - logical NOT

6RW;⁸œ?@\ḊḢ€⁼ - Link 1: potential-path (as permutation indices), dice-path
6             - six
 R            - range -> [1,2,3,4,5,6]
  W           - wrap -> [[1,2,3,4,5,6]]
   ;⁸         - concatenate with the permutation indices -> [[1,2,3,4,5,6],a,b,c,...]
        \     - cumulative reduce (current-state, permuation index) by:
       @      -   with swapped arguments:
     œ?       -     permuation (of the current state) at index (permutation index)
         Ḋ    - dequeue (remove the leading [1,2,3,4,5,6])
          Ḣ€  - head of each (get the list of face-up pips)
            ⁼ - equals (the dice-path)?
4 Noodle9 Sep 23 2020 at 20:26

Pythonの3、174 \$\cdots\$ 130の129バイト

なんと保存された15の 30人自身に35バイトのおかげアルノーを!
保存された別のなんと3 9 10は、おかげバイトOVSを!

def f(l,p=[3,2,4,5,1,6],v=0):
 for d in l:n=p.index(d);v+=1j**n;p=[p[int(i)]for i in'%06d'%ord('񽣾첽񥙘꘣'[n])]
 return v==0

オンラインでお試しください!

True原点に戻った場合などに戻りますFalse。

複雑な算術を使用してニール港のチャコールの答えを使用して、開始した場所に戻っているかどうかを確認します。

4 DominicvanEssen Sep 24 2020 at 21:25

R、143 ... 116102バイト

編集:トランジションのマトリックスリストの代わりにリニアに切り替えることで-13バイト、次にトランジションのリストを半分にし、各ロールで左、後、下のダイ値を7から右、前、上の値を引いたものとして計算することで-4バイト、次に、ベース7でエンコードされた数値に切り替えて遷移のリストを生成することで-3バイト、次に遷移リストを上、右、下、左に再配置して-14バイトで、iの累乗を使用して新しい位置を簡単に計算できるようにします。アプローチを変更しなかった他のさまざまなマイナーゴルフによる-6バイト

p=a=1:4;m=5032105982%/%7^(11:0)%%7;for(i in scan()){p[6:4]=7-p;p=p[m[q<-(p[m[a]]==i)]];F=F+1i^a[q]};!F

オンラインでお試しください!

どうやって?

(ゴルフ前のコメントコード)

is_dice_loop=
function(s,                     # s = vector of top die values along path
 p=1:6,                         # p = positions of current die values
                                #     (top,front,right,left,back,bot)
 m=matrix(                      # m = matrix of transitions at each roll
  utf8ToInt(                    #     created from ASCII values of
   "bedcfabbccafddfaafeeebcd")  #     this string
   -96,                         #     -96,
  4)                            #     matrix has 4 rows.
 ){
 for(i in s){                   # Now, for each die value i along the path
  r=match(i,p[m[,1]]);          #  calculate the roll direction r
                                #  (1:4 -> up,down,right,left),
  p=p[m[r,]];                   #  then calculate the new positions of die values,
  F=F+(-.5+r%%2)*1i^(r>2)       #  and calculate the new location of the die
                                #  as a complex number (real=left->right, imaginary=down->up)
                                #  (F is initialized as 0+0i by default).
 }
 !F                             # If we end up back at 0+0i, then we've done a loop,
}                               # so NOT F is true.  
4 att Sep 25 2020 at 04:16

Wolfram言語(Mathematica)、96 91 8374バイト

<<Quaternions`
0==Tr[a={-1,-K,J,-J,K,1};(a=#**a**#/2;#-1)&[1+a[[#]]]&/@#]&

オンラインでお試しください!

Quaternions` 関数定義の前にロードする必要があります。

<<Quaternions`          (* load the Quaternions` package *)
a={-1,-K,J,-J,K,1};     (* (a die roll of i moves the die in direction a[[i]]) *)
(a=#**a**#/2;#-1)&      (* rotate `a` in a direction, returning the direction, *)
% [1+a[[#]]]&/@#        (* taking directions one at a time from input. *)
0==Tr[ % ]&             (* check if sum of those directions returns to the origin. *)
2 NahuelFouilleul Sep 30 2020 at 03:05

パール5 -pF、130、121のバイト

@A=(2,4,-1,1,-@F,@F+!s/^/1/);s/.(?=.(.))/$x+=$A[$&==$1||$&+$1!=7&&($P[$|--]=$&)&&$1==$P[$|]?$A[$|]^=1:$A[$|]]/ge;$_=$x==1

オンラインでお試しください!

別の解決策である単純な解決策は173バイトで、165バイトに変換できました。

編集:私はその後、単純なものを136バイトにゴルフできることに気づきました

しかし、もっとゴルフをするのは違うけど。反対側の合計が7であるという事実を使用します。そして、以前の数を追跡することで、方向を取得するのに十分である可能性があります。

  • 配列A:
    • [0]= {2 | 3}および[1]= {4 | 5}:(+/-)xまたは(+/-)yに方向を格納します。ここで、xおよびyは、これらの軸での最初の移動の方向に依存します。
    • 次[2..5]:$x方向に対応して追加する番号を格納する
  • s/^/1/:1最初の面を追加します
  • 正規表現.(?=.(.)):1つのダイ面$&を消費し、次のダイ面をキャプチャします$1
  • $&==$1 方向が逆になっています
  • $&+$1==7 方向は変わらず、何もすることがないのでテストが逆になります
  • それ以外の場合、方向は前の方向と比較して右または左に変更されています
  • 配列P:最後のダイ面[0] x、[1] yを格納します。ここで、xとyは最初の移動に依存します
    • $P[$|--]=$& :
      • $P[$|]=$& 左または右に曲がるときにダイ面を保管する
      • $|-- x / yの軸インデックス0/1を切り替えます
  • $1==$P[$|] 同じ軸上を移動すると、次の次の面が最後の面と比較されます。等しい場合、方向は前の方向と比較して後方に変化します。
  • ^=1 :bytwise xor(2 <-> 3)または(4 <-> 5)を使用して切り替える
  • $_=$x==1:$x==1最初の移動(方向2:-1)が追加されなかったための初期位置。