Python 2.7
これは、他の回答者にスケルトン/インスピレーションを与えるために提供している進行中の提出物です。可能なすべての勝利ラインをリストし、そのヒューリスティックを適用して、そのラインの価値に応じてそのラインをスコアリングします。現在、ヒューリスティックは空白です(極秘の仕組み)。また、WinおよびClashのエラー処理も追加しました。
問題に関する注意
勝利ラインはいくつありますか?1次元の場合を考えます。2つの頂点、1つのエッジ、1つのラインがあります。2次元では、2つの線で結合された4つの頂点と、2 * nの線で結合された4つのエッジがあります。3次元では、4つの線で結合された8つの頂点、6 * nの線で結合された12のエッジ、および線で結合された6つの面があり3*n^2
ます。
一般に、頂点を0ファセット、エッジを1ファセットなどN(i)
と呼びます。次に、iファセットd
の数、次元の数、n
辺の長さを示します。勝った行の数は0.5*sum(N(i)*n^i,i=0..d-1)
です。
ウィキペディアごとにN(i)=2^(d-i)*d!/(i!*(n-1)!)
、最終的な式は次のとおりです。
sum(2^(d-i-1) n^i d! / (i! * (n-i)!),i=0..d-1)
どのwolfram | alphaはあまり好きではありません。これは非常に速く非常に大きくなるため、プログラムでd> 8のランタイムを管理できるとは考えていません。
いくつかの結果(フォーマットについては申し訳ありません:
d\n 0 1 2 3 4 5 6 7 8 9
0 1 1 1 1 1 1 1 1 1 1
1 2 4 6 8 10 12 14 16 18 20
2 4 11 26 47 74 107 146 191 242 299
3 8 40 120 272 520 888 1400 2080 2952 4040
4 16 117 492 1437 3372 6837 12492 21117 33612 50997
5 32 364 2016 7448 21280 51012 107744 206896 368928 620060
6 64 1093 8128 37969 131776 372709 908608 1979713 3951424 7352101
7 128 3280 32640 192032 807040 2687088 7548800 18640960 41611392 85656080
8 256 9834 130809 966714 4907769 19200234 62070009 173533434 432891129 985263594
I / O
現時点では、入力は次のように入力する必要がありますtictactoe.py <ret> n,d <ret> move;move <ret>
。-複数の行に注意してください。;
。
(x_1,x_2,x_3...)
たとえば、出力は次のようになります。
tictactoe.py <ret> 6,5 <ret> <ret>
=> 0, 0, 0, 0, 0
tictactoe.py <ret> 6,5 <ret> 0,0,0,0,0;0,0,0,0,5 <ret>
=> 0, 0, 0, 5, 0
# Notes on terminology:
#
# - A hypercube is the region [0,n]^d
# - An i-facet is an i-dimensional facet of a hypercube,
# which is to say, a 0-facet is a vertex, a 1-facet an
# edge, a 2-facet a face, and so on.
# - Any tuple {0,n}^i is a vertex of an i-hypercube
# which is why I've used vertex to describe such
# tuples
# - A winning line is a set of n coordinates which joins
# two opposite i-facets
# - i-facets are opposite if they differ in every co-
# ordinate which defines them
#
# Test Data:
#
import numpy
import itertools
def removeDuplicates(seq):
noDupes = []
[noDupes.append(i) for i in seq if not noDupes.count(i)]
return noDupes
def listPairedVertices (i,n):
"""
listPairedVertices returns a list L of elements of {0,n}^i which has the
property that for every l in L, there does not exist l' such that
l+l' = {n}^i.
"""
vertices = numpy.array([[b*(n-1) for b in a] for a in [
list(map(int,list(numpy.binary_repr(x,i)))) for x in range(2**i)
]])
result = []
while len(vertices)>1:
for j in range(len(vertices)):
if numpy.all(vertices[j] + vertices[0] == [n-1]*i):
result.append(vertices[0])
vertices=numpy.delete(vertices,[0,j],axis=0)
break
return result
def listSequences (d,l):
"""
listSequences returns the subset of {0,1}^d having precisely n 1s.
"""
return numpy.array([
r for r in itertools.product([0,1],repeat=d) if sum(r)==l
])
def listPaddedConstants (s,n):
"""
listPaddedConstants takes a sequence in {0,1}^d and returns a number in
{0..n}^sum(s) padded by s
"""
result = numpy.zeros([n**sum(s),len(s)],dtype=numpy.int)
for i,x in enumerate([list(z) for z in
itertools.product(range(n),repeat=sum(s))]):
for j in range(len(s)):
if s[j]: result[i][j] = x.pop()
return result
def listWinningVectorsForDimension(d,i,n):
"""
List the winning lines joining opposite i-facets of the hypercube.
An i-facet is defined by taking a vertex v and a sequence s, then forming
a co-ordinate C by padding v with zeroes in the positions indicated by s.
If we consider s = s_0.e_0 + s_1+e_1... where the e_j are the canonical
basis for R^d, then the formula of the i-facet is
C+x_0.s_0.e_0+x_1.s_1.e_1...
for all vectors x = (x_0,x_1...) in R^n
We know that winning lines only start at integral positions, and that the
value of a will only be needed when s_j is nonempty, so the start point S
of a winning line is in fact determined by:
+ vertex v in {0,n}^(d-i), padded by s
+ a in R^i, padded by the complement of s, s'
Having performed the following operations, the co-ordinates of the winning
lines are abs(S-k*s') for k in [0..n-1]
"""
vertices = listPairedVertices(d-i,n)
sequences = listSequences(d,i)
result = []
for s in sequences:
for v in vertices:
C = [0]*d
j = 0
for index in range(d):
if s[index]: C[index] = 0
else:
C[index] = v[j]
j+=1
result += [
[numpy.absolute(S-k*(numpy.absolute(s-1))) for k in range(n)]
for S in [C+a for a in listPaddedConstants(s,n)]
]
return result
def AllWinningLines (d,n):
"""
has the structure [[x_1,x_2,x_3],[y_1,y_2,y_3]] where each l_k is a
length-d co-ordinate
"""
result = []
for i in range(d):
result += listWinningVectorsForDimension(d,i,n)
return result
def movesAlreadyMade ():
"""
Returns a list of co-ordinates of moves already made read from STDIN
"""
parameters = raw_input()
moves = raw_input()
parameters = list(map(int,parameters.split(',')))
moves = [map(int,a.split(',')) for a in moves.split(';')] \
if moves != '' else []
return {'n':parameters[0], 'd':parameters[1], 'moves':moves}
def scoreLine (moves, line, scores, n):
"""
Gives each line a score based on whatever logic I choose
"""
myMoves = moves[0::2]
theirMoves = moves[1::2]
if len(moves)%2: myMoves, theirMoves = theirMoves, myMoves
lineHasMyMove = 0
lineHasTheirMove = 0
score = 0
for coord in line:
if coord.tolist() in myMoves:
lineHasMyMove += 1
if coord.tolist() in theirMoves: raise Exception('Move clash')
elif coord.tolist() in theirMoves: lineHasTheirMove += 1
if lineHasMyMove == len(line):
raise Exception('I have won')
elif lineHasTheirMove == len(line):
raise Exception('They have won')
elif lineHasMyMove and lineHasTheirMove:
pass
elif lineHasTheirMove == len(line)-1:
score = n**lineHasTheirMove
else:
score = n**lineHasMyMove
for coord in line:
if coord.tolist() not in moves:
scores[tuple(coord)]+=score
def main():
"""
Throw it all together
"""
data = movesAlreadyMade()
dimension = data['d']
length = data['n']
lines = AllWinningLines(dimension, length)
scores = numpy.zeros([length]*dimension, dtype=numpy.int)
try: [scoreLine(data['moves'], line, scores, length) for line in lines]
except Exception as E:
print 'ERROR: ' + E.args[0]
return
print ','.join(map(
str,numpy.unravel_index(numpy.argmax(scores),scores.shape)
))
if __name__ == "__main__": main()
編集:I / Oにロジックを追加。これでマークする準備ができたと思う
このコメントは最初はプレースホルダーであり、私が削除および削除解除したことに注意してください。