--- /dev/null
+from dataclasses import dataclass\r
+from collections import defaultdict\r
+from typing import List, DefaultDict, TextIO\r
+\r
+\r
+@dataclass\r
+class Problem:\r
+ data: DefaultDict[int, int]\r
+\r
+ @staticmethod\r
+ def calc(value: int) -> List[int]:\r
+ if value == 0:\r
+ result = [1]\r
+ elif len(str(value)) % 2 == 0:\r
+ digits = str(value)\r
+ mid = len(digits) // 2\r
+ result = [int(digits[:mid]), int(digits[mid:])]\r
+ else:\r
+ result = [value * 2024]\r
+ return result\r
+\r
+ def run(self, count: int, debug: bool = False) -> int:\r
+ data = self.data\r
+ if debug:\r
+ print(data)\r
+ for _ in range(count):\r
+ newdata: DefaultDict[int, int] = defaultdict(int)\r
+ for value, count in data.items():\r
+ for newval in Problem.calc(value):\r
+ newdata[newval] += count\r
+ if debug:\r
+ print(newdata)\r
+ data = newdata\r
+ return sum(data.values())\r
+\r
+ @staticmethod\r
+ def from_stream(stream: TextIO) -> 'Problem':\r
+ line = next(stream).strip() # just one line\r
+ data = defaultdict(int, {int(x): 1 for x in line.split(' ')})\r
+ return Problem(data)\r
--- /dev/null
+import sys
+import argparse
+from . import Problem
+
+
+def main(args=None):
+ parser = argparse.ArgumentParser(description="AOC 2024 day 11")
+ parser.add_argument('filename', type=str)
+ parser.add_argument('-d', '--debug', action='store_true')
+ parser.add_argument('-c', '--count', type=int, default=25)
+ options = parser.parse_args(args)
+
+ with open(options.filename) as f:
+ problem = Problem.from_stream(f)
+
+ print(f"result {problem.run(options.count, debug=options.debug)}")
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))