1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from typing import List
5
+ from functools import lru_cache
6
+ from collections import Counter
7
+
8
+ split_data = ' '
9
+ completed = True
10
+ raw_data = None # Not To be touched
11
+
12
+ def part1 (data :List [str ]):
13
+ stones = data
14
+
15
+ for _ in range (25 ):
16
+ newStones = []
17
+
18
+ for stone in stones :
19
+ if stone == '0' :
20
+ newStones .append ('1' )
21
+ elif len (stone ) % 2 == 0 :
22
+ mid = len (stone ) // 2
23
+ left , right = stone [:mid ], stone [mid :]
24
+ # str -> int -> str to remove trailing 0
25
+ newStones .append (str (int (left )))
26
+ newStones .append (str (int (right )))
27
+ else :
28
+ newStones .append (str (int (stone )* 2024 ))
29
+
30
+ stones = newStones
31
+
32
+ return len (stones )
33
+
34
+ def part2 (data :List [str ]):
35
+ # We can speed up the entire thing by grouping the same stones together
36
+
37
+ @lru_cache (None , typed = False )
38
+ def resolve (stone :str ) -> List [str ]:
39
+ if stone == '0' :
40
+ return ['1' ]
41
+ elif len (stone ) % 2 == 0 :
42
+ mid = len (stone ) // 2
43
+ left , right = stone [:mid ], stone [mid :]
44
+ # str -> int -> str to remove trailing 0
45
+ return [str (int (left )), str (int (right ))]
46
+ else :
47
+ return [str (int (stone )* 2024 )]
48
+
49
+ stones = Counter (data )
50
+
51
+ for _ in range (75 ):
52
+ newStones = Counter ()
53
+ for stone , value in stones .items ():
54
+ resolved = {s :v * value for s , v in Counter (resolve (stone )).items ()}
55
+ newStones .update (resolved )
56
+
57
+ stones = newStones
58
+
59
+ print (resolve .cache_info ())
60
+
61
+ return stones .total ()
0 commit comments