このTic-Tac-Toeボードは有効ですか?


48

チャレンジ

任意の形式の三目並べボードを使用して、それが有効かどうかを判断します。ボードが三目並べゲームの結果である場合、それは有効です。たとえば、このボードは有効です。

XOX
OXO
XOX
それどころか、このボードは無効です。

XXX
XXO
OOO

入力

  • フル(9/9)チックタックトーボード(ゲームではなく結果)。

ルール

  • 入力形式は、可能な512個の入力ボードすべてを表示できる必要があります。不明瞭/不明瞭な場合は、作成するための指示とともに指定する必要があります。ただし、ボードのマークは個別に記載する必要があります。
  • 有効性と無効性の2つの出力が必要です。
  • ボードに空のスポットがないと仮定できます。

テストケース

有効:

XOX
OXO
XOX

XOX
XOX
OXO

XOO
OOX
OXX

OXO
XOX
OXO

無効:

XXX
XXX
XXX

OOO
OOO
OOO

XXX
OOO
XXX

OOO
OOX
XXX

XXO
OXO
OOX

少しの援助?

ボードは、次の2つの条件が満たされている場合にのみ、このチャレンジに対して有効と見なされます。

  • 5 Xと4 O、または4 Xと5 Oがあります。たとえば、
    XXX
    OXO
    XXX
    7つのXと2つのOがあるため、無効と見なされます。
  • 5マークのプレイヤーのみが勝ったか、またはどれも勝ちませんでした。例えば、
    XXX
    OOO
    OOX
    Osの行またはsの行がX最初に形成されるため、無効と見なされます。2人のプレーヤーが同時に順番を回すことはできません。

現在の勝者は...

... ais523のゼリーの答え、驚異的な26バイト!


2
また、のようなテストケースを追加しO O O X O X X O Xて、同じプレーヤーが横列と縦列の両方を持っていることを示すこともできます。
smls 16

2
ただし、ボードのマークは個別に記載する必要があります。私はその部分を理解するかどうかわかりません。反例を教えてください。
アーナルド

3
@Tim Xには4つのマークがあります。
マーティンエンダー

2
@Sparr「5マークのプレイヤーだけが勝ったか、どれも勝っていない」
マーティンエンダー

2
@Kevin(1番目のコメントに返信)2番目のプレイヤー(4マークのプレイヤー)が勝った場合、9/9ボードは完成しません。
エリックアウトゴルファー16

回答:


11

ゼリー、26バイト

ṢŒrṪ4=$$Ðfx3ðœ-µẆm€6R¤;/µL

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

入力形式は少し変わっています。ボードを表す文字列ですが、Windowsの改行(キャリッジリターンの後に改行が続く)を使用します。たとえば、XXO\r\nOXO\r\nOOX。(実際には、行間の2文字のパディング文字列は機能しますが、Windowsの改行は他のオプションよりもはるかに防御可能です。)

基本的な考え方は、入力に4回出現するが、元の文字列に3つの等間隔の出現がない文字を探すことです。3×3グリッドの行間に2文字以上のパディング文字がある場合、すべての水平線、垂直線、対角線は等間隔になりますが、他の等間隔の行に3つの要素を含めることはできません。

説明:

ðそしてµSはチェーンセパレータそれぞれ独立している複数の部分にプログラムを分割し、。わかりやすくするために、それらを下のスペースに置き換えました。

ṢŒrṪ4=$$Ðfx3 œ- Ẇm€6R¤;/ L
Ṣ                           sorted version of the input
 Œr                         run-length-encode it
        Ðf                  keep only elements where
   Ṫ                        delete the last element, and it was
    4=                      equal to 4
      $$                    parse Ṫ4= as a group
          x3                repeat each element three times

                Ẇ           all sublists of the input
                 m€         take every nth element of each (€) sublist
                   6R       for each n in 1..6
                     ¤      parse 6R as a group
                      ;/    flatten one level (m€ creates a nested structure)

             œ-             multiset difference
                         L  length of that difference

言い換えると、入力に正確に4回現れる文字のリストを見つけ、それらのそれぞれの3つのコピーで構成されるリストを作成します。元の文字列で等間隔にあるすべてのサブシーケンスのリストを見つけます。そして、最初から2番目を引くと、結果の長さは1になります(つまり、プレーヤーは4回プレイしたが勝てなかった)。3×3グリッドであり、すべてのマスがいっぱいであるため、両方のプレイヤーが4回プレイすることは不可能です。Jellyでは、1は真実であり、0は偽であるため、結果のリストをブール値に変換するために特別なことをする必要はありません。(µLそうでない場合は、両方のために、しかし、必要とされる“XXX”“OOO”可能truthy出力値となり、そして質問はすべての有効なボードが同じ出力を与えることが必要です。)


3
これは完全に読み取り可能です。
パブラム

21

JavaScript(ES6)、88 87バイト

s=>(a=[...s]).sort()[5]-a[3]&[7,56,73,84,146,273,292,448].every(j=>j&i,i=`0b`+s^~-a[4])

9つの文字列として入力を受け取り、0そして1文字と戻り1、有効なため0無効のため。文字を順番に並べ替えます。中央の3つのキャラクターが同じ場合、1つのピースが多すぎるため、ボードは無効です。それ以外の場合、元のボードをバイナリに変換し、0sよりも1s が多い場合はビットを反転します。この時点で、03行の行がない場合、ボードは有効であるため、ビットマスクの配列を介して8行すべてをテストします。編集:@ETHproductionsのおかげで1バイト保存されました。


@ETHproductionsああ、もちろん、結果は0または1になります。
ニール

14

Pythonの3、131の 127 125 100 96バイト

ボードが有効かどうかを計算する代わりに、異なるアルゴリズムのアプローチ(および組み込みの圧縮を備えたこれらのマルチバイトゴルフ言語に本当に適しているアプローチ)の場合、各ビットが512ビットの数値を持ち、各ビットが特定のボードが有効かどうか、およびボードを表すバイナリ値を渡します。さらに、対称性により、ゼロの束とともに、テーブルの後半を削除できます。

def z(b):return int('agqozfx67wwye6rxr508ch2i8qicekpreqkap0725pk',36)<<24&1<<b+(b>255)*(511-b-b)

テスト値:

X X X
O X O
X X X

バイナリ値として表され、0b111010111ボードが有効な場合、関数はゼロ以外の値を返します。


4バイト少ない中間変数を削除
Ken YN

a&(1<<b)角かっこを必要としないため、2バイト少なくなります。
ケンYN

対称性を使用して25バイトをノックオフし、24個の最下位のゼロビットを短縮してもう1つ-ゴルファーの方法が必要if b>255:b=511-bです!
ケンYN

ゴルファーの方法を見つけたif
ケンYN

11

バッチ、140バイト

@set/aXXX=OOO=O=0
@for %%l in (%* %1%2%3 %1%4%7 %1%5%9 %2%5%8 %3%5%7 %3%6%9 %4%5%6 %7%8%9)do @set/a%%l+=1
@cmd/cset/a!XXX*!(O-=5)+!OOO*!~O

入力を9つの個別のコマンドライン引数として受け取り1、有効と0無効の出力を行います。またはのO直交線を見た回数を追跡することで機能します。便利なことに、Batchを使用すると、間接的に整数演算を実行できます。そのため、変数をインクリメントするのではなく、変数を増やします(言及した3つの変数のみに関心があります)。次に、勝っていないで5 秒あるか、勝っていないで4 秒あるかをテストする必要があります。OOOXXX%%lXOOO


10

Mathematica、82 75バイト

7バイトを節約してくれたMartin Enderに感謝します!

t=Total;3<(b=#~t~2)<6&&{t[c=If[b>4,1-#,#]],t/@c,Tr@c,Tr@Reverse@c}~FreeQ~3&

無名関数の入力として1と0の3×3のネストされたリストを取得し、出力しますTrueFalse

Total関数の便利な柔軟性を使用します(ここではにゴルフしますt):例の配列を指定するe = { {1,2,3} , {4,5,6} , {7,8,9} }と、コマンドt[e]は3つのベクトルを合計します(ここでは{12,15,18})。コマンドt/@eは各サブリストを個別に合計します(ここでは{6,15,24})。また、コマンドe~t~2は9つの要素すべてを合計します(ここでは45)。

したがって、最初に3<(b=#~t~2)<6、1の合計数が4か5かをテストします。そうでなければ、で終了しFalseます。その場合、c=If[b>4,1-#,#]5ではなく4つの1を強制的に使用します。次に、列の合計t[c]、行の合計t/@c、主対角Tr@cの合計Tr@Reverse~c、および反対の対角の合計を計算し、これらの計算された合計のどのレベルでも出現しないこと~FreeQ~3を確認するために使用し3ます。

面白い副次的注意:このサイトのほとんどの外観とは異なり、ここでTrは1次元のリストを合計するために使用されていませんが、実際には2次元マトリックスのトレースを計算するために設計どおりに使用されています!



5

JavaScript(ES6)、101バイト

X = 1およびO = 0(MSB =左上のセル、LSB =右下のセル)を9ビットのバイナリマスクとして入力します。

n=>[7,56,73,84,146,273,292,448,o=x=0].map((m,i)=>(c-=n>>i&1,m&n^m?m&n||o++:m&&x++),c=4)&&!(c|x&&~c|o)

テストケース


(多少)簡単なビット単位のソリューションが必要だと思いました。ニースの仕事
ETHproductions

5

Python 2、 158 132 109 92 91 123バイト

def v(b):f=sum(b,());w={x[0]for x in b+zip(*b)+[f[::4],f[-3:1:-2]]if len(set(x))==1};return sum(map(`b`.count,w))==len(w)*5

入力は行のリスト/タプルで、それぞれが3タプルの文字列です。例:
[('X', 'O', 'X'), ('O', 'X', 'O'), ('X', 'O', 'X')]

@Maltysenの回答ごとに対角線を無視することで、いくつかのバイトを節約しました。これにより、次の式も短縮されました。

保存してくれて@vaultahに感謝 17 18バイト。

対角線のチェックが必要であることが判明し、上記の多くの節約がなくなりました。

ここで試してみてください。

説明

def v(b):
  f=sum(b,())
  w={x[0]for x in b+zip(*b)+[f[::4],f[-3:1:-2]]if len(set(x))==1}
  return sum(map(`b`.count,w))==len(w)*5

fスライス用の平坦化された入力です。
w勝利シーケンスを持つキャラクターが含まれています。
各勝者の出現回数をカウントします。w空の場合は0、1の場合は5になりlen(w)ます。両方に勝者がいる場合は10の合計は不可能です。勝者が5の場合、敗者は4を持っていることを意味します。勝ちのシーケンスがなければ、5を超えることはできません。


lambda b:len({x[0]for x in b+zip(*b)if len(set(x))==1})<2and set(map(b .count,'XO'))=={4,5}はいくつかのバイトを節約します。
vaultah

そして、...and{4,5}==set(map(b .count,'XO'))がもう1バイト節約していることに気付きました。
vaultah

これは、勝者が5点のプレーヤーであることを保証するものではないため、質問の最後の「無効」の例を誤ってみなしていると思います。
smls 16

@smlsそのとおりです。その状態を確認するには多くのバイトが必要であり、さらにゴルフをすることができます。
ジェイクコブ

5

R、88 82バイト

x=scan();`if`(sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F)

合計が15までの1〜9の3つの整数のすべての組み合わせは、以下に示す正方形の行/列/対角線です。

2 7 6
9 5 1
4 3 8

この関数は入力をブール値のベクトルとして受け取ります。Tは「X」、Fは「O」を表します。これは、ボードの平坦化された表現です。しかし、これらはインデックスが正方形の数字と同じになるように順序が変更されます(2,7,6,9,5,1,4,3,8)。この順序は、通常の方法でボードを平坦化し、c(6,1,8,7,5,3,2,9,4)でスライスすることで実現できます。したがって、この

X O X
O X O
X O X

次のように表されます。

c(T, F, T, F, T, F, T, F, T)[c(6,1,8,7,5,3,2,9,4)]

これは:

c(F, T, F, T, T, T, F, T, F)

この関数は最初に、正確に4つのマークを持つプレーヤーがいるかどうかを判断します。そうである場合、関数は15に追加するファクトの事実を使用して、そのプレイヤーに3行があるかどうかを判断します(プレイヤーが持っている場合、ボードは無効です)。

従来のようにフラット化されたボードを入力として使用する場合、コードは次のようになります。

f=function(x)ifelse(sum(x)%in%4:5,all(apply(combn(c(2,7,6,9,5,1,4,3,8)[which(x==(sum(x)<5))],3),2,sum)!=15),F)

私はこれが初めてなので、アドバイスをいただければ幸いです。


1
if()代わりに使用する場合は2バイトを節約します:f=function(x)if (sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F)。十分にテストされていません。バックティックはコードを台無しにしますが、そうbacktick if backtick(です。
ジョナサンキャロル

1
さらに良い。x=scan();場合(sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F)や入力など10。82バイト。
ジョナサンキャロル

3

JavaScriptの(ES6)、145の 139 131 127バイト

s=>!(q="XO"[s.split`O`.length-5])|![...s].some((c,i)=>c==q&!/(.)(\1|..(\1|.(\1|.\1.).)..)\1/.test(s.slice(0,i)+0+s.slice(i+1)))

など、スペースで区切られた文字列として入力し"XOX OXO XOX"ます。1無効なボード、0有効なボードの出力。これは明らかに、少なくともJavaScriptを使用した場合の最良の手法ではありません...

これは基本的に、次の両方が成り立つかどうかをチェックします。

  • 正確に4または5がありO、かつ
  • 削除されたときに未決定のゲームを作成する5つのインスタンスの少なくとも1つがあります。

正規表現は、ゲームが決定されたかどうかを確認することです。0(行)、2(右対角線)、3(列)、または4(左対角線)の各ペアを区切る1文字の長さ3のランがある場合、ボードと一致します。

テストスニペット


2

ルビー、104 99 91バイト

->x{[7,56,448,292,146,73,84,273].none?{|y|b=x.to_i 2;((a=x.count'1')==4?b:a==5?~b:7)&y==y}}

入力形式:ボードを表す9つのシンボル(0と1)のバイナリ文字列101010101。たとえば、最初のテストケースはです。最初にそれを2進数に変換し、popcountが4または5であるかどうかを確認します。5である場合、常に4になります。

TL; DR:マークが4つあるプレイヤーが勝った場合はfalseを返し、そうでない場合はtrueを返します。

コメントしてくれたジョーダンに感謝します。

別のバイトを節約するUTF-8文字列を再現できません。


あなたは置き換えることができ.select{...}[0].find{...}
ヨルダン

そして、数値の配列を置き換えることでもう1バイト節約できます"8ǀĤITđ".unpack("U*")(翻訳中に何かが失われる場合、文字列はpack("U*")元の配列を呼び出した結果です;それは12バイトです)。
ヨルダン

any?代わりにnone?、出力を反転させてバイト全体を保存できますか?
アレクシスアンデルセン

試してみましたか?なしの代わりに?しかし、私は必要です!出力を反転します。
GB

1

Perlの6103の 99バイト

{my \c=%(.flat.Bag.invert)<5>;?all c,|(.[0]===c if [eq] $_ for |.flat[<0 4 8>,<2 4 6>],|$_,|.&zip)}

のようなリストのリストを受け入れ(('X','O','X'), ('O','X','O'), ('X','O','X'))、Boolを返すラムダ。

それはこのように動作します:

  1. どのマークが5回表示されるかを確認し、に保存しcます。(マークが正確に5回表示されない場合、これには偽の値が含まれます)
  2. すべての対角線、行、および列を反復処理し、「勝った」もの(つまり、3文字すべてが等しいもの)を除外します。
  3. cが真であるかどうかを確認し各勝ちのラインはタイプcです。

1

PHP、125バイト

for($p=$n=$argv[1];$p;$p/=2)$i+=$p&1;foreach([7,56,448,73,146,292,273,84]as$m)$n&$m^$m?$n&$m||$o++:$x++;echo!$x|!$o&&2>$i^=4;

私はArnauldと同じ考えを持っていました:ボードは、4または5ビットのいずれかが設定されていて、どちらXOまたは両方にストリークがある場合に有効です(両方ではありません)。

フィールドから入力を生成するには、Xwith 1およびOwith 0で置き換え、行を結合し、バイナリを10進数に変換し、コマンドライン引数として指定します。

1有効なものを印刷します。無効な場合は空の出力。で実行し-rます。

壊す

// count set bits
for($p=$n=$argv[1];$p;$p/=2)$i+=$p&1;
    /* ($p/=2 takes longer than $p>>=1, but eventually
       $p will come close enough to 0 for the loop to finish */
// count streaks for X and O
foreach([7,56,448,73,146,292,273,84]as$m)
    $n&$m^$m            // ($n masked with streak)!=streak <=> no streak for X
        ?$n&$m||$o++    // true: O has a streak if ($n masked with streak) is empty
        :$x++;          // false: X has a streak
echo!$x|!$o&&2>$i^=4;   // valid if not both have a streak
                        // AND $i is 4 or 5 (toggle 4 -> result 0 or 1)

1

Swift、178バイト

func t(i:String)->Bool{let r=i.characters.filter({$0=="X"}).count;let g=i.characters.split(separator:"\n").map(String.init).contains;return(r==5||r==4)&&(!g("XXX") && !g("OOO"))}

0

ES6(Javacript)、 130138、117バイト

編集:

  • @Neilからのすばらしいアドバイスのおかげで21バイトオフになりました!
  • 初期バージョンにはバグが発生しやすく、現在は+8バイトのコストで修正する必要があります。(指摘してくれてありがとう@ETHproductions)

非常に簡単なアプローチ。おそらくもう少しゴルフすることができます。

9つの個別の引数、1esと0esとして入力を受け入れます

  • 1X
  • 0O

引数:1-3-最初の行、4-6-2番目の行、7-9-3番目の行。

ゴルフ

(a,b,c,d,e,f,g,h,j)=>![a+b+c,d+e+f,g+h+j,a+d+g,b+e+h,c+f+j,a+e+j,g+e+c,7].some(x=>x=="7777307777"[a+b+c+d+e+f+g+h+j])

インタラクティブな「テストベッド」

var a=b=c=d=e=f=g=h=j=0;

T=(a,b,c,d,e,f,g,h,j)=>![a+b+c,d+e+f,g+h+j,a+d+g,b+e+h,c+f+j,a+e+j,g+e+c,7].some(x=>x=="7777307777"[a+b+c+d+e+f+g+h+j]);

function test() {
  if(T(a,b,c,d,e,f,g,h,j)) {
     grid.style.backgroundColor='green';
     msg.innerHTML="GOOD"
  } else {
     grid.style.backgroundColor='red';
     msg.innerHTML="BAD"
  }
}
<table id=grid style="background: red">
<thead>
  <tr>
     <td id=msg align="center" colspan="3">BAD</td>
    </tr>
  </thead>
  <tr>
      <td><input type="checkbox" onchange="a=this.checked*1;test();" id="ca"/></td>
      <td><input type="checkbox" onchange="b=this.checked*1;test();" id="cb"/></td>
      <td><input type="checkbox" onchange="c=this.checked*1;test();" id="cc"/></td>
    </tr>
    <tr>
      <td><input type="checkbox" onchange="d=this.checked*1;test();" id="cd"/></td>
      <td><input type="checkbox" onchange="e=this.checked*1;test();" id="ce"/></td>
      <td><input type="checkbox" onchange="f=this.checked*1;test();" id="cf"/></td>
    </tr>
    <tr>
      <td><input type="checkbox" onchange="g=this.checked*1;test();" id="cg"/></td>
      <td><input type="checkbox" onchange="h=this.checked*1;test();" id="ch"/></td>
      <td><input type="checkbox" onchange="j=this.checked*1;test();" id="cj"/></td>
    </tr>
 </table>


私は間違っているかもしれませんが、これは勝者がいるかどうかを確認するだけのようです。有効なボードには勝者がいません。たとえば、[1,0,1,1,0,1,0,1,0]XOX XOX OXO)。
ETHproductions 16

うん、ゴルフ中に否定を失った。反対側が勝者ではないことを確認することになっています。今すぐ修正する必要があります。どうも !
ツェッペリン

(私は最新の編集の前にコメントを始めました)あなたはa)a+b+c+d+e+f+g+H+i代わりに書くことができますかF.reduce((r,c)=>r+=c*1)(その時点であなたは必要ありませんF)b)書く.includes(C)(そしてインラインCの値に進みます)?
ニール

@Neil、これはおそらく機能するでしょう。明日試してみます。どうも !
ツェッペリン

されてOOO XXX OXO失敗しますか?
イスマエルミゲル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.