2021-12-04 - Giant Squid
(original .ipynb)
Day 4 puzzle input is a sequence of comma-separated numbers representing the order that bingo balls are drawn, followed by a number of bingo cards (mine is here). Part 1 involves playing through the bingo game and finding the first card to have a complete row or column. Part 2 involves finding the very last one.
puzzle_input_str = open("puzzle_input/day4.txt").read() test_input_str = """7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 22 13 17 11 0 8 2 23 4 24 21 9 14 16 7 6 10 3 18 5 1 12 20 15 19 3 15 0 2 22 9 18 13 17 5 19 8 7 25 23 20 11 10 24 4 14 21 16 12 6 14 21 17 24 4 10 16 15 9 19 18 8 23 26 20 22 11 13 6 5 2 0 12 3 7""" def parse_card(block): card = [] for line in block.split("\n"): card.append(line.split()) return card def parse_input(input_str): blocks = [block for block in input_str.split("\n\n")] numbers = [n for n in blocks[0].split(",")] cards = [parse_card(card) for card in blocks[1:]] return (numbers, cards) def is_winner(card): # check horizontals for line in card: all_true = True for v in line: all_true = all_true and v == None if all_true: return True # check verticals - there's a neater way to do this but meh for c in range(len(card[0])): all_true = True for r in range(len(card[c])): all_true = all_true and card[r][c] == None if all_true: return True return False def update_card(card, number): for r, row in enumerate(card): for c, col in enumerate(row): if col == number: card[r][c] = None return def score(card, drawn_number): card_total = 0 for row in card: for col in row: if col != None: card_total += int(col) return int(drawn_number) * card_total def nth_bingo_score(numbers, cards, n): winners = set() for number in numbers: for i, card in enumerate(cards): if i in winners: continue update_card(card, number) if is_winner(card): winners.add(i) if n == len(winners): return score(card, number) raise Exception("No winners") def part_one(input_str): numbers, cards = parse_input(input_str) return nth_bingo_score(numbers, cards, 1) assert 4512 == part_one(test_input_str) print("part one:", part_one(puzzle_input_str))
part one: 71708
def part_two(input_str): numbers, cards = parse_input(input_str) return nth_bingo_score(numbers, cards, len(cards)) assert 1924 == part_two(test_input_str) print("part two:", part_two(puzzle_input_str))
part two: 34726