In [28]:
import collections
SIZE = 11
PM = collections.namedtuple('PM', ['name', 'prime', 'row', 'drow', 'col', 'dcol', 'dir', 'ddir'])
DIRECTION_MAP = {
'N': 0,
'NE': 1,
'E': 2,
'SE': 3,
'S': 4,
'SW': 5,
'W': 6,
'NW': 7,
}
DEGREE_STR_MAP = {
'90deg CCW': 8 - 2,
'45deg CCW': 8 - 1,
'no change': 0,
'45deg CW': 1,
'90deg CW': 2,
'135deg CW': 3,
}
DEGREE_DR_DC_MAP = {
0: (0, -1), # N.
1: (1, -1),
2: (1, 0), # E.
3: (1, 1),
4: (0, 1), # S.
5: (-1, 1),
6: (-1, 0), # W.
7: (-1, -1), # NW.
}
def parse_data(data):
result = {}
lines = data.split('\n')
for line in lines[1:]:
properties = line.split('\t')
for i, v in enumerate(properties):
try:
properties[i] = int(v)
except:
pass
properties[2] -= 1
properties[4] -= 1
properties[-2] = DIRECTION_MAP[properties[-2]]
result[properties[0]] = PM(*properties)
return result
pms = parse_data("""
PM Prime Start Row Row Δ Start Col Col Δ Start Dir "Dir Δ [45 deg CW]"
TRUDEAU 23 2 7 9 4 W 1
CAMPBELL 19 5 6 3 8 N 3
TURNER 17 7 7 9 5 S 7
DIEFENBAKER 13 8 8 4 4 E 2
BENNETT 11 5 2 6 7 NW 6
LAURIER 7 8 8 6 1 NW 3
BOWELL 5 6 1 1 9 NW 0
ABBOTT 3 2 9 2 2 SE 6
MACKENZIE 2 2 8 3 9 S 1
""".strip())
"""
"""
Out[28]:
In [29]:
pms
Out[29]:
In [30]:
PM = collections.namedtuple('PM', ['name', 'prime', 'row', 'drow', 'col', 'dcol', 'dir', 'ddir'])
def wrap(n):
return (n + SIZE) % SIZE
def pm_coord_iter(pm, n):
n %= pm.prime
row = (pm.row + n * pm.drow) % SIZE
col = (pm.col + n * pm.dcol) % SIZE
dir = (pm.dir + n * pm.ddir) % len(DIRECTION_MAP)
dcol, drow = DEGREE_DR_DC_MAP[dir]
for i, c in enumerate(pm.name):
yield (c, wrap(row + drow * i), wrap(col + dcol * i))
In [31]:
def score_n(n, pms):
scored = collections.defaultdict(dict)
visited = set()
for pm in pms.values():
for c, row, col in pm_coord_iter(pm, n):
visited.add((row, col))
return len(visited)
def score_valid(n, pms):
scored = collections.defaultdict(dict)
grid = {}
for pm in pms.values():
for c, row, col in pm_coord_iter(pm, n):
key = (row, col)
if key not in grid:
grid[key] = c
elif grid[key] != c:
return False
return len(grid)
In [33]:
"""
best 32 748448
worst 65 2854719
best 31 3045743
best 30 6204717
best 28 23607102
worst 66 48000127
"""
best = float('inf')
best_i = -1
worst = float('-inf')
worst_i = -1
threshold = 2
for i in range(99999999 + 1):
score = score_valid(i, pms)
if i > threshold:
threshold *= 2
print(i)
if score is False:
continue
print(i, score)
# if score < best:
# best = score
# best_i = i
# print('best', best, best_i)
# if score >= worst:
# worst = score
# worst_i = i
# print('worst', worst, worst_i)
In [118]:
list(pm_coord_iter(pms['MACKENZIE'], 1))
Out[118]:
In [ ]:
# DIEFENBAKER
# TRUDEAU
In [ ]: