此井字棋牌有效吗?


48

挑战

给定任何格式的井字游戏板,请确定其是否有效。如果棋盘可以是井字游戏的结果,那么它是有效的。例如,此板有效:

XOX
氧代
XOX
相反,此板无效:

XXX
XXO
OOO

输入项

  • 完整的(9/9)井字游戏板(结果,而不是游戏)。

规则

  • 输入格式必须能够描述所有512种可能的输入板。如果不清楚/不清楚,则必须指定它以及创建说明。但是,您必须单独声明木板的标记。
  • 必须有两个可能的输出,一个用于有效性,一个用于无效。
  • 您可以假定板上没有空点。

测试用例

有效:

XOX
氧代
XOX

XOX
XOX
氧代

XOO
OX
OXX

氧代
XOX
氧代

无效:

XXX
XXX
XXX

OOO
OOO
OOO

XXX
OOO
XXX

OOO
OX
XXX

XXO
氧代
OX

一点帮助?

仅在以下两个条件成立的情况下,董事会才被认为是有效的(对此挑战):

  • 有5 X和4 O,或4 X和5O。例如,
    XXX
    氧代
    XXX
    被视为无效,因为有7个X和2个O。
  • 只有获得5分的玩家获胜,或者没有一个获胜。例如,
    XXX
    OOO
    OX
    被视为无效,因为Os的行或Xs的行将首先形成。两位玩家不能同时回合。

目前的获奖者是...

... ais523的果冻答案,惊人的26个字节!


2
也许还要添加一个测试用例,例如O O O X O X X O X,以表明同一播放器可能同时具有水平和垂直行。
smls

2
但是,您必须单独声明木板的标记。我不确定这部分内容。您能提供一个反例吗?
Arnauld

3
@Tim X有4个标记。
马丁·恩德

2
@Sparr“只有5分的玩家赢了,或者没有一个赢了。”
马丁·恩德

2
@Kevin(回复第一条评论),因为如果第二位玩家(获得4分的玩家)获胜,则不会完成9/9局。
Erik the Outgolfer '16

Answers:


11

果冻,26个字节

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

在线尝试!

输入格式有点不寻常;它是代表主板的字符串,但带有Windows换行符(回车后跟换行符)。例如,XXO\r\nOXO\r\nOOX。(实际上,两行之间的任何两个字符的填充字符串都可以,但是Windows换行符比其他选项更具防御性。)

基本思想是,我们寻找在输入中出现4次但在原始字符串中没有3个均匀间隔出现的字符。在3×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

换句话说,我们找到了在输入中恰好出现四次的字符列表,并制作了一个由每个字符的三个副本组成的列表。我们找到在原始字符串中均匀间隔的所有子序列的列表;如果我们从第一个中减去第二个,我们希望结果的长度为1(即玩家玩了四次,但没有获胜)。请注意,由于我们位于3×3网格上,并且每个方格都满了,所以两个玩家都不可能玩四次。在Jelly中,1是真实的,0是虚假的,因此我们无需执行任何特殊操作即可将结果列表转换为布尔值。(该µL是必需的,但是,因为否则的话都“XXX”“OOO”有可能truthy输出值,问题要求所有有效主板提供相同的输出。)


3
这是完全可读的。
pabrams,2013年

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的字符串01字符,并返回1有效,0无效。我们将字符排序。如果中间的三个字符现在相同,则该面板将无效,因为其中一个字符太多。否则,我们将原始板转换为二进制,如果0s大于1s ,则将位翻转。此时,如果0没有三行,那么该板就有效,因此我们只需通过一个位掩码数组测试所有八行。编辑:由于@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)不需要括号。
Ken YN

通过使用对称性来消除25个字节,并通过缩写24个最低的零位来消除另一个字节-必须有一种高尔夫球手的方法if b>255:b=511-b
肯·恩

找到了一种高尔夫球手的方法if
Ken 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和的正交线OOOXXX。方便地,Batch允许我们间接执行整数算术,因此我们不增加%%l而是取一些变量(尽管我们只对提到的三个变量感兴趣)。然后,我们需要测试要么X没有赢,有五个O秒,要么O没有赢,有四个O秒。


10

Mathematica,82 75字节

感谢Martin Ender节省了7个字节!

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

未命名函数,将3x3的1和0嵌套列表作为输入和输出Trueor False

使用该Total函数的一些方便灵活性(此处称为t):给定一个示例数组e = { {1,2,3} , {4,5,6} , {7,8,9} },该命令t[e]将三个向量求和(此处为yield {12,15,18});该命令t/@e分别对每个子列表求和(此处为yield {6,15,24});该命令e~t~2将所有九个元素相加(此处为yield 45)。

所以首先我们用检验3<(b=#~t~2)<61的总数是4还是5。如果不是,我们退出False。如果是这样,我们通常c=If[b>4,1-#,#]会强制使用四个1,而不是五个。然后,我们计算列总和t[c],行总和t/@c,主对角线总和以及对角线对角Tr@c总和Tr@Reverse~c,并~FreeQ~3用来检查3在这些计算出的总和中是否未出现任何水平。

有趣的旁注:与本网站上的大多数外观不同,此处Tr不是用来对一维列表求和,而实际上是按设计使用的—用于计算二维矩阵的轨迹!



5

JavaScript(ES6),101个字节

将输入作为9位二进制掩码,其中X = 1O = 0(MSB =左上方的单元格,LSB =右下方的单元格)。

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

输入是行的列表/元组,每行三元组的字符串,例如:
[('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;如果len(w)为1,则为5。当两个都有获胜顺序时,则为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 '16

我只是注意到...and{4,5}==set(map(b .count,'XO'))节省了一个字节。
vaultah '16

我认为这错误地认为问题中的最后一个“无效”示例是有效的,因为它不能确保获胜者是获得5分的玩家。
smls 2016年

@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)

从1到9的三个整数(总计为15)的所有组合都是下面所示正方形的行/列/对角线。

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)

该功能首先确定是否有一个球员拥有恰好四个标记。如果是这样,则该功能使用加到15的事实来确定该玩家是否有三人行(如果玩家这样做,则棋盘无效)。

如果您想将常规拼合的板作为输入,则代码应如下所示:

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
如果使用,则节省2个字节if()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();if (sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F)和输入as 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个实例中的一个实例被删除后会产生不确定的游戏。

正则表达式用于检查游戏是否已确定。它与木板匹配,前提是每个字符的长度为3的任何游程都以0(行),2(右下对角线),3(列)或4(左下对角线)字符分开。

测试片段


2

Ruby,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。首先将其转换为二进制数,检查popcount是4还是5,如果它是5则将数字取反,所以我们总是有4。检查其中三个是否对齐(遮盖水平,垂直,对角线)。

TL; DR:如果赢得4分的玩家赢得,则返回false,否则返回true。

感谢约旦的评论,

我无法复制将保存另一个字节的UTF-8字符串。


您可以替换.select{...}[0].find{...}
约旦

并且您可以通过将数字数组替换为来节省一个字节"8ǀĤITđ".unpack("U*")(以防万一在翻译中丢失内容,字符串是调用pack("U*")原始数组的结果;它是12个字节)。
约旦

您可以使用any?代替none?,翻转输出并保存整个字节吗?
亚历克西斯·安德森

我尝试过一个吗?而不是没有?但是那我需要一个!翻转输出。
GB

1

Perl 6的103个 99字节

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

一个lambda,它接受列表列表,例如(('X','O','X'), ('O','X','O'), ('X','O','X')),并返回Bool。

它是这样的:

  1. 检查哪个标记正好出现5次,并将其存储在中c(如果没有标记出现恰好5次,则该值将为假值)
  2. 遍历所有对角线,行和列,并过滤掉“获胜”的那些(即,三个字母都相等的那些)
  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位并且一个X或一个O或没有人有连胜(但不能同时出现),则该板有效。

为了产生从输入字段替代X1O0,联接线和二进制转换为十进制,提供作为命令行参数。

打印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

迅捷,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
  • 0代表O

参数:1-3-第一行,4-6-第二行,7-9-第三行。

打高尔夫球

(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 2016年

是的,打高尔夫球时我已经失去了否定性。应该检查对方是否不是赢家。现在应该修复。谢谢 !
zeppelin

(我在最近的编辑之前就开始评论了)您可以a)写a+b+c+d+e+f+g+H+i而不是F.reduce((r,c)=>r+=c*1)(此时不需要F)b)写.includes(C)(并继续inline C的值)吗?
尼尔

@Neil,这可能会起作用,我明天尝试一下。谢谢 !
齐柏林飞艇

OOO XXX OXO失败吗?
Ismael Miguel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.