Day 15 p1
parent
9eb1eb185d
commit
bb66a533eb
@ -0,0 +1,202 @@
|
|||||||
|
from pprint import pprint
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
m = list()
|
||||||
|
hitpoints = dict()
|
||||||
|
|
||||||
|
|
||||||
|
with open('input.txt', 'r') as f:
|
||||||
|
for raw_line in f.readlines():
|
||||||
|
line = list()
|
||||||
|
for field in raw_line.strip():
|
||||||
|
line.append(field)
|
||||||
|
m.append(line)
|
||||||
|
|
||||||
|
for x in range(len(m)):
|
||||||
|
for y in range(len(m[x])):
|
||||||
|
if m[x][y] in ['G', 'E']:
|
||||||
|
hitpoints[(x, y)] = 200
|
||||||
|
|
||||||
|
def get_patch(pos):
|
||||||
|
x, y = pos
|
||||||
|
if x < 0 or x >= len(m):
|
||||||
|
return None
|
||||||
|
if y < 0 or y >= len(m[x]):
|
||||||
|
return None
|
||||||
|
return m[x][y]
|
||||||
|
|
||||||
|
def neighbors(pos):
|
||||||
|
return [
|
||||||
|
(pos[0], pos[1] + 1),
|
||||||
|
(pos[0], pos[1] - 1),
|
||||||
|
(pos[0] + 1, pos[1]),
|
||||||
|
(pos[0] - 1, pos[1])
|
||||||
|
]
|
||||||
|
|
||||||
|
def valid_neighbors(pos):
|
||||||
|
return [x for x in neighbors(pos) if get_patch(x) == '.']
|
||||||
|
|
||||||
|
|
||||||
|
def flood(pos):
|
||||||
|
patches = set([pos])
|
||||||
|
flood_map = {
|
||||||
|
pos: 0
|
||||||
|
}
|
||||||
|
new = set(valid_neighbors(pos))
|
||||||
|
i = 1
|
||||||
|
while new:
|
||||||
|
patches.update(new)
|
||||||
|
new_new = set()
|
||||||
|
for p in new:
|
||||||
|
flood_map[p] = i
|
||||||
|
new_new.update(valid_neighbors(p))
|
||||||
|
new = new_new - patches
|
||||||
|
i += 1
|
||||||
|
return flood_map
|
||||||
|
|
||||||
|
def get_units():
|
||||||
|
"""unit is a tuple (pos, symbol)"""
|
||||||
|
units = list()
|
||||||
|
for x in range(len(m)):
|
||||||
|
for y in range(len(m[x])):
|
||||||
|
if m[x][y] in ['G', 'E']:
|
||||||
|
units.append(((x, y), m[x][y]))
|
||||||
|
return units
|
||||||
|
|
||||||
|
def get_closest_target(flood_map, targets):
|
||||||
|
reachable_targets = {pos: dist for pos, dist in flood_map.items() if pos in targets}
|
||||||
|
if len(reachable_targets) == 0:
|
||||||
|
return None
|
||||||
|
# print('Reachable targets:', reachable_targets)
|
||||||
|
min_range = min(reachable_targets.values())
|
||||||
|
closest = [pos for pos, dist in reachable_targets.items() if dist == min_range]
|
||||||
|
# print('Closest targets:', closest)
|
||||||
|
closest.sort()
|
||||||
|
return closest[0]
|
||||||
|
|
||||||
|
def get_enemies(unit):
|
||||||
|
return [e for e in get_units() if e[1] != unit[1]]
|
||||||
|
|
||||||
|
def get_targets(unit):
|
||||||
|
targets = set()
|
||||||
|
for e in get_enemies(unit):
|
||||||
|
targets.update(valid_neighbors(e[0]))
|
||||||
|
return targets
|
||||||
|
|
||||||
|
def get_enemies_in_range(unit):
|
||||||
|
x, y = unit[0]
|
||||||
|
enemies = get_enemies(unit)
|
||||||
|
neighbors = [
|
||||||
|
(x + 1, y),
|
||||||
|
(x - 1, y),
|
||||||
|
(x, y + 1),
|
||||||
|
(x, y - 1)
|
||||||
|
]
|
||||||
|
return [e for e in enemies if e[0] in neighbors]
|
||||||
|
|
||||||
|
def move(unit, target):
|
||||||
|
move_to = dict()
|
||||||
|
neighbors = valid_neighbors(unit[0])
|
||||||
|
# print('neighbors', neighbors)
|
||||||
|
for n in neighbors:
|
||||||
|
flood_map = flood(n)
|
||||||
|
# print(n, target, flood_map.get('target'))
|
||||||
|
if target in flood_map:
|
||||||
|
move_to[n] = flood_map[target]
|
||||||
|
# print(move_to)
|
||||||
|
min_range = min(move_to.values())
|
||||||
|
closest = [pos for pos, dist in move_to.items() if dist == min_range]
|
||||||
|
closest.sort()
|
||||||
|
|
||||||
|
x1, y1 = unit[0]
|
||||||
|
x2, y2 = closest[0]
|
||||||
|
m[x1][y1] = '.'
|
||||||
|
m[x2][y2] = unit[1]
|
||||||
|
|
||||||
|
htp = hitpoints[unit[0]]
|
||||||
|
del hitpoints[unit[0]]
|
||||||
|
hitpoints[closest[0]] = htp
|
||||||
|
|
||||||
|
return (closest[0])
|
||||||
|
|
||||||
|
def count_dwarfes():
|
||||||
|
c = 0
|
||||||
|
for line in m:
|
||||||
|
for sym in line:
|
||||||
|
if sym == 'E':
|
||||||
|
c += 1
|
||||||
|
return c
|
||||||
|
|
||||||
|
def count_goblins():
|
||||||
|
c = 0
|
||||||
|
for line in m:
|
||||||
|
for sym in line:
|
||||||
|
if sym == 'G':
|
||||||
|
c += 1
|
||||||
|
return c
|
||||||
|
|
||||||
|
def print_map():
|
||||||
|
print(' ', ''.join([ str(y // 10) for y, _ in enumerate(m[0]) ]))
|
||||||
|
print(' ', ''.join([ str(y % 10) for y, _ in enumerate(m[0]) ]))
|
||||||
|
for i, line in enumerate(m):
|
||||||
|
htp_list = [(pos, htp) for pos, htp in hitpoints.items() if pos[0] == i]
|
||||||
|
htp_list.sort()
|
||||||
|
print(str(i).ljust(2), ''.join(line), [h[1] for h in htp_list])
|
||||||
|
print(' ', ''.join([ str(y % 10) for y, _ in enumerate(m[0]) ]))
|
||||||
|
print(' ', ''.join([ str(y // 10) for y, _ in enumerate(m[0]) ]))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
i = 0
|
||||||
|
while 1:
|
||||||
|
print()
|
||||||
|
print(f'After {i} rounds:')
|
||||||
|
print_map()
|
||||||
|
units = get_units()
|
||||||
|
units.sort()
|
||||||
|
for u in units:
|
||||||
|
if get_patch(u[0]) != u[1]:
|
||||||
|
continue
|
||||||
|
if count_dwarfes() == 0 or count_goblins() == 0:
|
||||||
|
return i
|
||||||
|
# print(f'UNIT: {u[1]} at {u[0]}')
|
||||||
|
e = get_enemies_in_range(u)
|
||||||
|
if len(e) == 0:
|
||||||
|
# move
|
||||||
|
targets = get_targets(u)
|
||||||
|
closest = get_closest_target(flood(u[0]), targets)
|
||||||
|
if closest is None:
|
||||||
|
# print('do nothing')
|
||||||
|
continue
|
||||||
|
d = move(u, closest)
|
||||||
|
u = (d, u[1])
|
||||||
|
# print(f'Moved towards {closest} via {d}')
|
||||||
|
e = get_enemies_in_range(u)
|
||||||
|
if len(e) != 0:
|
||||||
|
# attack
|
||||||
|
atk_pos = [en[0] for en in e]
|
||||||
|
htp_map = {pos: val for pos, val in hitpoints.items() if pos in atk_pos}
|
||||||
|
min_htp = min(htp_map.values())
|
||||||
|
atk_targets = [pos for pos, htp in htp_map.items() if htp == min_htp]
|
||||||
|
|
||||||
|
target = atk_targets[0]
|
||||||
|
# print(f'Unit {u} attacking {target}')
|
||||||
|
hitpoints[target] -= 3
|
||||||
|
if hitpoints[target] <= 0:
|
||||||
|
del hitpoints[target]
|
||||||
|
x, y = target
|
||||||
|
m[x][y] = '.'
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
# pprint(hitpoints)
|
||||||
|
sleep(.1)
|
||||||
|
|
||||||
|
|
||||||
|
i = main()
|
||||||
|
print()
|
||||||
|
print(f'After {i + 1} rounds:')
|
||||||
|
print_map()
|
||||||
|
print()
|
||||||
|
print('Number of complete rounds:', i)
|
||||||
|
print('hitpoints:', sum(hitpoints.values()))
|
||||||
|
print('Result', i * sum(hitpoints.values()))
|
@ -0,0 +1,32 @@
|
|||||||
|
################################
|
||||||
|
##########################..####
|
||||||
|
#########################...####
|
||||||
|
#########################..#####
|
||||||
|
########################G..#####
|
||||||
|
#####################.#.....##.#
|
||||||
|
#####################..........#
|
||||||
|
##############.#####...........#
|
||||||
|
########G...G#.####............#
|
||||||
|
#######......G....#.....#......#
|
||||||
|
#######...G....GG.#............#
|
||||||
|
#######G.G.............####....#
|
||||||
|
#######.#.....#####....E.....###
|
||||||
|
#######......#######.G.......###
|
||||||
|
#..####..G..#########.###..#####
|
||||||
|
#........G..#########.##########
|
||||||
|
#..#..#G....#########.##########
|
||||||
|
#.###...E...#########.##########
|
||||||
|
#####...G.G.#########.##########
|
||||||
|
########G....#######..##########
|
||||||
|
####..........#####...##########
|
||||||
|
####......E........G..##########
|
||||||
|
#.G..................###########
|
||||||
|
#G...................###########
|
||||||
|
###.....##E.......E..###########
|
||||||
|
###....#............############
|
||||||
|
###.................############
|
||||||
|
##G.....#.............##########
|
||||||
|
###########...#E..##..##########
|
||||||
|
###########.E...###.E.EE.#######
|
||||||
|
###########......#.......#######
|
||||||
|
################################
|
@ -0,0 +1,7 @@
|
|||||||
|
#######
|
||||||
|
#G..#E#
|
||||||
|
#E#E.E#
|
||||||
|
#G.##.#
|
||||||
|
#...#E#
|
||||||
|
#...E.#
|
||||||
|
#######
|
@ -0,0 +1,7 @@
|
|||||||
|
#######
|
||||||
|
#E..EG#
|
||||||
|
#.#G.E#
|
||||||
|
#E.##E#
|
||||||
|
#G..#.#
|
||||||
|
#..E#.#
|
||||||
|
#######
|
@ -0,0 +1,7 @@
|
|||||||
|
#######
|
||||||
|
#E.G#.#
|
||||||
|
#.#G..#
|
||||||
|
#G.#.G#
|
||||||
|
#G..#.#
|
||||||
|
#...E.#
|
||||||
|
#######
|
@ -0,0 +1,7 @@
|
|||||||
|
#######
|
||||||
|
#.E...#
|
||||||
|
#.#..G#
|
||||||
|
#.###.#
|
||||||
|
#E#G#G#
|
||||||
|
#...#G#
|
||||||
|
#######
|
@ -0,0 +1,9 @@
|
|||||||
|
#########
|
||||||
|
#G......#
|
||||||
|
#.E.#...#
|
||||||
|
#..##..G#
|
||||||
|
#...##..#
|
||||||
|
#...#...#
|
||||||
|
#.G...G.#
|
||||||
|
#.....G.#
|
||||||
|
#########
|
@ -0,0 +1,7 @@
|
|||||||
|
#######
|
||||||
|
#.G...#
|
||||||
|
#...EG#
|
||||||
|
#.#.#G#
|
||||||
|
#..G#E#
|
||||||
|
#.....#
|
||||||
|
#######
|
@ -0,0 +1,32 @@
|
|||||||
|
################################
|
||||||
|
##########..#####...############
|
||||||
|
##########.G..####..############
|
||||||
|
########.....##.##.#############
|
||||||
|
####G..#G#.......#.#############
|
||||||
|
#G.....#.GG...G.##.#############
|
||||||
|
#.#...G.......#.##..############
|
||||||
|
###..#.......#####......########
|
||||||
|
######.......#####..G....#######
|
||||||
|
######..GG..######.......#######
|
||||||
|
#####.GG....##.####G......G.####
|
||||||
|
###.............G...........####
|
||||||
|
###.#.........#####G..G....#####
|
||||||
|
###..#.##....#######E.....######
|
||||||
|
########....#########.#######..#
|
||||||
|
#########...#########.#######..#
|
||||||
|
########....#########..##......#
|
||||||
|
#########...#########...#...#.E#
|
||||||
|
#########...#########.......##.#
|
||||||
|
########....E#######.......#####
|
||||||
|
######........#####....E.#######
|
||||||
|
######.......E..E..G.E....######
|
||||||
|
#######.............###....#####
|
||||||
|
#######............####.E...####
|
||||||
|
#######...G....E##....##....####
|
||||||
|
#######...............##########
|
||||||
|
############.E.......###########
|
||||||
|
###########.....#....###########
|
||||||
|
###########.....#....###########
|
||||||
|
###########.....###.############
|
||||||
|
###########.#.##################
|
||||||
|
################################
|
@ -0,0 +1,9 @@
|
|||||||
|
#########
|
||||||
|
#G..G..G#
|
||||||
|
#.......#
|
||||||
|
#.......#
|
||||||
|
#G..E..G#
|
||||||
|
#.......#
|
||||||
|
#.......#
|
||||||
|
#G..G..G#
|
||||||
|
#########
|
Loading…
Reference in New Issue