クロス、ノーズなし


10

Tic Tac Toeが解決されたゲームであることは誰もが知っています。ただし、Only-XのMisèreバージョンは興味深い代替手段を提供します。

このバージョンのゲームでは、両方のプレイヤーがボード上でXをプレイし、連続して3つになることを避けます。これについて詳しく知りたい場合は、Numberphileがこのコンセプトに関する素晴らしいビデオを公開しています。

ミゼールクロスのボードが与えられたら、最適な動きをします。

ボードは、3文字の3行で、Xまたはです。したがって:

X X
X  
 XX

有効なボードです。入力と出力が同じ形式を使用している限り、これを任意の便利な形式で使用できます。形式には次のものが含まれます(ただし、これらに限定されません)。複数行の文字列(オプションで末尾の改行)。Xまたはである文字の2D配列。各位置が再生されたかどうかを表すブール値の1Dフラット化配列。

最適な移動とは、最適なプレーを継続するか、損失を可能な限り長くすることで勝利することを保証する移動であり、次のルールによって定義されます。

  • 3つ続けて作成することは避けてください。
  • あなたが最初に行くなら、真ん中でプレーします。
  • 唯一の占有スペースが中央である場合、残りのスペースのいずれかでプレイします。
  • 中央のマスが占有されておらず、外側のマスが占有されている場合は、対戦相手の最後のプレイの反対側でプレイする
  • 真ん中の正方形が占められており、外側の正方形が占められている場合は、前の動きから「騎士の動き」(反対側、1オーバー)を離してください。
  • 失うことのない残りのマスが残っていない場合は、残りのマスのいずれかでプレイします。

[注:これは1つの場合に最適ではないことが証明されていますが、とにかくこのアルゴリズムを使用する必要があります。]

以前の動きはすべて最適だったと思うかもしれません。したがって、最初のサンプルボードは有効な入力ではありません。対戦相手の動きは最適な場合とそうでない場合があります。

ゲームが終了した場合(つまり、3つ続けて行われた場合)の動作は未定義です。

これはなので、バイト単位の最短の回答が優先されます!

最適な移動のみを使用した1つの可能なパスは次のとおりです。

[   ]  [   ]  [X  ]  [X  ]  [X  ]  [X  ]  [XX ]
[   ]->[ X ]->[ X ]->[ XX]->[ XX]->[ XX]->[ XX]
[   ]  [   ]  [   ]  [   ]  [ X ]  [XX ]  [XX ]

最適でない動きを使用して対戦相手から発生する可能性のある入力は次のとおりです
(このリストの左側のボードのみが有効な入力であることに注意してください)。

[X  ]  [X  ]
[   ]->[   ]
[   ]  [  X]

[XX ]  [XX ]
[   ]->[   ]
[  X]  [ XX]

[XX ]  [XX ]
[X  ]->[X X]
[ XX]  [ XX]


入力と出力のフォーマットは何ですか?ボードを配列または文字列として想定していますか?しかし、これは最後の動きに関する情報を提供しないので、次の質問です。
Level River St

1
「対戦相手の最後のプレイの反対側でプレイする」戦略は、対戦相手の移動履歴に関する知識があるか、またはこの戦略を以前に実行したことがある、つまりボードなどを継承していないことを前提としています.XX\nX..\nX..。このようなボードの継承を検討する必要がありますか?
Level River St

@LevelRiverSt書かれているように、「以前の動きはすべて最適だったと思うかもしれません」ので、ボードは無効な入力になります。あなたは好きなフォーマットで入力をとることができますが、あなたの例のような複数行の文字列には「デフォルト」があります:移動ロジックがポイントであるときに文字列を解析する必要があるだけに誰も制限したくないチャレンジ。
'97年

回答:


3

Ruby、Rev B 121バイト

提出は無名関数からを引いたものf=です。使用方法を説明するためにテストプログラムに示されています。

