Skip to content

Instantly share code, notes, and snippets.

@dfkoh
Created January 15, 2014 01:07
Show Gist options
  • Save dfkoh/8429006 to your computer and use it in GitHub Desktop.
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
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
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
@aditsu
Copy link

aditsu commented Jan 15, 2014

I had independently golfed it down from 504 to 473, feel free to merge the improvements:

import sys
s=sys.stdin
M=int(next(s))+1
j=Z=M*M-M
B=s.read(Z)
P=0
b=[0]*3
while j>0:j-=1+(j%M<1);b[int(B[j])]|=1<<j;P|=1<<j
N=lambda x:(x<<1|x>>1|x<<M|x>>M)&P&~x
h=lambda a,b:(N(a)&b&~a and h(a|N(a)&b,b)-a)+a
c,r,t=map(int,next(s).split())
o=3-t
p=1<<M*r+c
b[t]|=p
for n in(p<<1,p>>1,p<<M,p>>M):e=h(n&P&b[o],b[o]);b[o]^=e*(~b[t]&N(e)<1)
g=p&b[0]and~b[o]&N(h(p,b[t]))>0
print(g*1)
q=''
while j<Z:
 if g*j%M>M-2:print(q);q=''
 else:q+=str((1<<j&b[1]>0)+(1<<j&b[2]>0)*2)
 j+=1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment