from collections import Counter import time # import operator def read_moves(): with open('day24/input') as reader: return reader.read().splitlines() def split_move(move): split_moves = [] cur = '' for c in move: if cur == '' and c in ('e', 'w'): split_moves.append(c) elif c in ('n', 's'): cur = c else: split_moves.append(cur + c) cur = '' return split_moves move_set = {'e': (2, 0), 'w': (-2, 0), 'ne': (1, 1), 'nw': (-1, 1), 'se': (1, -1), 'sw': (-1, -1)} def add_move(a, b): return a[0]+b[0], a[1]+b[1] # return tuple(map(sum, zip(a, b))) # return tuple(map(operator.add, a, b)) def reduce_moves(move): tile = (0, 0) for m in move: tile = add_move(tile, move_set[m]) return tile moves = read_moves() split_moves = map(split_move, moves) reduced_moves = map(reduce_moves, split_moves) tile_count = Counter(reduced_moves) black_tiles = [tile for tile, amount in tile_count.items() if amount % 2 == 1] print(len(black_tiles)) # part2 def black_needs_to_turn_white(adjacents, current_black): black_adjacent = adjacents.intersection(current_black) return len(black_adjacent) == 0 or len(black_adjacent) > 2 def white_needs_to_turn_black(white, current_black): adjacent_to_white = get_adjacents(white) blacks_adjacent_to_white = adjacent_to_white.intersection(current_black) return len(blacks_adjacent_to_white) == 2 def get_adjacents(current): adjacents = set() for m in move_set.values(): adjacents.add(add_move(current, m)) return adjacents start = time.time() previous_black = set(black_tiles) for i in range(100): black_next = set() already_checked = set(previous_black) for black in previous_black: adjacents = get_adjacents(black) if not black_needs_to_turn_white(adjacents, previous_black): black_next.add(black) for a in adjacents: if a not in already_checked: already_checked.add(a) if white_needs_to_turn_black(a, previous_black): black_next.add(a) if i == 99: print("Day {}: {}".format(str(i+1), len(black_next))) previous_black = black_next end = time.time() print(end - start)