import re
M=re.match
x='X';o='O'
R=lambda b,z=[6,3,0,7,4,1,8,5,2]:''.join(b[z[i]]for i in range(9))
p='XXX......|...XXX...|......XXX|X...X...X';q=p.replace(x,o)
def e(b):c=b.count;d=c(x)-c(o);w=M(p,b)or M(p,R(b));v=M(q,b)or M(q,R(b));return 0 if d not in[0,1]else 0 if w and v else(x if d==1 else 0)if w else(o if d==0 else 0)if v else'.'if'.'in b else'/'
h=set()
for n in range(3**9):
b=reduce(lambda a,v:('.XO'[a[1]%3]+a[0],a[1]/3),range(9),('',n))[0]
if b not in h:
u=e(b)
if u:print'%s\n%s\n%s %s\n'%(b[:3],b[3:6],b[6:],u)
h.update(reduce(lambda a,v:a+[R(a[-2]),R(a[-1])],range(3),[b,R(b,[2,1,0,5,4,3,8,7,6])]))
オンラインでお試しください!
おそらく、このアプローチでは、ちょっとしたゴルフが可能です。しかし、多くはありません。
編集:Thxからovsへ、28バイトの増加を指摘した。アルテミスファウルの 3人
ゴルフではないコード
ここでの基本的な考え方は、3 ^ 9 = 19683の可能なボードエンコーディングのそれぞれをブルートフォースにします。エントリが重複しないように、すでに調査済みのボードの共役(回転と反射)を追跡します。少なくとも、有効なボードには、XとOの数が等しいか、XがOよりも1つ多い必要があります。Xの勝利とOの勝利の両方を持つことはできません。加えて、いくつかの厄介な制約。
import re
from collections import Counter
FLIP_XFRM = [2,1,0,5,4,3,8,7,6]
ROT_XFRM = [6,3,0,7,4,1,8,5,2]
def xfrm(b, xf):
return ''.join(b[xf[i]] for i in range(9))
def flipIt(b):
return xfrm(b,FLIP_XFRM)
def rotIt(b):
return xfrm(b,ROT_XFRM)
def conjugates(b):
conj = [b, flipIt(b)]
for i in range(3):
conj += [rotIt(conj[-2]), rotIt(conj[-1])]
return conj
def tttToB(n):
b = ''
for i in range(9):
b = '.XO'[n %3]+b
n /= 3
return b
def printBoard(b,outcome='.'):
print '%s\n%s\n%s %s\n' % (b[:3],b[3:6],b[6:],outcome)
def evalBoard(b):
c = Counter(b)
if c['X']-c['O'] not in [0,1]:
return False
p1 = 'XXX......|...XXX...|......XXX|X...X...X'
p2 = p1.replace('X','O')
br = rotIt(b)
w1 = re.match(p1,b) or re.match(p1,br)
w2 = re.match(p2,b) or re.match(p2,br)
if w1 and w2:
return False
if w1:
return 'X' if c['X']==c['O']+1 else False
if w2:
return 'O' if c['X']==c['O'] else False
if '.' in b:
return '.'
else:
return '/'
def main():
history = set()
for m in range(3**9):
b = tttToB(m)
if b not in history:
outcome = evalBoard(b)
if outcome:
printBoard(b,outcome)
history.update(conjugates(b))
main()