f=->n{["~mK)\7","}uYwQO"][l=n%2].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m/2*257>>j&255==126-t&&t+j%2!=119&&l=m}}}
l}

puts g=f[gets.to_i]
puts
[7,6,5,
 8,0,4,
 1,2,3].each{|i|print g>>i&1; puts if i/3==1}

中央の正方形を最上位ビットではなく最下位ビットにすることで節約された2バイト(の/2代わりに削除されます%256。)許容可能な移動のテーブルの再編成による残りの節約。Xの総数ではなく、中央の正方形の空き/占有として整理すると、より簡単なテストが可能になります。また、配列には2つの文字列しかないため、%w{string1 string2}構文は破棄され、構文が優先され["string1","string2"]ます。これにより、印刷不可能な文字\7を含めることができます。これにより、の126-t代わりに、より単純なエンコーディングを使用できます(36-t)%120

Ruby、Rev A 143バイト

->n{l=r=("%b"%n).sum%8
%w{$ %5 - I+Wy Q S#}[r].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m%256*257>>j&255==(t-36)%120&&t+j%2!=43&&l=m}}}
l}

これは無名関数です。入力/出力フォーマットは開いたままにしていたので、9ビットの2進数を使いました。512のビットは中心を表し、残りのビットはその周りをらせん状にしています(1のビットはコーナーと見なされます)。

許容可能な出力よりもはるかに多くの可能な入力があるため、アルゴリズムはすべての動きを試み、許容可能な出力パターンに適合するものを見つけることです。Xの数ごとに許容される出力パターンはハードコーディングされています。

中央の正方形に関する情報は取り除かれ、残りの8ビットはそれらを複製するために257で乗算されます。このパターンは、右シフトによって許容可能なパターンを超えて回転されます。

パターンが検出されてもループは終了しないため、返されるパターンは最後に検出された許容可能なパターンになります。このため、好ましいパターン(好みがある場合)はリストの後半にあります。

「騎士の動き」戦略を考えると、パターンが45度回転するかどうかはあまり重要ではありません。非ゴルフバージョンは騎士の移動戦略に従うため、コーナースクエアとエッジスクエアを区別する必要はありません。

ただし、次のトリックがあるため、これが常に最良の戦略であるとは限りません。あなたの対戦相手が最初に行き、センターを取るなら、彼は勝つべきです。しかし、彼の2番目の手で、彼は2x2の正方形を作ることができるという間違いを犯します。これにより、彼は3つ続けて作るように強制することができます。これはゴルフバージョンで実装されます。この1つのインスタンスでは、コーナーにある3つのX(敵を強制的に失う)と1つのエッジに沿った3つのX(即時自殺)を区別するために、少し余分なコードが必要です。

テストプログラムに含まれていない

非ゴルフバージョンは、質問で表現されたロジックに従います。

ゴルフバージョンでは[[0],[1,17],[9],[37,7,51,85],[45],[47,119]]、ケースに対してわずかに異なる動作を実装するようにテーブルがわずかに変更されていますr=3。次に、印刷可能なASCIIに圧縮されます(デコードが必要です(t-36)%120)。テーブルエントリ7の場合、コーナーの3つのXとエッジに沿った3つのXを区別するには、追加のロジックビットが必要です。&&t+j%2!=43

f=->n{l=r=("%b"%n).sum%8                                      #convert input to text, take character checksum to count 1's(ASCII 49.) 
                                                              #0 is ASCII 48, so %8 removes unwanted checksum bloat of 48 per char.
                                                              #l must be initialised here for scoping reasons.
  [[0],[1,17],[9],[11,13,37,51,85],[45],[47,119]][r].each{|t| #according to r, find the list of acceptable perimeter bitmaps, and search for a solution.
    9.times{|i|(m=n|1<<i)==n||                                #OR 1<<i with input. if result == n, existing X overwritten, no good.
                                                              #ELSE new X is in vacant square, good. So.. 
      8.times{|j|m%256*257>>j&255==t&&l=m}}                   #%256 to strip off middle square. *257 to duplicate bitmap.
                                                              #rightshift, see if pattern matches t. If so, write to l
  }
l}                                                            #return l (the last acceptable solution found) as the answer.

#call function and pretty print output (not part of submission)
puts g=f[gets.to_i]
puts
[6,7,0,
 5,8,1,
4,3,2].each{|i|print g>>i&1; puts if i<3}

テストプログラムの出力

これは、コンピュータが自分自身を再生するときに起こります。

C:\ Users \ steve> ruby​​ tictac.rb
0
256

000
010
000

C:\ Users \ steve> ruby​​ tictac.rb
256
384

010
010
000

C:\ Users \ steve> ruby​​ tictac.rb
384
400

010
010
100

C:\ Users \ steve> ruby​​ tictac.rb
400
404

010
010
101

C:\ Users \ steve> ruby​​ tictac.rb
404
436

010
110
101

C:\ Users \ steve> ruby​​ tictac.rb
436
444

010
110
111

ゲーム分析が最初に

これは実際には非常に単純で線形です。

最初にプレイするときは、真ん中の正方形が常に最初に占める正方形になります。

r = 0

...  binary representation 0
.X.
...

r = 2

X..  binary representation 1001=9 
.XX
...

r = 4

X.. binary representation 101101=45
.XX
XX.

ゲームが終わっていない状態で、ボード上の中央の正方形を含む5つのXを使用する方法は(対称性まで)1つだけです。中央の正方形にXがあり、各対角線に1つ(互いに90度)と、水平/垂直の各中心線に1つ(互いに90度)です。エッジ全体を占めることができないため、上記の唯一のものです。可能な配置。他のプレーヤーは次の手で負けなければなりません。

ゲーム分析プレイングセカンド

他のプレイヤーが真ん中のマスを選んだかどうかによって、プレーはかなり異なります。

r = 1

真ん中の正方形

.X. X..  binary representation 1 
.X. .X.
... ...

ミドルスクエア無料

X.. .X. binary representation 10001=17
... ...
..X .X.

r = 3

真ん中の四角が占有、他のプレイヤーが最後のXに隣接してプレイする場合以下のように、騎士の移動をプレイすることが、ゴルフされていないバージョンでサポートされています

XX. .XX binary representation 1011=11 
.X. XX. or mirror image 1101=13
X.. ...

ただし、上記は最善の動きではなく、ゴルフバージョンではサポートされていません。最善の動きは次のとおりであり、次のターンで勝利を強制します。

XX. binary representation 111=7.           XXX
XX. Only to be used where j is odd.        .X.
... Even j would look like image to right. ...

他のプレイヤーが最後のXに対して90度または135度でプレイする場合、真ん中の正方形が占有されます(ナイトの移動でプレイします)。

X.X .X. binary representation 100101=37 
.X. .XX
.X. X..

ミドルスクエアフリー

X.X .X. XX. binary representations:
... X.X ...    1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)

r = 5

中央の正方形が占有されています。上記のr = 4で述べた理由により、4つの可能な手がありますが、すべて負けです。101111 = 47の1つのみがサポートされています。

中央の広場は無料です。次のように、対称性に達する可能性のあるボードは1つだけです。他のプレイヤーは次の手で負けなければならないので、r> 5をサポートする必要はありません。

XX. binary representation 1110111=119
X.X
.XX

これは素晴らしい答えです!すべてのケースで最適な萌えをチェックしたと思いますが、見逃していると思います。ただし、仕様は単純化のために同じままです。(本当にこれは驚くべきことです。これを実行してくれてありがとう、これはとてもよく説明されています!私はI / Oを失ったので、人々はこのようなすばらしいことをすることができました。)
CAD97

1
ありがとう、それは興味深い挑戦でした。今ではかなりゴルフをすることができました。
Level River St
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.