import numpy as np def solution(g): #print_grid(g) grid = np.array(g) #print grid height, width = grid.shape #print height, width memo = {} prev_cases = {} for i in range(2**(height+1)): prev_cases[i] = 1 memo[i] = {} for j in range(2**(height+1)): memo[i][j] = calculate_c_column(i, j, height) #print memo #print prev_cases for column in range(width): cases = {} for i in range(2**(height+1)): cases[i] = 0 #print grid[:,column], list_to_int(grid[:,column]) for i in range(2**(height+1)): if prev_cases[i] == 0: continue for j in range(2**(height+1)): if memo[i][j] == list_to_int(grid[:,column]): cases[j] += prev_cases[i] #print cases prev_cases = cases return sum(prev_cases.values()) def print_grid(g): for row in g: line = "" for elem in row: if elem: line+="O" else: line+="." print line def calculate_c_column(i, j, length): mask = 2**(length)-1 multi_ones = ((i&j)|((i&j)>>1)) & mask odd_ones = ((i^j)^((i^j)>>1)) & mask single_one = (~multi_ones & odd_ones) & mask #print ' '.join(('{:0'+str(length)+'b}').format(k) for k in [i, j]), ' '.join(('{:0'+str(length-1)+'b}').format(k) for k in [multi_ones, odd_ones, single_one]) return single_one #l=3 #memo = {} #for i in range(2**(l-1)): # memo[i] = 0 #for i in range(2**l): # for j in range(2**l): # t = calculate_c_column(i, j, l) # memo[t] += 1 #print memo #exit(0) def list_to_int(l): value = 0 for v in l: value |= v value <<= 1 return value >> 1 tests = [ ([[True, True, False, True, False, True, False, True, True, False], [True, True, False, False, False, False, True, True, True, False], [True, True, False, False, False, False, False, False, False, True], [False, True, False, False, False, False, True, True, False, False]], 11567), ([[True, False, True], [False, True, False], [True, False, True]], 4), ([[True, False, True, False, False, True, True, True], [True, False, True, False, False, False, True, False], [True, True, True, False, False, False, True, False], [True, False, True, False, False, False, True, False], [True, False, True, False, False, True, True, True]] ,254), ([[True]], 4), ([[False]], 12), ([[True, True]], 6), ([[True, False]], 10), ([[False, True]], 10), ([[False, False]], 38), ] for (i, o) in tests: result = solution(i) print(i, result == o, result, o)