Skip to content

Instantly share code, notes, and snippets.

@enaeseth
Created March 16, 2012 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save enaeseth/2047821 to your computer and use it in GitHub Desktop.
Save enaeseth/2047821 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from itertools import product, repeat
import json
import sys
PLAYERS = ['X', 'O']
RUN_LENGTH = 4
def value_at(board, coordinate):
value = board
for dimension in coordinate:
value = value[dimension]
return value
def vector_add(v1, v2):
return map(lambda x1, x2: x1 + x2,
v1, v2)
def vector_scale(factor, vector):
return [factor * x for x in vector]
def is_run(board, start, step):
try:
player = value_at(board, start)
return all(map(lambda c: value_at(board, c) == player,
(vector_add(vector_scale(x, step),
start)
for x in range(1, RUN_LENGTH))))
except IndexError:
return False
def coordinates(arr):
return product(*[range(x) for x in arr])
def find_dimensions(arr):
if not isinstance(arr[0], list):
return [len(arr)]
else:
dimensions = [find_dimensions(x) for x in arr]
return ([len(arr)] + map(max, zip(*dimensions)))
def find_winner(board):
board_dimensions = find_dimensions(board)
# XXX this could stand to be a lot smarter; by going backwards and
# forwards, we test each candidate twice.
steps = [step for step in product(*repeat([-1, 0, 1],
len(board_dimensions)))
if any(step)] # filter out (0, 0, ..., 0)
for start in coordinates(board_dimensions):
for step in steps:
try:
if value_at(board, start) in PLAYERS and is_run(board, start, step):
return value_at(board, start)
except IndexError:
pass
if __name__ == '__main__':
board = json.loads(sys.stdin.read())
winner = find_winner(board)
if winner:
print "Winner: %s" % (winner,)
else:
print "No winner."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment