騎士はどこでN移動できますか?


21

これは、APL CodeGolf のオータムトーナメント Hole-3 です。私はそこで問題の元の著者であるため、ここに再投稿することができます。


与えられた:

  1. ターン数(動きが0でない場合は状態を示し、そうでない場合は1と呼ばれると仮定します)および

  2. 8行8列のチェス盤上の1つ以上の開始位置のリスト(任意の形式で、0または1のインデックス付き座標、64の連続する数字/文字、またはA1–H8 –状態)

(入力と同じ形式で)騎士が指定されたターン数の後に存在できる一意の位置のリストを(任意の順序で)返します。

  • 各騎士は毎ターン移動する必要がありますが、同じ広場に複数の騎士がいることを心配する必要はありません。

  • ナイトは、currentでマークされた現在の位置に対してXでマークされた位置にのみ移動できます。
    騎士が移動できる場所

例(1インデックスの座標)

1から移動[[1,1]]: [[2,3],[3,2]]

2から移動[[1,1]]: [[1,1],[1,3],[1,5],[2,4],[3,1],[3,5],[4,2],[4,4],[5,1],[5,3]]

1から移動[[1,1],[5,7]]: [[2,3],[3,2],[3,6],[3,8],[4,5],[6,5],[7,6],[7,8]]

2から移動[[1,1],[5,7]]: [[1,1],[1,3],[1,5],[1,7],[2,4],[2,6],[2,8],[3,1],[3,3],[3,5],[3,7],[4,2],[4,4],[4,6],[4,8],[5,1],[5,3],[5,5],[5,7],[6,4],[6,6],[6,8],[7,3],[7,7],[8,4],[8,6],[8,8]]

0から移動[[3,4]]: [[3,4]]


[ランク、ファイル]の代わりに0〜63の番号を付けることで、チェスのスペースを入出力できますか?
デイブ

@Dave Sure、どうして?I / Oと一貫性を保つだけです。
アダム

8
私はこのHNQを「騎士がNiに移動する場所」と読むことを誓います
シドニー

3
パンの警告:ナイトの表記はNです
ジョシュア

ステップ数に1から始まるインデックスを使用できますか?例:[[1,1]], 2 -> [[2,3],[3,2]]
ズガルブ

回答:


11

Wolfram言語(Mathematica)、45バイト

他のソリューションは間違っているため(下記のMartinのコメントを参照)、ソリューションを投稿することにしました。

8~KnightTourGraph~8~AdjacencyList~#&~Nest~##&

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

究極の挿入記法...

2つの入力を取ります。最初の入力は範囲内の番号のリスト[1,64]で、ナイトの開始位置を記述します。2番目の入力はステップの数です。

このソリューションは、Mathematicaの組み込み関数の非常に便利な機能に依存しています。

  • AdjacencyListは、その右側に頂点のリストを取り、それらのいずれかに隣接する頂点のリストを返します。既に削除された重複とソート済みです。
  • KnightTourGraph組み込みです。驚きではありません。
  • Nest順序で引数を取りNest[f, expr, n]、我々はスプラットことができた、##とその右側の上にNest[f, ##]
  • 最後に、Mathematicaはa~b~c~d~eとして解析する(a~b~c)~d~eため、角括弧は必要ありません。中置表記法とフラット化がなければ##、そうなりますNest[AdjacencyList[KnightTourGraph[8, 8], #] &, #, #2]&

1
既存の解決策をアウトゴルフすることには何の問題もないと思います。
アダム

1
これは複数の開始位置で機能しますか?
アダム

すごい!今、私はこれをどのように読むかを理解する必要があります...-
デイブ

これは、仮想のMthmcaゴルフ言語ではおそらく17バイトになります。
マイケルスターン

7

JavaScript(ES7)、99バイト

入力/出力形式:[0 ... 63]の二乗インデックス。

f=(a,n)=>n--?f([...Array(64).keys()].filter(p=>!a.every(P=>(p%8-P%8)**2^((p>>3)-(P>>3))**2^5)),n):a

テストケース

このスニペットには、OPが提供する形式との間で変換する2つのヘルパー関数が含まれています。

どうやって?

以下からの移動(X、Y)(X、Y)は、我々はどちらか持っている場合は、有効な騎士の動きであります:

  • | xX | = 1および| yY | = 2または
  • | xX | = 2および| yY | = 1

絶対値を使用する代わりに二乗することにより、これは次のように表現できます。

  • xX )²= 1および(yY)²= 4、または
  • xX)²= 4および(yY)²= 1

ので14が与える唯一の完璧な正方形で5を一緒にXOR演算するとき、我々は次の場合に有効な騎士の動きを持っています:

(xX)²XOR(yY)²XOR 5 = 0

この式をボード上の各正方形p = 8y + xと各ナイトスクエアP = 8Y + Xに適用して、新しい可能なナイトターゲットスクエアを推定し、このプロセスをn回再帰的に繰り返します。


5

オクターブ、69バイト

function a=f(a,n,b=~a)for k=1:n;a=b&imdilate(a,de2bi(")0#0)"-31));end

オンラインデモ!

入出力は、バイナリ8 * 8マトリックスとしての開始/終了時のボードの構成です。

説明:

n手順については、次のマスクを使用してボードの形態学的拡張を繰り返します。

01010
10001
00100
10001
01010

5

網膜147102バイト

.$
$*	
¶
 ¶
{s`((?<=N(....|.{11}|.{13})?.{7})|(?=.{8}(....|.{11}|.{13})?N))\S(?=.*	)
n
Ts`	Nn`_:N`.*¶	

オンラインでお試しください!:騎士にNsのマークが付いた8x8のsのボードとして入力を受け取り、次の行のターン数を表す数字を入力します(9ターンを超えることは意味がありませんが、追加でサポートできると主張する場合)バイト)。出力には追加の空白が含まれていることに注意してください。編集:@MartinEnderのおかげで45バイト保存されました。説明:最初の段階では、ターン数を単項に変換しますが、タブ文字を使用して、後で偶然に一致しないようにします。一方、2番目の段階では、正規表現の折り返しを防ぐためにボードの右側にスペースを追加しますエッジ。第三段階は、すべて置き換えNSと:から離れる騎士の動きをしているのNn四段目は、残りの削除ながらNsは、変更をnsからNsに移動し、移動カウントから1を引きます。これは、移動カウントがゼロになるまで繰り返されます。


これが最も印象的です。間違いなく仕事にふさわしいツールではありません!
アダム

4

ゼリー、29バイト

+þ1,2Œ!×þ1,-p`¤¤Ẏ¤Ẏ⁼%8$$ÐfQµ¡

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

0インデックス付きの座標。これがほぼ最適であることはほぼ確実です。

user202729のおかげで-1バイト

説明

+þ1,2Œ!×þ1,-p`¤¤Ẏ¤Ẏ⁼%8$$ÐfQµ¡  Main Link
+þ                             Addition Table (all pairs using + as combining function) with
  1,2Œ!×þ1,-p`¤¤Ẏ¤             All knight moves:
  1,2                          [1, 2]
     Œ!                        All permutations ([1, 2], [2, 1])
       ×þ                      Product Table (all pairs using × as combining function) with
         1,-p`¤                [1, 1], [1, -1], [-1, 1], [-1, -1]
         1,-                   [1, -1]
            p`                 Cartestian Product with itself
               ¤               All knight moves (in a nested array) as a nilad
                Ẏ¤             Tighten (flatten once); all knight moves in a (semi-)flat array
                        Ðf     Keep elements where
                   ⁼%8$$       The element equals itself modulo 8 (discard all elements out of the range)
                          Q    Remove Duplicates
                           µ   Start new monadic chain (essentially, terminates previous chain)
                            ¡  Repeat n times; n is implicitly the second input (right argument)

1
0インデックスのゼリー?
アダム

1
@Adámフィルタリングを簡単にします
。P– HyperNeutrino

2
APLの現在のレコード所有者は24文字で処理しているため、Jellyはこれを15バイト未満で実行できると期待しています。
アダム

3つ以上の$がある場合、それを前のリンクに移動して、で参照できる可能性がありますÇ
user202729

@ user202729そうそう、ありがとう。
ハイパーニュートリノ

3

05AB1E27 25バイト

2バイトを節約してくれたEmignaに感謝します!

1インデックスの座標を使用します。

コード:

F•eĆ•SÍü‚Dí«δ+€`Ùʒ{`9‹*0›

05AB1Eエンコードを使用します。オンラインでお試しください!

説明:

F                          # Do the following <input_1> times..
 •eĆ•SÍ                    #   Push [-1, -2, 1, 2, -1]
       ü‚                  #   Pairwise pairing: [[-1, -2], [-2, 1], [1, 2], [2, -1]]
         D                 #   Duplicate the array
          í                #   Reverse each element
           «               #   Concatenate to the previous array

これにより、次の配列が得られます。

[[-1, -2], [-2, 1], [1, 2], [2, -1], [-2, -1], [1, -2], [2, 1], [-1, 2]]

騎士の動きのデルタです。

            δ+             #   Addition vectorized on both sides
              €`           #   Flatten each element
                Ù          #   Uniquify
                 ʒ         #   Keep elements which..
                  {`9‹     #     Has a maximum element smaller than 9
                      *0›  #     And a minimum element larger than 0

•eĆ•SÍü‚代わりにƵ‡4в2ô<D(«を使用して、2バイトを節約できます。
エミグナ

@Emignaああ、それは賢い、ありがとう!
アドナン

2

Python 3、105バイト

p=lambda g,i:i and list(set(p([x+y for x in g for y in[6,10,15,17,-6,-10,-15,-17]if 0<=x+y<64],i-1)))or g

再帰には名前付きラムダを使用する必要があります。それが失格かどうかわかりません。開始位置を0から始まる正方形のリストとして渡します。0は移動なしとしてカウントされます。


2

Java(OpenJDK 8)、124バイト

(m,p)->{for(;m-->0;)for(long a=p,i=p=0,j;i<64;i++)for(j=64;j-->0;)p|=(p=i%8-j%8)*p+(p=i/8-j/8)*p==5?(a>>i&1)<<j:0;return p;}

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

入力/出力形式

入出力はa long(64ビット)のビットとして表されます。セットビットは馬が存在することを意味し、セットされていないビットは馬が存在しないことを意味します。例:

// [[0, 0]]
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001L

説明

(m, p) -> {                          // Lambda. No currying because m and p are modified
 for(;m-->0;)                        // For each move
  for(long a=p,i=p=0,j;i<64;i++)     // Declare variables, move p to a, create a new p and loop on bits of a.
   for(j=64;j-->0;)                  // Loop on bits of p.
    p |=                             // Assign to p a value.
     (p=i%8-j%8)*p+(p=i/8-j/8)*p==5  // If i -> j is a valid horse move, see Arnauld's JavaScript answer for full explanations
      ? (a>>i&1)<<j                  // Assign the presence of the horse (i-th bit of a) to the resulting board (j-th bit of p).
      : 0;                           // Else it's not a valid horse move
 return p;
}

クレジット

  • Nevayのおかげで19バイトが節約されました!
  • (X-x)²+(Y-y)²==5ArnauldのJavaScriptの答えからトリックを再利用しました
  • 新しいアルゴリズムのNevayのおかげで、さらに1バイト節約されました!
  • Nevayのおかげでint[]、64ビットに切り替えることで、さらに7バイト節約されましたlong

1
169バイト:(m,p)->{for(;m-->0;){int i=64,a[]=p,x,y,u[]={1,3,5,9,15,19,21,23};for(p=new int[i];i-->0;)for(int z:u)if((((x=i/8+z/5-2)|(y=i%8+z%5-2))&-8)==0)p[x*8+y]|=a[i];}return p;}
Nevay

1
-1バイト:(m,p)->{for(int i,j,a[],x;m-->0;)for(a=p,p=new int[i=64];i-->0;)for(j=64;j-->0;)p[j]|=(x=i%8-j%8)*x+(x=i/8-j/8)*x==5?a[i]:0;return p;}
Nevay

ありがとう@Nevay!かっこ/ブロックを削除するコードを追加するのはいつでもいいことです!;-)
オリビエグレゴワール

1
-7バイトint[]long次の(m,p)->{for(long i,j,a;m-->0;)for(a=p,p=i=0;i<64;i++)for(j=64;j-->0;)p|=(p=i%8-j%8)*p+(p=i/8-j/8)*p==5?(a>>i&1)<<j:0;return p;}
文字に

乾杯、そんなことすることすら考えていませんでした!いい仕事です、@ Nevay ;-)
オリビエグレゴワール

2

ゼリー29 28バイト

8Rp`
“¦Ʋƈ2’D_2ṡ2+€µẎ
ÇƓ¡f1£Q

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

ターン数はSTDINを通り、平方は引数です。

これにより、@ HyperNeutrinoのJellyソリューションが結び付けられますが、アプローチは異なります。

@HyperNeutrinoを1バイト単位で叩きます!

いくつかのバイトをノックオフするための提案が必要です!

リンク1(チェス盤)

8Rp`
8R   = The list [1,2,3,4,5,6,7,8]
  p` = cartesian multiplied with itself (this results in the chessboard)

リンク2(世代の移動)

“¦Ʋƈ2’D_2ṡ2+€µẎ
“¦Ʋƈ2’          = the number 103414301
      D         = converted into a list of digits
       _2       = subtract two from each element
         ṡ2     = overlapping pairs
           +€   = add to the list of squares
             µ  = Make sure the next part isn't treated as a right argument
              Ẏ = Tighten the list (Reducing the depth by one)

リンク3(スクエアチェック)

ÇƓ¡f1£Q
ÇƓ¡     = Repeat link #2 the requested amount of times
   f1£  = Remove everything not a member of link #1 (not on the chess board)
      Q = Make sure squares don't appear more than once

1

、18バイト

u!¡ṁö`fΠR2ḣ8=5ṁ□z-

正方形とステップの1ベースのインデックスを使用します。 オンラインでお試しください!

説明

u!¡ṁö`fΠR2ḣ8=5ṁ□z-  Implicit inputs, say P=[[1,1],[5,7]] and n=2
  ¡                 Iterate on P:
   ṁö               Map the following function, then concatenate:
                     Argument is a pair, say p=[5,7].
          ḣ8         The range [1,2,..,8]
       ΠR2           Repeat twice, take cartesian product: [[1,1],[1,2],..,[8,8]]
     `f              Filter with this predicate:
                      Argument is a pair, say q=[3,8].
                z-    Zip p and q with difference: [-2,1]
              ṁ□      Sum of squares: 5
            =5        Is it 5? Yes, so [3,8] is kept.
 !                  Take n'th step of the iteration.
u                   Remove duplicates, implicitly print.

1

R145の 183 134バイト

これは、ジュゼッペの最初のゴルフゴルフではないアルゴの素晴らしいゴルフの結果です(下記のコメントを参照)

function(x,n){x=x%/%8*24+x%%8
t=c(49,47,26,22)
t=c(t,-t)
for(i in 1:n)x=intersect(v<-outer(1:8,0:7*24,"+"),outer(x,t,"+"))
match(x,v)}

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

入力と出力は1〜64ベースです。1 ... 64表記を使用して位置のベクトルを取得します。9枚のボードで構成されるスーパーボードである1:576表記にマップします。この表記では、各反復で、各騎士は+/- 22,26,47,49で移動できるはずです。中央のボードから落ちるものを除き、将来の位置を1 ... 64表記に戻します。TIOの例は、8x8マトリックスを使用して結果を表示します。


これは最初のテストケースで失敗するようです(2ではなく4つの座標を返します)。
-Zgarb

Zgarbを指摘してくれてありがとう、私は今問題を修正したと思う
-NofP


または148は、バイトあなたがそれを取る場合は[0...63]代わりに表記。
ジュゼッペ

1
134バイト[1..64]入力および出力のために。+1、しかし、これは素晴らしい答えです。
ジュゼッペ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.