Created
January 15, 2014 01:07
-
-
Save dfkoh/8429006 to your computer and use it in GitHub Desktop.
Code golfed version of Go player with comments. See http://codegolf.stackexchange.com/questions/17505/make-a-move-on-a-go-board
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
# M=int(next(s))+1 | |
# j=Z=M*M-M | |
# S=s.read(Z) | |
# P=0 | |
# b=[0]*3 | |
# I need N+1 more than N | |
N = int(sys.stdin.readline()) | |
M = N+1 | |
# Each row has N+1 characters because of newline | |
Z = BOARD_LENGTH = N * (N+1) | |
# We'll count down from the index the first time | |
j = index = BOARD_LENGTH | |
S = BOARD_STRING = sys.stdin.read(BOARD_LENGTH) | |
P = PERIMETER_MASK = 0 | |
b = board = [0,0,0] | |
# while j>0:j-=1+(j%M<1);b[int(S[j])]|=1<<j;P|=1<<j | |
while index > 0: | |
index -= 1 | |
# Skip the newline at the end of each row | |
if index % M == M-1: | |
continue | |
color = BOARD_STRING[index] | |
# Each board is a bitmask represnting an NxN+1 rectangle with the following | |
# format (e.g. for N=4). The x's represent bits that are set if the board | |
# position is that color. The 0s on the right are a buffer so the | |
# 'get_neighbors' method below doesn't wrap around the board when shifting. | |
# | |
# 01234 | |
# 0 xxxx0 | |
# 1 xxxx0 | |
# 2 xxxx0 | |
# 3 xxxx0 | |
# | |
board[int(color)] |= 1 << index | |
PERIMETER_MASK |= 1 << index | |
# The get_neighbors method takes a set of pieces on the board, and gets the set | |
# of locations that neighbor those pieces. It does this by shifting the input | |
# left, right, down and up and ORing the result together | |
# | |
# It also removes any input positions from the output, as well as any positions | |
# off the board | |
# | |
# N=lambda x:(x<<1|x>>1|x<<M|x>>M)&P&~x | |
def get_neighbors(pieces): | |
shifted = pieces<<1 | pieces>>1 | pieces<<M | pieces>>M | |
# Remove input positions from output | |
shifted &= ~pieces | |
# Remove off-board positions | |
shifted &= PERIMETER_MASK | |
return shifted | |
# The get_chain method takes a location and the pieces of a color, and finds | |
# all connected chains of that color by recursively adding all friendly | |
# neighbors | |
# | |
# def h(a,b):t=a|N(a)&b;return h(t,b)if t!=a else a | |
def get_chain(start_pieces, color_pieces): | |
neighbors = get_neighbors(start_pieces) | |
friendly_neighbors = neighbors & color_pieces | |
new_pieces = start_pieces | friendly_neighbors | |
# We're done when we didn't add anything new | |
if new_pieces == start_pieces: | |
return start_pieces | |
else: | |
return get_chain(new_pieces, color_pieces) | |
# c,r,m=map(int,next(s).split()) | |
column, row, my_color = map(int, next(sys.stdin).split()) | |
# o=m%2+1 | |
if my_color == 1: opponent = 2 | |
elif my_color == 2: opponent = 1 | |
# p=1<<M*r+c | |
piece = 1 << ((M * row) + column) | |
# Add new piece to board | |
# | |
# b[m]|=p | |
board[my_color] |= piece | |
# Remove captured opponent pieces | |
# | |
# for n in(p<<1,p>>1,p<<M,p>>M): | |
# e=h(n&P,b[o]) | |
# if~b[m]&N(e)<1<=n&b[o]:b[o]&=~e | |
for neighbor in (piece<<1, piece>>1, piece<<M, piece>>M): | |
# if the piece belongs to the opponent... | |
if neighbor & board[opponent]: | |
enemy_chain = get_chain(neighbor & PERIMETER_MASK, board[opponent]) | |
# Check if all of this chain's neighbors are my pieces | |
if get_neighbors(enemy_chain) & ~board[my_color] == 0: | |
# If so, remove them from the board | |
board[opponent] &= ~enemy_chain | |
#_,B,W=b | |
EMPTY, BLACK, WHITE = board | |
# Check that the spot we played was empty, and that we didn't commit suicide | |
# | |
# g=~b[o]&N(h(p,b[m]))>=1>~_&p | |
# print(+g) | |
my_chain = get_chain(piece, board[my_color]) | |
suicide = get_neighbors(my_chain) & ~board[opponent] == 0 | |
g = good_move = piece & EMPTY and not suicide | |
print(int(good_move)) | |
# Print out board | |
# | |
# q='' | |
# while j<Z: | |
# r=1<<j | |
# if g*j%M>M-2:print(q);q='' | |
# else:q+='012E'[(r&B>0)+(r&W>0)*2] | |
# j+=1 | |
if good_move: | |
q = row_output = '' | |
# Remember index = 0 from earlier loop | |
while index < BOARD_LENGTH: | |
if index % M == M-1: | |
# Print at end of each row | |
print(row_output) | |
row_output = '' | |
else: | |
r = pos = 1<<index | |
if pos & BLACK: | |
row_output += '1' | |
elif pos & WHITE: | |
row_output += '2' | |
else: | |
row_output += '0' | |
index += 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
s=sys.stdin | |
M=int(next(s))+1 | |
j=Z=M*M-M | |
S=s.read(Z) | |
P=0 | |
b=[0]*3 | |
while j>0:j-=1+(j%M<1);b[int(S[j])]|=1<<j;P|=1<<j | |
N=lambda x:(x<<1|x>>1|x<<M|x>>M)&P&~x | |
def h(a,b):t=a|N(a)&b;return h(t,b)if t!=a else a | |
c,r,m=map(int,next(s).split()) | |
o=m%2+1 | |
p=1<<M*r+c | |
b[m]|=p | |
for n in(p<<1,p>>1,p<<M,p>>M): | |
e=h(n&P,b[o]) | |
if~b[m]&N(e)<1<=n&b[o]:b[o]&=~e | |
_,B,W=b | |
g=~b[o]&N(h(p,b[m]))>=1>~_&p | |
print(+g) | |
q='' | |
while j<Z: | |
r=1<<j | |
if g*j%M>M-2:print(q);q='' | |
else:q+='012E'[(r&B>0)+(r&W>0)*2] | |
j+=1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I had independently golfed it down from 504 to 473, feel free to merge the improvements: