from collections import defaultdict from tools.aoc import AOCDay from typing import Any class Marble: number: int left: 'Marble' right: 'Marble' def __init__(self, number: int): self.number = number def play(players: int, marbles: int): current = Marble(0) current.left = current current.right = current scores = defaultdict(int) next_num = 1 player = 0 while next_num <= marbles: this_marble = Marble(next_num) if next_num % 23 == 0: scores[player] = scores[player] + this_marble.number for _ in range(7): current = current.left scores[player] = scores[player] + current.number current.left.right = current.right current.right.left = current.left current = current.right else: current = current.right this_marble.left = current this_marble.right = current.right current.right.left = this_marble current.right = this_marble current = this_marble player = (player + 1) % players next_num += 1 return max(scores.values()) class Day(AOCDay): inputs = [ [ (8317, "input9_test1"), (146373, "input9_test2"), (412959, "input9"), ], [ (3333662986, "input9"), ] ] def parse_input(self) -> (int, int): parts = self.getInput().split(" ") return int(parts[0]), int(parts[6]) def part1(self) -> Any: return play(*self.parse_input()) def part2(self) -> Any: players, marbles = self.parse_input() marbles *= 100 return play(players, marbles) if __name__ == '__main__': day = Day(2018, 9) day.run(verbose=True)