Compare commits
	
		
			85 Commits
		
	
	
		
			master
			...
			2023/day17
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					40ab70271e | ||
| 
						 | 
					f15908876d | ||
| 
						 | 
					5f5ebda674 | ||
| 
						 | 
					5b30cc00d5 | ||
| 
						 | 
					3a7f8e83dc | ||
| 
						 | 
					ba5b01c594 | ||
| 
						 | 
					d0970c090b | ||
| 
						 | 
					8e90bf7002 | ||
| 9698dfcdac | |||
| 
						 | 
					1a6ab1cc0e | ||
| 
						 | 
					f5aabbee8f | ||
| 
						 | 
					6c00341ab0 | ||
| 
						 | 
					755e0bd4b3 | ||
| 
						 | 
					a52d077a40 | ||
| 
						 | 
					3fc0f94b1c | ||
| 
						 | 
					8a0412f926 | ||
| 
						 | 
					855efeb0aa | ||
| 
						 | 
					f2a65e03e5 | ||
| 
						 | 
					759f47bfab | ||
| 
						 | 
					999207b007 | ||
| 
						 | 
					d92e4744a4 | ||
| 
						 | 
					8dbf0f101c | ||
| 
						 | 
					b8d8df06d6 | ||
| 
						 | 
					825ebea299 | ||
| 
						 | 
					869cd4477f | ||
| 
						 | 
					fd777627d6 | ||
| 
						 | 
					98f605f30e | ||
| 
						 | 
					d51fed283c | ||
| 
						 | 
					e991cd8b04 | ||
| 
						 | 
					10f67e6bfd | ||
| 
						 | 
					f291b0aa3f | ||
| 
						 | 
					0eb5b5a88f | ||
| 
						 | 
					2ec0a3d5f9 | ||
| 
						 | 
					0327a3f36a | ||
| 
						 | 
					3732e70ef7 | ||
| 
						 | 
					b0cc6b4a46 | ||
| 
						 | 
					8c24b9f9e2 | ||
| 
						 | 
					dca6f6a08f | ||
| 
						 | 
					8d7a20f575 | ||
| 
						 | 
					3934dfd152 | ||
| 
						 | 
					b656e8929e | ||
| 
						 | 
					c9c69f479b | ||
| 
						 | 
					72ebcfff1f | ||
| 
						 | 
					dd72bb3238 | ||
| 
						 | 
					c1dd74c57d | ||
| 
						 | 
					1bf2de62c7 | ||
| 
						 | 
					df808bc98a | ||
| 
						 | 
					f46e190e98 | ||
| 
						 | 
					7f4a34b2d7 | ||
| 
						 | 
					ddebd26db2 | ||
| 
						 | 
					01300e23b2 | ||
| 
						 | 
					b8e2faa8c9 | ||
| 
						 | 
					ea5b757180 | ||
| 
						 | 
					89a71c175f | ||
| 
						 | 
					9ffb332dea | ||
| 
						 | 
					8167ab34c7 | ||
| 
						 | 
					100df02a09 | ||
| 
						 | 
					15b987a590 | ||
| 
						 | 
					b1578f5709 | ||
| 
						 | 
					d80dbb6c7c | ||
| 
						 | 
					b679c1f895 | ||
| 
						 | 
					e9d5f9747b | ||
| 
						 | 
					fe3aad7ddd | ||
| 
						 | 
					7ac9981ae5 | ||
| 
						 | 
					652756a341 | ||
| 
						 | 
					c7ef505f1b | ||
| 
						 | 
					c55f6ac8e1 | ||
| 
						 | 
					726a6aecac | ||
| 
						 | 
					291b188238 | ||
| 
						 | 
					289e3b7d02 | ||
| 
						 | 
					9820765e9c | ||
| 
						 | 
					c6522de8a2 | ||
| 
						 | 
					80465e5e53 | ||
| 
						 | 
					af1428b5e1 | ||
| 
						 | 
					fca283527d | ||
| 
						 | 
					0d37458ec5 | ||
| 
						 | 
					198927e4a3 | ||
| 
						 | 
					4192c98bba | ||
| 
						 | 
					7cb8317659 | ||
| 
						 | 
					f46cb51c60 | ||
| 
						 | 
					261a396ae7 | ||
| 
						 | 
					4b3af377ab | ||
| 
						 | 
					f697415ef2 | ||
| 
						 | 
					ac2806b0fb | ||
| 
						 | 
					c62b8abfd0 | 
							
								
								
									
										14
									
								
								2021/day1.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								2021/day1.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
values = [int(line) for line in lines]
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:]))
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
runnings = [sum(values[i : i + 3]) for i in range(len(values) - 2)]
 | 
			
		||||
answer_2 = sum(v2 > v1 for v1, v2 in zip(runnings[:-1], runnings[1:]))
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day10.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day10.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day11.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day11.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day12.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day12.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day13.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day13.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day14.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day14.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day15.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day15.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day16.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day16.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day17.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day17.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day18.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day18.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day19.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day19.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										40
									
								
								2021/day2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								2021/day2.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
import sys
 | 
			
		||||
from math import prod
 | 
			
		||||
from typing import Literal, cast
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
commands = [
 | 
			
		||||
    (cast(Literal["forward", "up", "down"], (p := line.split())[0]), int(p[1]))
 | 
			
		||||
    for line in lines
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def depth_and_position(use_aim: bool):
 | 
			
		||||
    aim, pos, depth = 0, 0, 0
 | 
			
		||||
    for command, value in commands:
 | 
			
		||||
        d_depth = 0
 | 
			
		||||
        match command:
 | 
			
		||||
            case "forward":
 | 
			
		||||
                pos += value
 | 
			
		||||
                depth += value * aim
 | 
			
		||||
            case "up":
 | 
			
		||||
                d_depth = -value
 | 
			
		||||
            case "down":
 | 
			
		||||
                d_depth = value
 | 
			
		||||
 | 
			
		||||
        if use_aim:
 | 
			
		||||
            aim += d_depth
 | 
			
		||||
        else:
 | 
			
		||||
            depth += value
 | 
			
		||||
 | 
			
		||||
    return depth, pos
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = prod(depth_and_position(False))
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = prod(depth_and_position(True))
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day20.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day20.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day21.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day21.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day22.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day22.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day23.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day23.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day24.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day24.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day25.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day25.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										39
									
								
								2021/day3.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								2021/day3.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import Counter
 | 
			
		||||
from typing import Literal
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generator_rating(
 | 
			
		||||
    values: list[str], most_common: bool, default: Literal["0", "1"]
 | 
			
		||||
) -> str:
 | 
			
		||||
    index = 0
 | 
			
		||||
    most_common_idx = 0 if most_common else 1
 | 
			
		||||
 | 
			
		||||
    while len(values) > 1:
 | 
			
		||||
        cnt = Counter(value[index] for value in values)
 | 
			
		||||
        bit = cnt.most_common(2)[most_common_idx][0]
 | 
			
		||||
        if cnt["0"] == cnt["1"]:
 | 
			
		||||
            bit = default
 | 
			
		||||
        values = [value for value in values if value[index] == bit]
 | 
			
		||||
        index += 1
 | 
			
		||||
 | 
			
		||||
    return values[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
most_and_least_common = [
 | 
			
		||||
    tuple(Counter(line[col] for line in lines).most_common(2)[m][0] for m in range(2))
 | 
			
		||||
    for col in range(len(lines[0]))
 | 
			
		||||
]
 | 
			
		||||
gamma_rate = int("".join(most for most, _ in most_and_least_common), base=2)
 | 
			
		||||
epsilon_rate = int("".join(least for _, least in most_and_least_common), base=2)
 | 
			
		||||
print(f"answer 1 is {gamma_rate * epsilon_rate}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
 | 
			
		||||
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
 | 
			
		||||
answer_2 = oxygen_generator_rating * co2_scrubber_rating
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										45
									
								
								2021/day4.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								2021/day4.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
numbers = [int(c) for c in lines[0].split(",")]
 | 
			
		||||
 | 
			
		||||
boards = np.asarray(
 | 
			
		||||
    [
 | 
			
		||||
        [[int(c) for c in line.split()] for line in lines[start : start + 5]]
 | 
			
		||||
        for start in range(2, len(lines), 6)
 | 
			
		||||
    ]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# (round, score) for each board (-1 when not found)
 | 
			
		||||
winning_rounds: list[tuple[int, int]] = [(-1, -1) for _ in range(len(boards))]
 | 
			
		||||
marked = np.zeros_like(boards, dtype=bool)
 | 
			
		||||
 | 
			
		||||
for round, number in enumerate(numbers):
 | 
			
		||||
    # mark boards
 | 
			
		||||
    marked[boards == number] = True
 | 
			
		||||
 | 
			
		||||
    # check each board for winning
 | 
			
		||||
    for index in range(len(boards)):
 | 
			
		||||
        if winning_rounds[index][0] > 0:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if np.any(np.all(marked[index], axis=0) | np.all(marked[index], axis=1)):
 | 
			
		||||
            winning_rounds[index] = (
 | 
			
		||||
                round,
 | 
			
		||||
                number * int(np.sum(boards[index][~marked[index]])),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    # all boards are winning - break
 | 
			
		||||
    if np.all(marked.all(axis=1) | marked.all(axis=2)):
 | 
			
		||||
        break
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
(_, score) = min(winning_rounds, key=lambda w: w[0])
 | 
			
		||||
print(f"answer 1 is {score}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
(_, score) = max(winning_rounds, key=lambda w: w[0])
 | 
			
		||||
print(f"answer 2 is {score}")
 | 
			
		||||
							
								
								
									
										48
									
								
								2021/day5.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								2021/day5.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
lines: list[str] = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
sections: list[tuple[tuple[int, int], tuple[int, int]]] = [
 | 
			
		||||
    (
 | 
			
		||||
        (
 | 
			
		||||
            int(line.split(" -> ")[0].split(",")[0]),
 | 
			
		||||
            int(line.split(" -> ")[0].split(",")[1]),
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            int(line.split(" -> ")[1].split(",")[0]),
 | 
			
		||||
            int(line.split(" -> ")[1].split(",")[1]),
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    for line in lines
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
np_sections = np.array(sections).reshape(-1, 4)
 | 
			
		||||
 | 
			
		||||
x_min, x_max, y_min, y_max = (
 | 
			
		||||
    min(np_sections[:, 0].min(), np_sections[:, 2].min()),
 | 
			
		||||
    max(np_sections[:, 0].max(), np_sections[:, 2].max()),
 | 
			
		||||
    min(np_sections[:, 1].min(), np_sections[:, 3].min()),
 | 
			
		||||
    max(np_sections[:, 1].max(), np_sections[:, 3].max()),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
counts_1 = np.zeros((y_max + 1, x_max + 1), dtype=int)
 | 
			
		||||
counts_2 = counts_1.copy()
 | 
			
		||||
 | 
			
		||||
for (x1, y1), (x2, y2) in sections:
 | 
			
		||||
    x_rng = range(x1, x2 + 1, 1) if x2 >= x1 else range(x1, x2 - 1, -1)
 | 
			
		||||
    y_rng = range(y1, y2 + 1, 1) if y2 >= y1 else range(y1, y2 - 1, -1)
 | 
			
		||||
 | 
			
		||||
    if x1 == x2 or y1 == y2:
 | 
			
		||||
        counts_1[list(y_rng), list(x_rng)] += 1
 | 
			
		||||
        counts_2[list(y_rng), list(x_rng)] += 1
 | 
			
		||||
    elif abs(x2 - x1) == abs(y2 - y1):
 | 
			
		||||
        for i, j in zip(y_rng, x_rng):
 | 
			
		||||
            counts_2[i, j] += 1
 | 
			
		||||
 | 
			
		||||
answer_1 = (counts_1 >= 2).sum()
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
answer_2 = (counts_2 >= 2).sum()
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										21
									
								
								2021/day6.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								2021/day6.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
values = [int(c) for c in sys.stdin.read().strip().split(",")]
 | 
			
		||||
 | 
			
		||||
days = 256
 | 
			
		||||
lanterns = {day: 0 for day in range(days)}
 | 
			
		||||
for value in values:
 | 
			
		||||
    for day in range(value, days, 7):
 | 
			
		||||
        lanterns[day] += 1
 | 
			
		||||
 | 
			
		||||
for day in range(days):
 | 
			
		||||
    for day2 in range(day + 9, days, 7):
 | 
			
		||||
        lanterns[day2] += lanterns[day]
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = sum(v for k, v in lanterns.items() if k < 80) + len(values)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = sum(lanterns.values()) + len(values)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										21
									
								
								2021/day7.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								2021/day7.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
positions = np.asarray([int(c) for c in sys.stdin.read().strip().split(",")])
 | 
			
		||||
 | 
			
		||||
min_position, max_position = positions.min(), positions.max()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = min(
 | 
			
		||||
    np.sum(np.abs(positions - position))
 | 
			
		||||
    for position in range(min_position, max_position + 1)
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = min(
 | 
			
		||||
    np.sum(abs(positions - position) * (abs(positions - position) + 1) // 2)
 | 
			
		||||
    for position in range(min_position, max_position + 1)
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										87
									
								
								2021/day8.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								2021/day8.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
import itertools
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
 | 
			
		||||
 | 
			
		||||
digits = {
 | 
			
		||||
    "abcefg": 0,
 | 
			
		||||
    "cf": 1,
 | 
			
		||||
    "acdeg": 2,
 | 
			
		||||
    "acdfg": 3,
 | 
			
		||||
    "bcdf": 4,
 | 
			
		||||
    "abdfg": 5,
 | 
			
		||||
    "abdefg": 6,
 | 
			
		||||
    "acf": 7,
 | 
			
		||||
    "abcdefg": 8,
 | 
			
		||||
    "abcdfg": 9,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)}
 | 
			
		||||
answer_1 = sum(
 | 
			
		||||
    len(p) in lengths for line in lines for p in line.split("|")[1].strip().split()
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
values: list[int] = []
 | 
			
		||||
 | 
			
		||||
for line in lines:
 | 
			
		||||
    parts = line.split("|")
 | 
			
		||||
    broken_digits = sorted(parts[0].strip().split(), key=len)
 | 
			
		||||
 | 
			
		||||
    per_length = {
 | 
			
		||||
        k: list(v)
 | 
			
		||||
        for k, v in itertools.groupby(sorted(broken_digits, key=len), key=len)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # a can be found immediately
 | 
			
		||||
    a = next(u for u in per_length[3][0] if u not in per_length[2][0])
 | 
			
		||||
 | 
			
		||||
    # c and f have only two possible values corresponding to the single entry of
 | 
			
		||||
    # length 2
 | 
			
		||||
    cf = list(per_length[2][0])
 | 
			
		||||
 | 
			
		||||
    # the only digit of length 4 contains bcdf, so we can deduce bd by removing cf
 | 
			
		||||
    bd = [u for u in per_length[4][0] if u not in cf]
 | 
			
		||||
 | 
			
		||||
    # the 3 digits of length 5 have a, d and g in common
 | 
			
		||||
    adg = [u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])]
 | 
			
		||||
 | 
			
		||||
    # we can remove a
 | 
			
		||||
    dg = [u for u in adg if u != a]
 | 
			
		||||
 | 
			
		||||
    # we can deduce d and g
 | 
			
		||||
    d = next(u for u in dg if u in bd)
 | 
			
		||||
    g = next(u for u in dg if u != d)
 | 
			
		||||
 | 
			
		||||
    # then b
 | 
			
		||||
    b = next(u for u in bd if u != d)
 | 
			
		||||
 | 
			
		||||
    # f is in the three 6-length digits, while c is only in 2
 | 
			
		||||
    f = next(u for u in cf if all(u in p for p in per_length[6]))
 | 
			
		||||
 | 
			
		||||
    # c is not f
 | 
			
		||||
    c = next(u for u in cf if u != f)
 | 
			
		||||
 | 
			
		||||
    # e is the last one
 | 
			
		||||
    e = next(u for u in "abcdefg" if u not in {a, b, c, d, f, g})
 | 
			
		||||
 | 
			
		||||
    mapping = dict(zip((a, b, c, d, e, f, g), "abcdefg"))
 | 
			
		||||
 | 
			
		||||
    value = 0
 | 
			
		||||
    for number in parts[1].strip().split():
 | 
			
		||||
        digit = "".join(sorted(mapping[c] for c in number))
 | 
			
		||||
        value = 10 * value + digits[digit]
 | 
			
		||||
 | 
			
		||||
    if VERBOSE:
 | 
			
		||||
        print(value)
 | 
			
		||||
 | 
			
		||||
    values.append(value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
answer_2 = sum(values)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										13
									
								
								2021/day9.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								2021/day9.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = ...
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
answer_2 = ...
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										2000
									
								
								2021/inputs/day1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2000
									
								
								2021/inputs/day1.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day10.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day10.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day11.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day11.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day12.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day12.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day13.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day13.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day14.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day14.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day15.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day15.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day16.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day16.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day17.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day17.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day18.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day18.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day19.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day19.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1000
									
								
								2021/inputs/day2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1000
									
								
								2021/inputs/day2.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day20.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day20.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day21.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day21.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day22.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day22.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day23.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day23.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day24.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day24.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/inputs/day25.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day25.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1000
									
								
								2021/inputs/day3.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1000
									
								
								2021/inputs/day3.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										601
									
								
								2021/inputs/day4.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										601
									
								
								2021/inputs/day4.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,601 @@
 | 
			
		||||
46,12,57,37,14,78,31,71,87,52,64,97,10,35,54,36,27,84,80,94,99,22,0,11,30,44,86,59,66,7,90,21,51,53,92,8,76,41,39,77,42,88,29,24,60,17,68,13,79,67,50,82,25,61,20,16,6,3,81,19,85,9,28,56,75,96,2,26,1,62,33,63,32,73,18,48,43,65,98,5,91,69,47,4,38,23,49,34,55,83,93,45,72,95,40,15,58,74,70,89
 | 
			
		||||
 | 
			
		||||
37 72 60 35 89
 | 
			
		||||
32 49  4 77 82
 | 
			
		||||
30 26 27 63 88
 | 
			
		||||
29 43 16 34 58
 | 
			
		||||
48 33 96 79 94
 | 
			
		||||
 | 
			
		||||
41 94 77 43 87
 | 
			
		||||
 2 17 82 96 25
 | 
			
		||||
95 49 32 12  9
 | 
			
		||||
59 33 67 71 64
 | 
			
		||||
88 54 93 85 30
 | 
			
		||||
 | 
			
		||||
78 84 73 64 81
 | 
			
		||||
 6 66 54 21 15
 | 
			
		||||
72 88 69  5 93
 | 
			
		||||
11 96 38 95 44
 | 
			
		||||
13 41 94 55 48
 | 
			
		||||
 | 
			
		||||
 5 14  2 82 33
 | 
			
		||||
56 26  0 84 92
 | 
			
		||||
 8 95 24 54 25
 | 
			
		||||
68 67 15 85 47
 | 
			
		||||
20 91 36 13 88
 | 
			
		||||
 | 
			
		||||
39 26 33 65 32
 | 
			
		||||
78 72 80 51  0
 | 
			
		||||
35 64 60 18 31
 | 
			
		||||
93 59 83 54 74
 | 
			
		||||
86  5  9 98 69
 | 
			
		||||
 | 
			
		||||
 0  8 20 18 70
 | 
			
		||||
 5 29 65 21 57
 | 
			
		||||
68 61 83 63 51
 | 
			
		||||
91 73 77 75 80
 | 
			
		||||
35 62 16 32 10
 | 
			
		||||
 | 
			
		||||
51 78 58 67 93
 | 
			
		||||
50 14 99  5 31
 | 
			
		||||
 6 21 48 30 83
 | 
			
		||||
22 33 23  1 34
 | 
			
		||||
 2 72 57 54 42
 | 
			
		||||
 | 
			
		||||
15 68  4 24 49
 | 
			
		||||
12  9 74 88 51
 | 
			
		||||
91 19 50 76 75
 | 
			
		||||
80 84 23 17 53
 | 
			
		||||
67 42 22 85 36
 | 
			
		||||
 | 
			
		||||
41 78 11 69  9
 | 
			
		||||
90 25 98 65 77
 | 
			
		||||
97 53 37 84 89
 | 
			
		||||
58 63  5 55  1
 | 
			
		||||
24 10 74 20 82
 | 
			
		||||
 | 
			
		||||
42 19 95 89 49
 | 
			
		||||
61 31 50 76  3
 | 
			
		||||
34 47 32 69 86
 | 
			
		||||
78 68 99 11 91
 | 
			
		||||
55 12 73 45 23
 | 
			
		||||
 | 
			
		||||
24 53 95 64 14
 | 
			
		||||
40 29 71 57 97
 | 
			
		||||
62 70 25 22  2
 | 
			
		||||
88 68 33 82 59
 | 
			
		||||
72 38 76 78 43
 | 
			
		||||
 | 
			
		||||
73 36 84 90 40
 | 
			
		||||
16  4 57  9 29
 | 
			
		||||
38 97 46 51 83
 | 
			
		||||
86 88 99 44 32
 | 
			
		||||
54 49 37 43 62
 | 
			
		||||
 | 
			
		||||
18 66 17 49 27
 | 
			
		||||
24 93 91 87 72
 | 
			
		||||
54 37 77 43 10
 | 
			
		||||
88 80 60 15 79
 | 
			
		||||
47 68 12  2 69
 | 
			
		||||
 | 
			
		||||
 9 23 13 57 68
 | 
			
		||||
38 97 63 88 98
 | 
			
		||||
96 62 65 82 58
 | 
			
		||||
61 83 29 47 40
 | 
			
		||||
21 86 20 16 56
 | 
			
		||||
 | 
			
		||||
27 90 37 97 52
 | 
			
		||||
14 96 76 21 79
 | 
			
		||||
 0 43 63 81 56
 | 
			
		||||
42 62 23 55 74
 | 
			
		||||
45 72 77 44 47
 | 
			
		||||
 | 
			
		||||
 8 78 63 24 87
 | 
			
		||||
 9 23 12 17 68
 | 
			
		||||
36 83 45 61 50
 | 
			
		||||
84 77 18 86 37
 | 
			
		||||
31 26 19 49 94
 | 
			
		||||
 | 
			
		||||
72 84 59 48 40
 | 
			
		||||
92 98 35  1 80
 | 
			
		||||
83 15 85 63 39
 | 
			
		||||
 2 64 58 13 20
 | 
			
		||||
29 88 60 12 74
 | 
			
		||||
 | 
			
		||||
21 94 52  6  4
 | 
			
		||||
89 70 39 23 64
 | 
			
		||||
96 87 31 54 14
 | 
			
		||||
88 35 83 13 56
 | 
			
		||||
84 10 98 48 68
 | 
			
		||||
 | 
			
		||||
70 33 48 21 37
 | 
			
		||||
91 95 65 38 77
 | 
			
		||||
92 14 26 96 60
 | 
			
		||||
12  6 73 13 81
 | 
			
		||||
54 55  2 45 80
 | 
			
		||||
 | 
			
		||||
60 11 67 95 28
 | 
			
		||||
 5 32  0 71 12
 | 
			
		||||
47 78 13 54 43
 | 
			
		||||
49 89 82 66 77
 | 
			
		||||
26 53 19 79  3
 | 
			
		||||
 | 
			
		||||
81  9 53 72 29
 | 
			
		||||
56 35 60 44 45
 | 
			
		||||
42 94 96 88 64
 | 
			
		||||
15 92  4  6 14
 | 
			
		||||
97 11 17 61 63
 | 
			
		||||
 | 
			
		||||
24 43 33  9 34
 | 
			
		||||
36 28 69 35  7
 | 
			
		||||
47  4 14 82 38
 | 
			
		||||
11  1 52  0 49
 | 
			
		||||
93 87 98 41  5
 | 
			
		||||
 | 
			
		||||
37 79 99 34 77
 | 
			
		||||
38 26 25 95 70
 | 
			
		||||
28 78 40 33 86
 | 
			
		||||
41 57 96 10 24
 | 
			
		||||
 9 74 72 50 81
 | 
			
		||||
 | 
			
		||||
18 96 52 29 61
 | 
			
		||||
38 90  1 48 51
 | 
			
		||||
78 11 27 55 97
 | 
			
		||||
33 21 87 93 67
 | 
			
		||||
79 46 94 45  2
 | 
			
		||||
 | 
			
		||||
27 63  6 90 10
 | 
			
		||||
 3 60 24  5 89
 | 
			
		||||
78 72 76 54  8
 | 
			
		||||
33 22 87 51 58
 | 
			
		||||
 4 37 64 91 43
 | 
			
		||||
 | 
			
		||||
63 73 87 80 89
 | 
			
		||||
29 14 95 48  3
 | 
			
		||||
71 55 69  9 67
 | 
			
		||||
30 99 19  2 86
 | 
			
		||||
26 72 88 85 37
 | 
			
		||||
 | 
			
		||||
12 57 81 78 40
 | 
			
		||||
35  4 55 15 39
 | 
			
		||||
33 45 25 60 70
 | 
			
		||||
86 79 88 52  3
 | 
			
		||||
90 20 28 59 85
 | 
			
		||||
 | 
			
		||||
92 51 98 47 99
 | 
			
		||||
41 78 65  4 46
 | 
			
		||||
19 87 39 89 17
 | 
			
		||||
12 23 36 29 44
 | 
			
		||||
 6 82 71 16 37
 | 
			
		||||
 | 
			
		||||
 8 34 81 67 80
 | 
			
		||||
83 92 13 11 41
 | 
			
		||||
39 89 93 49 43
 | 
			
		||||
20 69  3 74 76
 | 
			
		||||
44 72 68 70 45
 | 
			
		||||
 | 
			
		||||
66 39 94 98 28
 | 
			
		||||
72  4 25 77 76
 | 
			
		||||
56 41 84 59 40
 | 
			
		||||
36 87 18 44 73
 | 
			
		||||
29 45 79 55 95
 | 
			
		||||
 | 
			
		||||
45 91  2 92 16
 | 
			
		||||
21 47 86 81 56
 | 
			
		||||
31 11 62  5 95
 | 
			
		||||
39  1 30 65 33
 | 
			
		||||
42 60 17 18 83
 | 
			
		||||
 | 
			
		||||
86 11 77 30 43
 | 
			
		||||
51 88 73 98 94
 | 
			
		||||
72 63 38 56 10
 | 
			
		||||
57 92 49  7 41
 | 
			
		||||
79 75 34 23 54
 | 
			
		||||
 | 
			
		||||
56 95  3 43 65
 | 
			
		||||
39 62 93 19 27
 | 
			
		||||
61 41 99 96 52
 | 
			
		||||
 4 92 77 98 70
 | 
			
		||||
16 54 11 17 57
 | 
			
		||||
 | 
			
		||||
 6 63 10 71 58
 | 
			
		||||
64 70 50 92  0
 | 
			
		||||
 7 14 99 45 26
 | 
			
		||||
78 17 44 46 73
 | 
			
		||||
77 38 62 53 37
 | 
			
		||||
 | 
			
		||||
31 82 67 55 27
 | 
			
		||||
57 58 84  6 15
 | 
			
		||||
14 41 49  8 85
 | 
			
		||||
12 32 91 42 19
 | 
			
		||||
23  1 87 54 29
 | 
			
		||||
 | 
			
		||||
54 60 43 26  4
 | 
			
		||||
78 17 28 67  5
 | 
			
		||||
87 93 90 71 22
 | 
			
		||||
13 30 16 21 85
 | 
			
		||||
55 74 52  1 29
 | 
			
		||||
 | 
			
		||||
50 16 70 32 33
 | 
			
		||||
 6 94 52 66 22
 | 
			
		||||
97 64 98 72 39
 | 
			
		||||
27 69 99 34 26
 | 
			
		||||
36 91 37 21 14
 | 
			
		||||
 | 
			
		||||
 7 97 64 28 18
 | 
			
		||||
85 80 14 37 34
 | 
			
		||||
72  1 22 58 73
 | 
			
		||||
53  3 68 17  0
 | 
			
		||||
29 44 56 95 32
 | 
			
		||||
 | 
			
		||||
30 66 93 24 92
 | 
			
		||||
48 80 79 86 27
 | 
			
		||||
89 13 62 94 81
 | 
			
		||||
70 65 61  8 54
 | 
			
		||||
96 97 20 90 34
 | 
			
		||||
 | 
			
		||||
87 76  4  7 43
 | 
			
		||||
92 55 80 25 62
 | 
			
		||||
79  6 88 35 30
 | 
			
		||||
10 32  5 45 17
 | 
			
		||||
36 27 33 68 63
 | 
			
		||||
 | 
			
		||||
72 69 27 88 41
 | 
			
		||||
34 53 42 84  3
 | 
			
		||||
58 18 22 66 65
 | 
			
		||||
 9 47 85 12 62
 | 
			
		||||
73 90 91 57 33
 | 
			
		||||
 | 
			
		||||
67 16 50 58 52
 | 
			
		||||
68 70 84 98 69
 | 
			
		||||
 4 72  9 64  0
 | 
			
		||||
93 97 39 26  5
 | 
			
		||||
 3 37 79  7 82
 | 
			
		||||
 | 
			
		||||
61 57 88 54 70
 | 
			
		||||
77  8 94 81 63
 | 
			
		||||
39 48 18 13 10
 | 
			
		||||
55 23 27  4 73
 | 
			
		||||
 3  5 64  0 96
 | 
			
		||||
 | 
			
		||||
62 27  0 52 19
 | 
			
		||||
28 57 83 25 41
 | 
			
		||||
 5 59 24 33 80
 | 
			
		||||
37 85  2 86 43
 | 
			
		||||
22 94 50  8 20
 | 
			
		||||
 | 
			
		||||
54 32 34 47 87
 | 
			
		||||
71 22 43 85 24
 | 
			
		||||
11 68 58 36 46
 | 
			
		||||
35 56 61 67 18
 | 
			
		||||
70 23 72  5 59
 | 
			
		||||
 | 
			
		||||
 3 96 41 45 32
 | 
			
		||||
68  2 56 28 24
 | 
			
		||||
87 38 40 75 26
 | 
			
		||||
53 64 73 80 81
 | 
			
		||||
54 88 20  6 18
 | 
			
		||||
 | 
			
		||||
64 55 51 96 47
 | 
			
		||||
59 35 49 67 71
 | 
			
		||||
36 91 61 76 68
 | 
			
		||||
 6 94 20  8 27
 | 
			
		||||
60 88 45  7 82
 | 
			
		||||
 | 
			
		||||
87 94 51 91  1
 | 
			
		||||
96 60 28 97 37
 | 
			
		||||
26 27 74 53 35
 | 
			
		||||
88 89 11 77  8
 | 
			
		||||
73 47 18 59  6
 | 
			
		||||
 | 
			
		||||
46 50 19 36 83
 | 
			
		||||
69 28  4 44 70
 | 
			
		||||
45 20 63 27  1
 | 
			
		||||
53 38  9 47 67
 | 
			
		||||
91 31 79 73 86
 | 
			
		||||
 | 
			
		||||
45  3 98 91 60
 | 
			
		||||
40  7 78 34 83
 | 
			
		||||
52 73 59 13  4
 | 
			
		||||
38 15 82 86 79
 | 
			
		||||
42 11 17 20 62
 | 
			
		||||
 | 
			
		||||
65 86 38 20 72
 | 
			
		||||
78 45 73 74 25
 | 
			
		||||
62 42 24 75  3
 | 
			
		||||
81  8 35 50 51
 | 
			
		||||
44 11 94 85 57
 | 
			
		||||
 | 
			
		||||
13 86 55 65 96
 | 
			
		||||
53 18 43 76 20
 | 
			
		||||
41 14 32 52 38
 | 
			
		||||
90 59 80 68  7
 | 
			
		||||
 2 23 92 39 50
 | 
			
		||||
 | 
			
		||||
96 62 85 24 14
 | 
			
		||||
37  5 11 91 45
 | 
			
		||||
61 28 23 34 77
 | 
			
		||||
43 48 20  0 21
 | 
			
		||||
10 35  2 26 97
 | 
			
		||||
 | 
			
		||||
89  5 40 34 84
 | 
			
		||||
90  6 72 68 10
 | 
			
		||||
13 64 71 31 76
 | 
			
		||||
53 60  9 92 62
 | 
			
		||||
69 98  8 50  3
 | 
			
		||||
 | 
			
		||||
17 86 10 75 79
 | 
			
		||||
67 94 78 40 56
 | 
			
		||||
11 85 82 50 46
 | 
			
		||||
53 39 22  9 61
 | 
			
		||||
59 73 72 33 45
 | 
			
		||||
 | 
			
		||||
65 22 18 96 95
 | 
			
		||||
55 86 67 52 69
 | 
			
		||||
10  2 60 83 98
 | 
			
		||||
43 61 87 88 66
 | 
			
		||||
41 24  8 84 33
 | 
			
		||||
 | 
			
		||||
31 53 98 70 91
 | 
			
		||||
33 34 48 83  9
 | 
			
		||||
40 39 29 71 65
 | 
			
		||||
69 10 62 30  4
 | 
			
		||||
52 21 11 93 75
 | 
			
		||||
 | 
			
		||||
 8 94 53 85 89
 | 
			
		||||
13 84 58 59 29
 | 
			
		||||
97  7 21 25 96
 | 
			
		||||
45 54 34 22 63
 | 
			
		||||
37 17 49 68 67
 | 
			
		||||
 | 
			
		||||
86 87 84 24 10
 | 
			
		||||
82 32 36 59 50
 | 
			
		||||
 8 62 79 71 43
 | 
			
		||||
49 23 85 69 58
 | 
			
		||||
21 66 42 25 56
 | 
			
		||||
 | 
			
		||||
65 88 43 25 19
 | 
			
		||||
26 36 63  5  6
 | 
			
		||||
37 54 75  1 38
 | 
			
		||||
95 46 83 66 28
 | 
			
		||||
 4 90 80 99 85
 | 
			
		||||
 | 
			
		||||
78 83  7 77 34
 | 
			
		||||
27 92 93 96 82
 | 
			
		||||
40 95 52 32 43
 | 
			
		||||
17 28 69 41 85
 | 
			
		||||
21 65 39 58 19
 | 
			
		||||
 | 
			
		||||
11 84 28 90 36
 | 
			
		||||
74  4 62  5 46
 | 
			
		||||
22  8 45 40 98
 | 
			
		||||
12  6 30  9 82
 | 
			
		||||
37  2 53 29 41
 | 
			
		||||
 | 
			
		||||
17 65 31 86 57
 | 
			
		||||
73 16 24 67 53
 | 
			
		||||
60 93 88 45 26
 | 
			
		||||
14 80 94  7 44
 | 
			
		||||
55 78 49  8 82
 | 
			
		||||
 | 
			
		||||
95 38 81 25 76
 | 
			
		||||
29 13 83 47 12
 | 
			
		||||
17 69  4 43 28
 | 
			
		||||
63 84 39 52 34
 | 
			
		||||
 1 97 41 88  8
 | 
			
		||||
 | 
			
		||||
70 40 16 83  3
 | 
			
		||||
15 49 20 74 48
 | 
			
		||||
71 30 21 28 84
 | 
			
		||||
29 10 97  1 18
 | 
			
		||||
57 50 63 35 69
 | 
			
		||||
 | 
			
		||||
40 13 67  9 41
 | 
			
		||||
71 76  8 54 24
 | 
			
		||||
15 97 92 49 96
 | 
			
		||||
61 34 23 81 31
 | 
			
		||||
11 38 48 37 86
 | 
			
		||||
 | 
			
		||||
77 36 32 75  7
 | 
			
		||||
38 18 84 26  2
 | 
			
		||||
19 13 99 83 20
 | 
			
		||||
35 51 74  6 27
 | 
			
		||||
71 48 15 66 69
 | 
			
		||||
 | 
			
		||||
91 57 41  3 99
 | 
			
		||||
74 55 81 77 43
 | 
			
		||||
36 52 47 49 45
 | 
			
		||||
85 65  5 38 50
 | 
			
		||||
90 68 70 16  0
 | 
			
		||||
 | 
			
		||||
 1 90 28 86 27
 | 
			
		||||
73 36 67 11 14
 | 
			
		||||
71 31 10 65 55
 | 
			
		||||
78 21 16 69 12
 | 
			
		||||
87 24 33 83 68
 | 
			
		||||
 | 
			
		||||
90 17 10 84 45
 | 
			
		||||
 5 68 69 27 92
 | 
			
		||||
 6 63 98  3 46
 | 
			
		||||
94 48 59 34 43
 | 
			
		||||
39 88 12 33 73
 | 
			
		||||
 | 
			
		||||
12 31 33 98 63
 | 
			
		||||
65 51 94 83 92
 | 
			
		||||
41 38 84 91 66
 | 
			
		||||
47 28 76 54  3
 | 
			
		||||
48 36 11 13 27
 | 
			
		||||
 | 
			
		||||
51 84 96 16  8
 | 
			
		||||
64 26 74 30 48
 | 
			
		||||
29 41 68 97 87
 | 
			
		||||
 9 38  1 15 39
 | 
			
		||||
98  3 45 53 14
 | 
			
		||||
 | 
			
		||||
53 70 90 95 86
 | 
			
		||||
35 22 85 45 66
 | 
			
		||||
93  0 83 30 88
 | 
			
		||||
64 57 68 36  3
 | 
			
		||||
 5 51 19 20 89
 | 
			
		||||
 | 
			
		||||
 9 36 69 46 44
 | 
			
		||||
37  7 99 57 45
 | 
			
		||||
79 10 86 58 30
 | 
			
		||||
49 98 52 90 27
 | 
			
		||||
14 51 88 60 81
 | 
			
		||||
 | 
			
		||||
73 97 91 19 48
 | 
			
		||||
76 43 18 83 67
 | 
			
		||||
62  9 11 82 55
 | 
			
		||||
24 17 33 53 22
 | 
			
		||||
75  8 56  1 21
 | 
			
		||||
 | 
			
		||||
27 97 53  0 89
 | 
			
		||||
30 70  3 80 54
 | 
			
		||||
56 93 40 64 35
 | 
			
		||||
46 82  1 44 65
 | 
			
		||||
 6 59 45 32 34
 | 
			
		||||
 | 
			
		||||
87 58 73 45 69
 | 
			
		||||
24 49 89 71 83
 | 
			
		||||
94  6 53 68 50
 | 
			
		||||
28 25 88 47  0
 | 
			
		||||
36 13 31 18 55
 | 
			
		||||
 | 
			
		||||
52 63 37 66  9
 | 
			
		||||
34 77 57  6 55
 | 
			
		||||
85 80 97 78 74
 | 
			
		||||
95 75 67 96 29
 | 
			
		||||
22 73 92 69 47
 | 
			
		||||
 | 
			
		||||
79 97 80 36 73
 | 
			
		||||
38 77 35 32 53
 | 
			
		||||
 2 37 29  6 89
 | 
			
		||||
78 91 15 47 34
 | 
			
		||||
11 52 64 84  0
 | 
			
		||||
 | 
			
		||||
69 30 21 99 46
 | 
			
		||||
72  4 15 25 42
 | 
			
		||||
67 98 81 91 63
 | 
			
		||||
70 20 57 65 14
 | 
			
		||||
 0 78 19  8 87
 | 
			
		||||
 | 
			
		||||
20  4 98 33 85
 | 
			
		||||
76 17 94 65 35
 | 
			
		||||
95 69 72 52 71
 | 
			
		||||
23 25 50 38 27
 | 
			
		||||
43 49 96 53 99
 | 
			
		||||
 | 
			
		||||
16 27 34 65 36
 | 
			
		||||
10 40 84 60 82
 | 
			
		||||
80  2 54 67 70
 | 
			
		||||
52 94 79 17 56
 | 
			
		||||
 5 14 77 91 88
 | 
			
		||||
 | 
			
		||||
32 90 50 66 39
 | 
			
		||||
30 16 14 20 10
 | 
			
		||||
 4 42 88 59 12
 | 
			
		||||
75 84 54 51 48
 | 
			
		||||
33 24 13 89 43
 | 
			
		||||
 | 
			
		||||
78 42 34 65 51
 | 
			
		||||
75 72  3 99 61
 | 
			
		||||
15 50 59  8 89
 | 
			
		||||
71 18  9 54 53
 | 
			
		||||
43 39 97 56 19
 | 
			
		||||
 | 
			
		||||
50 43 83  4 30
 | 
			
		||||
89 97 58 35 39
 | 
			
		||||
11 24 61 41 25
 | 
			
		||||
87 99 93 15 34
 | 
			
		||||
31 57  3 45 44
 | 
			
		||||
 | 
			
		||||
70 21 63 24 38
 | 
			
		||||
34 23 88  7 51
 | 
			
		||||
43 18 76 46 49
 | 
			
		||||
60 78 47  8 12
 | 
			
		||||
11 66 98 25 74
 | 
			
		||||
 | 
			
		||||
30 17 23 10 92
 | 
			
		||||
12 85 69 81 91
 | 
			
		||||
47 80 28 29 58
 | 
			
		||||
73 44 77 50 32
 | 
			
		||||
76 54 78 75 60
 | 
			
		||||
 | 
			
		||||
71 53 86 48 98
 | 
			
		||||
90 37 79  8 56
 | 
			
		||||
99 42 97 36 15
 | 
			
		||||
31 85 34 10 40
 | 
			
		||||
43 89 57 72 51
 | 
			
		||||
 | 
			
		||||
48  0 65 55 90
 | 
			
		||||
45 76 69 97  4
 | 
			
		||||
42 52 46 77 56
 | 
			
		||||
64 62 68 35 72
 | 
			
		||||
71 10 27 30 16
 | 
			
		||||
 | 
			
		||||
41 69 63 88 57
 | 
			
		||||
25 56 23 78 80
 | 
			
		||||
 8 92 59 66 97
 | 
			
		||||
48 61 77 15 14
 | 
			
		||||
87 47 91 12 71
 | 
			
		||||
 | 
			
		||||
51 46 15  2 49
 | 
			
		||||
48 33 23 16  4
 | 
			
		||||
80 41 43 59 83
 | 
			
		||||
62 13 20 63 85
 | 
			
		||||
99 30  7 87  8
 | 
			
		||||
 | 
			
		||||
69 80 96 43 47
 | 
			
		||||
61 75 45 62 15
 | 
			
		||||
32 22 91 83 58
 | 
			
		||||
82 13 50 52  8
 | 
			
		||||
89 20 63 73 14
 | 
			
		||||
 | 
			
		||||
40  2 96 52 73
 | 
			
		||||
25 27 26 43 34
 | 
			
		||||
60 38 80 78  5
 | 
			
		||||
83 63 48 10 66
 | 
			
		||||
97 46 53 74 86
 | 
			
		||||
 | 
			
		||||
46  7  0 69 15
 | 
			
		||||
79 19 85 27 73
 | 
			
		||||
63 45  5 49 54
 | 
			
		||||
93 29 84 28 66
 | 
			
		||||
72 23 99  8 33
 | 
			
		||||
 | 
			
		||||
20 72 85 99 49
 | 
			
		||||
69  0 10 52 23
 | 
			
		||||
88 56 28 67 21
 | 
			
		||||
16 91 83 54 81
 | 
			
		||||
14 73 32 30 59
 | 
			
		||||
 | 
			
		||||
31 52 63 12  3
 | 
			
		||||
96 20 82  6 89
 | 
			
		||||
55 38  8 95 40
 | 
			
		||||
 5 60 84 81 75
 | 
			
		||||
51 14 65 27 61
 | 
			
		||||
 | 
			
		||||
46 93  1 47 76
 | 
			
		||||
 8 98  7 16 63
 | 
			
		||||
44 78 17 14 92
 | 
			
		||||
42 62 20 12 68
 | 
			
		||||
56  3 74  6 21
 | 
			
		||||
 | 
			
		||||
 8 94 11 40 44
 | 
			
		||||
43 92 78 91 18
 | 
			
		||||
75 80 12 54 26
 | 
			
		||||
67  9 45 22 21
 | 
			
		||||
86  1 90 36 30
 | 
			
		||||
 | 
			
		||||
21 19 83 90  8
 | 
			
		||||
50 28 45 65 75
 | 
			
		||||
59 88 25 29 70
 | 
			
		||||
58 23  0 95 49
 | 
			
		||||
36 68 76 78 66
 | 
			
		||||
 | 
			
		||||
77 28 43 56 97
 | 
			
		||||
73 71  8 72 46
 | 
			
		||||
23 25 70 69 41
 | 
			
		||||
90 17 34 67 48
 | 
			
		||||
32 75 81 63 21
 | 
			
		||||
							
								
								
									
										500
									
								
								2021/inputs/day5.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										500
									
								
								2021/inputs/day5.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,500 @@
 | 
			
		||||
657,934 -> 657,926
 | 
			
		||||
130,34 -> 570,474
 | 
			
		||||
478,716 -> 226,464
 | 
			
		||||
861,110 -> 861,167
 | 
			
		||||
448,831 -> 370,831
 | 
			
		||||
75,738 -> 390,738
 | 
			
		||||
26,880 -> 864,42
 | 
			
		||||
965,658 -> 527,220
 | 
			
		||||
208,381 -> 80,381
 | 
			
		||||
523,475 -> 807,475
 | 
			
		||||
219,69 -> 219,434
 | 
			
		||||
793,538 -> 534,797
 | 
			
		||||
754,602 -> 754,148
 | 
			
		||||
443,327 -> 443,611
 | 
			
		||||
606,395 -> 546,395
 | 
			
		||||
980,56 -> 51,985
 | 
			
		||||
619,325 -> 354,325
 | 
			
		||||
342,123 -> 819,600
 | 
			
		||||
290,533 -> 374,533
 | 
			
		||||
598,77 -> 598,75
 | 
			
		||||
605,302 -> 605,636
 | 
			
		||||
97,981 -> 692,386
 | 
			
		||||
278,779 -> 278,800
 | 
			
		||||
661,377 -> 661,10
 | 
			
		||||
726,108 -> 518,316
 | 
			
		||||
271,883 -> 271,50
 | 
			
		||||
382,271 -> 606,271
 | 
			
		||||
963,358 -> 891,286
 | 
			
		||||
496,880 -> 496,855
 | 
			
		||||
211,142 -> 211,49
 | 
			
		||||
841,866 -> 260,285
 | 
			
		||||
841,849 -> 173,181
 | 
			
		||||
927,326 -> 391,862
 | 
			
		||||
396,558 -> 459,558
 | 
			
		||||
753,183 -> 953,183
 | 
			
		||||
941,698 -> 941,407
 | 
			
		||||
347,612 -> 347,476
 | 
			
		||||
18,340 -> 18,612
 | 
			
		||||
140,299 -> 797,956
 | 
			
		||||
714,907 -> 714,228
 | 
			
		||||
966,155 -> 194,927
 | 
			
		||||
769,674 -> 712,674
 | 
			
		||||
644,675 -> 948,979
 | 
			
		||||
703,872 -> 812,763
 | 
			
		||||
26,629 -> 120,535
 | 
			
		||||
844,738 -> 844,253
 | 
			
		||||
798,133 -> 798,795
 | 
			
		||||
27,318 -> 288,57
 | 
			
		||||
38,545 -> 872,545
 | 
			
		||||
827,351 -> 195,983
 | 
			
		||||
818,45 -> 21,842
 | 
			
		||||
257,559 -> 626,928
 | 
			
		||||
145,925 -> 886,184
 | 
			
		||||
83,618 -> 590,111
 | 
			
		||||
326,243 -> 53,243
 | 
			
		||||
489,278 -> 526,278
 | 
			
		||||
783,693 -> 783,525
 | 
			
		||||
495,636 -> 495,585
 | 
			
		||||
374,716 -> 215,557
 | 
			
		||||
839,536 -> 839,966
 | 
			
		||||
850,468 -> 955,468
 | 
			
		||||
55,799 -> 55,447
 | 
			
		||||
472,722 -> 296,898
 | 
			
		||||
390,731 -> 120,461
 | 
			
		||||
405,493 -> 208,296
 | 
			
		||||
807,42 -> 56,793
 | 
			
		||||
476,327 -> 655,327
 | 
			
		||||
24,965 -> 967,22
 | 
			
		||||
776,211 -> 776,850
 | 
			
		||||
489,20 -> 822,20
 | 
			
		||||
630,740 -> 871,499
 | 
			
		||||
743,493 -> 283,953
 | 
			
		||||
62,429 -> 62,720
 | 
			
		||||
806,270 -> 806,332
 | 
			
		||||
550,154 -> 107,597
 | 
			
		||||
71,713 -> 533,251
 | 
			
		||||
620,575 -> 620,156
 | 
			
		||||
726,829 -> 143,246
 | 
			
		||||
944,553 -> 468,553
 | 
			
		||||
185,582 -> 185,468
 | 
			
		||||
845,266 -> 212,899
 | 
			
		||||
654,97 -> 265,486
 | 
			
		||||
726,609 -> 726,147
 | 
			
		||||
631,76 -> 860,76
 | 
			
		||||
835,24 -> 928,24
 | 
			
		||||
712,719 -> 74,81
 | 
			
		||||
616,478 -> 616,117
 | 
			
		||||
903,226 -> 903,577
 | 
			
		||||
440,699 -> 136,395
 | 
			
		||||
215,705 -> 890,30
 | 
			
		||||
20,24 -> 981,985
 | 
			
		||||
102,144 -> 850,892
 | 
			
		||||
695,967 -> 582,967
 | 
			
		||||
219,284 -> 219,388
 | 
			
		||||
359,833 -> 665,833
 | 
			
		||||
389,55 -> 305,55
 | 
			
		||||
59,32 -> 957,930
 | 
			
		||||
815,198 -> 64,949
 | 
			
		||||
699,540 -> 717,558
 | 
			
		||||
215,682 -> 182,682
 | 
			
		||||
805,489 -> 328,489
 | 
			
		||||
43,546 -> 578,546
 | 
			
		||||
489,181 -> 489,363
 | 
			
		||||
266,391 -> 266,582
 | 
			
		||||
863,368 -> 448,368
 | 
			
		||||
83,236 -> 83,487
 | 
			
		||||
874,875 -> 874,413
 | 
			
		||||
799,90 -> 799,802
 | 
			
		||||
253,29 -> 253,905
 | 
			
		||||
136,446 -> 435,745
 | 
			
		||||
830,534 -> 550,534
 | 
			
		||||
183,785 -> 107,785
 | 
			
		||||
81,517 -> 159,517
 | 
			
		||||
359,941 -> 359,560
 | 
			
		||||
71,546 -> 948,546
 | 
			
		||||
596,811 -> 596,791
 | 
			
		||||
255,960 -> 255,159
 | 
			
		||||
788,15 -> 788,682
 | 
			
		||||
240,55 -> 240,244
 | 
			
		||||
51,423 -> 137,423
 | 
			
		||||
504,418 -> 809,723
 | 
			
		||||
131,842 -> 914,59
 | 
			
		||||
727,790 -> 82,145
 | 
			
		||||
281,509 -> 841,509
 | 
			
		||||
797,807 -> 834,807
 | 
			
		||||
333,499 -> 790,499
 | 
			
		||||
215,328 -> 215,139
 | 
			
		||||
500,898 -> 500,862
 | 
			
		||||
75,217 -> 777,919
 | 
			
		||||
17,264 -> 17,446
 | 
			
		||||
852,755 -> 150,755
 | 
			
		||||
865,186 -> 385,186
 | 
			
		||||
158,192 -> 158,733
 | 
			
		||||
196,261 -> 196,128
 | 
			
		||||
989,960 -> 131,102
 | 
			
		||||
807,393 -> 807,153
 | 
			
		||||
507,579 -> 507,764
 | 
			
		||||
468,76 -> 535,76
 | 
			
		||||
381,357 -> 659,357
 | 
			
		||||
794,277 -> 749,277
 | 
			
		||||
51,152 -> 546,647
 | 
			
		||||
797,959 -> 458,959
 | 
			
		||||
82,156 -> 967,156
 | 
			
		||||
261,624 -> 460,624
 | 
			
		||||
597,53 -> 197,53
 | 
			
		||||
153,507 -> 411,765
 | 
			
		||||
305,717 -> 768,717
 | 
			
		||||
344,954 -> 344,217
 | 
			
		||||
194,432 -> 545,432
 | 
			
		||||
346,46 -> 557,46
 | 
			
		||||
685,599 -> 685,312
 | 
			
		||||
49,719 -> 49,631
 | 
			
		||||
499,668 -> 304,863
 | 
			
		||||
262,405 -> 554,405
 | 
			
		||||
87,64 -> 295,64
 | 
			
		||||
859,675 -> 74,675
 | 
			
		||||
663,776 -> 99,212
 | 
			
		||||
232,189 -> 232,904
 | 
			
		||||
777,276 -> 703,276
 | 
			
		||||
704,492 -> 86,492
 | 
			
		||||
142,736 -> 514,364
 | 
			
		||||
418,611 -> 224,417
 | 
			
		||||
602,571 -> 602,424
 | 
			
		||||
152,603 -> 248,603
 | 
			
		||||
915,673 -> 143,673
 | 
			
		||||
538,32 -> 128,32
 | 
			
		||||
975,885 -> 975,344
 | 
			
		||||
870,511 -> 870,756
 | 
			
		||||
330,798 -> 46,798
 | 
			
		||||
440,195 -> 587,195
 | 
			
		||||
739,237 -> 568,66
 | 
			
		||||
54,838 -> 196,980
 | 
			
		||||
370,556 -> 47,556
 | 
			
		||||
124,575 -> 748,575
 | 
			
		||||
261,283 -> 880,902
 | 
			
		||||
784,91 -> 426,449
 | 
			
		||||
764,670 -> 148,670
 | 
			
		||||
32,51 -> 967,986
 | 
			
		||||
807,906 -> 10,906
 | 
			
		||||
470,488 -> 579,597
 | 
			
		||||
274,649 -> 285,649
 | 
			
		||||
221,540 -> 221,94
 | 
			
		||||
914,957 -> 914,510
 | 
			
		||||
879,825 -> 145,91
 | 
			
		||||
438,833 -> 438,775
 | 
			
		||||
191,844 -> 911,124
 | 
			
		||||
145,763 -> 595,763
 | 
			
		||||
504,81 -> 622,199
 | 
			
		||||
834,206 -> 834,704
 | 
			
		||||
908,308 -> 815,308
 | 
			
		||||
929,567 -> 929,322
 | 
			
		||||
805,50 -> 620,235
 | 
			
		||||
36,409 -> 133,312
 | 
			
		||||
345,375 -> 19,701
 | 
			
		||||
468,948 -> 468,108
 | 
			
		||||
109,547 -> 446,547
 | 
			
		||||
929,916 -> 69,56
 | 
			
		||||
927,857 -> 318,248
 | 
			
		||||
833,948 -> 833,61
 | 
			
		||||
559,787 -> 559,982
 | 
			
		||||
293,825 -> 293,775
 | 
			
		||||
508,744 -> 545,744
 | 
			
		||||
827,713 -> 753,639
 | 
			
		||||
88,775 -> 555,775
 | 
			
		||||
523,812 -> 684,812
 | 
			
		||||
307,142 -> 307,265
 | 
			
		||||
636,40 -> 355,321
 | 
			
		||||
891,875 -> 891,25
 | 
			
		||||
301,423 -> 712,12
 | 
			
		||||
922,187 -> 219,890
 | 
			
		||||
45,447 -> 230,262
 | 
			
		||||
114,568 -> 233,687
 | 
			
		||||
573,398 -> 677,398
 | 
			
		||||
334,101 -> 324,101
 | 
			
		||||
957,277 -> 957,652
 | 
			
		||||
943,834 -> 610,834
 | 
			
		||||
523,632 -> 523,379
 | 
			
		||||
958,361 -> 90,361
 | 
			
		||||
408,824 -> 380,824
 | 
			
		||||
647,314 -> 647,449
 | 
			
		||||
747,83 -> 59,83
 | 
			
		||||
776,104 -> 937,104
 | 
			
		||||
16,984 -> 989,11
 | 
			
		||||
362,581 -> 362,226
 | 
			
		||||
72,962 -> 940,94
 | 
			
		||||
319,877 -> 319,122
 | 
			
		||||
310,206 -> 986,882
 | 
			
		||||
794,877 -> 267,877
 | 
			
		||||
855,58 -> 976,58
 | 
			
		||||
699,971 -> 598,971
 | 
			
		||||
162,556 -> 162,440
 | 
			
		||||
494,859 -> 494,255
 | 
			
		||||
794,210 -> 142,862
 | 
			
		||||
275,510 -> 548,510
 | 
			
		||||
739,592 -> 739,793
 | 
			
		||||
376,985 -> 376,990
 | 
			
		||||
755,264 -> 280,739
 | 
			
		||||
187,34 -> 187,688
 | 
			
		||||
770,827 -> 770,548
 | 
			
		||||
10,68 -> 913,971
 | 
			
		||||
571,427 -> 571,944
 | 
			
		||||
153,211 -> 153,560
 | 
			
		||||
976,972 -> 55,51
 | 
			
		||||
103,611 -> 674,40
 | 
			
		||||
95,972 -> 924,143
 | 
			
		||||
929,94 -> 38,985
 | 
			
		||||
777,330 -> 60,330
 | 
			
		||||
312,430 -> 312,326
 | 
			
		||||
549,433 -> 269,433
 | 
			
		||||
477,267 -> 477,403
 | 
			
		||||
598,375 -> 19,375
 | 
			
		||||
512,799 -> 512,831
 | 
			
		||||
348,700 -> 348,43
 | 
			
		||||
165,97 -> 63,199
 | 
			
		||||
38,835 -> 38,828
 | 
			
		||||
282,334 -> 282,909
 | 
			
		||||
14,891 -> 390,515
 | 
			
		||||
930,657 -> 334,61
 | 
			
		||||
630,341 -> 630,85
 | 
			
		||||
671,464 -> 319,112
 | 
			
		||||
949,340 -> 894,285
 | 
			
		||||
663,916 -> 245,916
 | 
			
		||||
114,395 -> 286,223
 | 
			
		||||
335,804 -> 529,804
 | 
			
		||||
567,338 -> 14,891
 | 
			
		||||
623,705 -> 379,949
 | 
			
		||||
82,864 -> 545,401
 | 
			
		||||
932,128 -> 932,134
 | 
			
		||||
291,294 -> 291,101
 | 
			
		||||
739,765 -> 739,757
 | 
			
		||||
460,94 -> 892,94
 | 
			
		||||
375,673 -> 367,681
 | 
			
		||||
81,831 -> 90,831
 | 
			
		||||
890,402 -> 890,138
 | 
			
		||||
775,547 -> 790,547
 | 
			
		||||
49,927 -> 966,10
 | 
			
		||||
23,116 -> 257,116
 | 
			
		||||
923,75 -> 18,980
 | 
			
		||||
63,986 -> 687,362
 | 
			
		||||
369,844 -> 357,844
 | 
			
		||||
790,188 -> 644,188
 | 
			
		||||
557,282 -> 557,669
 | 
			
		||||
861,173 -> 390,644
 | 
			
		||||
480,529 -> 893,529
 | 
			
		||||
32,960 -> 830,162
 | 
			
		||||
368,725 -> 368,40
 | 
			
		||||
502,600 -> 701,600
 | 
			
		||||
63,977 -> 873,167
 | 
			
		||||
463,518 -> 788,193
 | 
			
		||||
738,406 -> 324,406
 | 
			
		||||
162,931 -> 822,931
 | 
			
		||||
377,487 -> 707,817
 | 
			
		||||
610,319 -> 901,319
 | 
			
		||||
586,658 -> 690,658
 | 
			
		||||
25,288 -> 53,288
 | 
			
		||||
760,602 -> 760,628
 | 
			
		||||
294,62 -> 951,62
 | 
			
		||||
222,773 -> 661,334
 | 
			
		||||
151,483 -> 646,483
 | 
			
		||||
272,852 -> 317,852
 | 
			
		||||
557,906 -> 503,960
 | 
			
		||||
736,445 -> 736,703
 | 
			
		||||
241,376 -> 241,692
 | 
			
		||||
835,41 -> 835,369
 | 
			
		||||
987,743 -> 987,210
 | 
			
		||||
42,700 -> 42,244
 | 
			
		||||
646,136 -> 646,440
 | 
			
		||||
544,751 -> 404,751
 | 
			
		||||
295,651 -> 295,805
 | 
			
		||||
687,878 -> 113,878
 | 
			
		||||
290,142 -> 604,142
 | 
			
		||||
579,920 -> 579,807
 | 
			
		||||
12,985 -> 987,10
 | 
			
		||||
919,940 -> 919,808
 | 
			
		||||
770,143 -> 770,832
 | 
			
		||||
114,76 -> 962,76
 | 
			
		||||
876,882 -> 428,434
 | 
			
		||||
861,139 -> 861,320
 | 
			
		||||
888,59 -> 888,39
 | 
			
		||||
629,823 -> 707,823
 | 
			
		||||
296,598 -> 296,305
 | 
			
		||||
61,54 -> 578,54
 | 
			
		||||
864,58 -> 253,58
 | 
			
		||||
71,861 -> 306,861
 | 
			
		||||
682,181 -> 326,537
 | 
			
		||||
307,418 -> 307,910
 | 
			
		||||
810,251 -> 810,431
 | 
			
		||||
151,836 -> 602,385
 | 
			
		||||
954,987 -> 243,276
 | 
			
		||||
724,272 -> 350,646
 | 
			
		||||
134,295 -> 434,295
 | 
			
		||||
178,235 -> 802,859
 | 
			
		||||
832,688 -> 832,573
 | 
			
		||||
165,334 -> 165,378
 | 
			
		||||
816,26 -> 114,728
 | 
			
		||||
668,192 -> 540,192
 | 
			
		||||
730,341 -> 969,341
 | 
			
		||||
951,169 -> 286,834
 | 
			
		||||
647,115 -> 886,115
 | 
			
		||||
664,288 -> 507,131
 | 
			
		||||
609,362 -> 609,295
 | 
			
		||||
747,479 -> 287,19
 | 
			
		||||
350,967 -> 350,725
 | 
			
		||||
117,383 -> 311,383
 | 
			
		||||
871,124 -> 292,124
 | 
			
		||||
654,271 -> 547,271
 | 
			
		||||
525,773 -> 345,953
 | 
			
		||||
401,670 -> 610,670
 | 
			
		||||
930,196 -> 301,825
 | 
			
		||||
336,37 -> 961,662
 | 
			
		||||
714,212 -> 714,667
 | 
			
		||||
454,848 -> 454,107
 | 
			
		||||
587,390 -> 587,577
 | 
			
		||||
530,437 -> 542,437
 | 
			
		||||
304,229 -> 517,229
 | 
			
		||||
340,571 -> 766,571
 | 
			
		||||
727,941 -> 138,352
 | 
			
		||||
831,325 -> 11,325
 | 
			
		||||
241,294 -> 403,456
 | 
			
		||||
788,658 -> 788,126
 | 
			
		||||
337,360 -> 337,589
 | 
			
		||||
799,402 -> 342,402
 | 
			
		||||
530,820 -> 530,319
 | 
			
		||||
982,27 -> 20,989
 | 
			
		||||
923,936 -> 923,721
 | 
			
		||||
581,395 -> 64,912
 | 
			
		||||
61,509 -> 61,827
 | 
			
		||||
989,580 -> 610,580
 | 
			
		||||
477,592 -> 219,592
 | 
			
		||||
296,775 -> 296,58
 | 
			
		||||
204,12 -> 204,457
 | 
			
		||||
190,171 -> 190,673
 | 
			
		||||
939,200 -> 939,457
 | 
			
		||||
472,282 -> 472,631
 | 
			
		||||
983,331 -> 734,331
 | 
			
		||||
365,609 -> 365,817
 | 
			
		||||
640,698 -> 145,698
 | 
			
		||||
103,618 -> 549,618
 | 
			
		||||
454,319 -> 454,346
 | 
			
		||||
650,815 -> 381,546
 | 
			
		||||
624,603 -> 507,603
 | 
			
		||||
966,445 -> 723,445
 | 
			
		||||
763,129 -> 763,784
 | 
			
		||||
695,145 -> 695,511
 | 
			
		||||
498,84 -> 435,147
 | 
			
		||||
188,716 -> 967,716
 | 
			
		||||
810,446 -> 810,924
 | 
			
		||||
731,483 -> 731,51
 | 
			
		||||
307,783 -> 307,533
 | 
			
		||||
15,956 -> 956,15
 | 
			
		||||
192,210 -> 882,210
 | 
			
		||||
303,173 -> 38,438
 | 
			
		||||
769,952 -> 769,863
 | 
			
		||||
135,781 -> 405,781
 | 
			
		||||
494,436 -> 494,892
 | 
			
		||||
705,394 -> 714,394
 | 
			
		||||
164,37 -> 164,633
 | 
			
		||||
813,232 -> 813,620
 | 
			
		||||
227,906 -> 222,906
 | 
			
		||||
542,432 -> 414,432
 | 
			
		||||
549,858 -> 88,397
 | 
			
		||||
200,101 -> 958,859
 | 
			
		||||
235,565 -> 469,331
 | 
			
		||||
492,871 -> 503,882
 | 
			
		||||
704,398 -> 869,563
 | 
			
		||||
450,736 -> 746,736
 | 
			
		||||
420,706 -> 420,635
 | 
			
		||||
717,493 -> 686,524
 | 
			
		||||
187,554 -> 717,24
 | 
			
		||||
31,851 -> 315,851
 | 
			
		||||
800,230 -> 466,230
 | 
			
		||||
226,324 -> 226,614
 | 
			
		||||
937,927 -> 937,798
 | 
			
		||||
143,26 -> 534,417
 | 
			
		||||
952,344 -> 12,344
 | 
			
		||||
181,361 -> 782,361
 | 
			
		||||
925,906 -> 415,396
 | 
			
		||||
685,944 -> 470,944
 | 
			
		||||
200,627 -> 290,627
 | 
			
		||||
728,285 -> 728,326
 | 
			
		||||
271,864 -> 271,34
 | 
			
		||||
802,558 -> 207,558
 | 
			
		||||
963,26 -> 84,905
 | 
			
		||||
504,60 -> 529,60
 | 
			
		||||
840,292 -> 180,292
 | 
			
		||||
914,272 -> 914,330
 | 
			
		||||
82,107 -> 925,950
 | 
			
		||||
33,245 -> 33,134
 | 
			
		||||
463,663 -> 463,82
 | 
			
		||||
27,305 -> 27,675
 | 
			
		||||
276,894 -> 891,279
 | 
			
		||||
746,325 -> 746,948
 | 
			
		||||
249,657 -> 341,749
 | 
			
		||||
530,848 -> 28,346
 | 
			
		||||
798,617 -> 798,609
 | 
			
		||||
119,767 -> 312,767
 | 
			
		||||
80,18 -> 674,18
 | 
			
		||||
723,374 -> 583,374
 | 
			
		||||
582,985 -> 239,642
 | 
			
		||||
217,765 -> 217,395
 | 
			
		||||
811,159 -> 609,159
 | 
			
		||||
689,896 -> 501,896
 | 
			
		||||
562,881 -> 562,96
 | 
			
		||||
244,621 -> 629,621
 | 
			
		||||
277,379 -> 277,287
 | 
			
		||||
856,153 -> 20,153
 | 
			
		||||
518,228 -> 518,898
 | 
			
		||||
230,789 -> 243,789
 | 
			
		||||
534,335 -> 534,592
 | 
			
		||||
240,790 -> 413,617
 | 
			
		||||
768,615 -> 768,560
 | 
			
		||||
773,101 -> 912,101
 | 
			
		||||
252,571 -> 767,56
 | 
			
		||||
370,595 -> 681,906
 | 
			
		||||
565,176 -> 565,318
 | 
			
		||||
750,465 -> 750,724
 | 
			
		||||
979,130 -> 120,989
 | 
			
		||||
160,153 -> 160,785
 | 
			
		||||
610,222 -> 610,191
 | 
			
		||||
873,124 -> 130,867
 | 
			
		||||
519,593 -> 519,32
 | 
			
		||||
525,947 -> 525,562
 | 
			
		||||
50,292 -> 291,533
 | 
			
		||||
558,927 -> 960,525
 | 
			
		||||
536,694 -> 249,981
 | 
			
		||||
954,896 -> 277,896
 | 
			
		||||
732,202 -> 732,288
 | 
			
		||||
447,989 -> 541,895
 | 
			
		||||
890,754 -> 367,231
 | 
			
		||||
368,89 -> 564,285
 | 
			
		||||
588,100 -> 588,156
 | 
			
		||||
282,313 -> 943,974
 | 
			
		||||
16,792 -> 495,792
 | 
			
		||||
111,591 -> 111,493
 | 
			
		||||
57,713 -> 685,85
 | 
			
		||||
676,632 -> 676,575
 | 
			
		||||
560,708 -> 560,602
 | 
			
		||||
489,288 -> 489,404
 | 
			
		||||
904,515 -> 443,54
 | 
			
		||||
70,977 -> 985,62
 | 
			
		||||
11,119 -> 11,403
 | 
			
		||||
215,859 -> 937,137
 | 
			
		||||
78,469 -> 110,437
 | 
			
		||||
747,605 -> 747,369
 | 
			
		||||
847,598 -> 847,299
 | 
			
		||||
742,695 -> 159,112
 | 
			
		||||
986,370 -> 986,460
 | 
			
		||||
631,900 -> 771,760
 | 
			
		||||
228,406 -> 683,861
 | 
			
		||||
189,639 -> 61,639
 | 
			
		||||
221,650 -> 820,650
 | 
			
		||||
558,569 -> 834,845
 | 
			
		||||
655,533 -> 558,630
 | 
			
		||||
967,921 -> 967,169
 | 
			
		||||
230,308 -> 429,308
 | 
			
		||||
873,762 -> 873,528
 | 
			
		||||
412,151 -> 412,538
 | 
			
		||||
881,587 -> 881,21
 | 
			
		||||
941,45 -> 26,960
 | 
			
		||||
377,126 -> 700,126
 | 
			
		||||
							
								
								
									
										1
									
								
								2021/inputs/day6.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								2021/inputs/day6.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
2,3,1,3,4,4,1,5,2,3,1,1,4,5,5,3,5,5,4,1,2,1,1,1,1,1,1,4,1,1,1,4,1,3,1,4,1,1,4,1,3,4,5,1,1,5,3,4,3,4,1,5,1,3,1,1,1,3,5,3,2,3,1,5,2,2,1,1,4,1,1,2,2,2,2,3,2,1,2,5,4,1,1,1,5,5,3,1,3,2,2,2,5,1,5,2,4,1,1,3,3,5,2,3,1,2,1,5,1,4,3,5,2,1,5,3,4,4,5,3,1,2,4,3,4,1,3,1,1,2,5,4,3,5,3,2,1,4,1,4,4,2,3,1,1,2,1,1,3,3,3,1,1,2,2,1,1,1,5,1,5,1,4,5,1,5,2,4,3,1,1,3,2,2,1,4,3,1,1,1,3,3,3,4,5,2,3,3,1,3,1,4,1,1,1,2,5,1,4,1,2,4,5,4,1,5,1,5,5,1,5,5,2,5,5,1,4,5,1,1,3,2,5,5,5,4,3,2,5,4,1,1,2,4,4,1,1,1,3,2,1,1,2,1,2,2,3,4,5,4,1,4,5,1,1,5,5,1,4,1,4,4,1,5,3,1,4,3,5,3,1,3,1,4,2,4,5,1,4,1,2,4,1,2,5,1,1,5,1,1,3,1,1,2,3,4,2,4,3,1
 | 
			
		||||
							
								
								
									
										1
									
								
								2021/inputs/day7.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								2021/inputs/day7.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,209,573,1277,704,518,276,196,62,1226,170,58,1450,101,65,99,435,986,1437,1570,35,354,247,110,105,139,1209,23,1074,339,69,483,21,33,323,1348,111,2,270,1239,316,529,1680,1056,1960,257,1009,1073,59,425,1181,198,31,299,771,53,817,728,931,72,517,39,279,304,401,1271,533,1551,133,297,162,902,370,985,643,1217,78,16,380,223,177,600,349,12,776,26,1738,526,85,1542,111,844,93,595,1545,873,836,422,180,1187,329,231,1521,54,162,212,471,1329,156,1299,160,541,676,67,200,22,24,76,242,178,1093,1173,818,1380,284,335,642,1047,112,271,541,927,52,983,238,116,135,871,400,436,1094,684,249,263,303,24,437,813,32,45,19,620,57,866,44,68,277,1112,110,77,1481,437,302,678,541,904,322,13,186,1474,836,43,1020,201,1586,1169,1149,470,535,55,879,133,1229,106,989,1023,256,103,56,401,667,557,98,288,694,286,237,1661,933,1063,20,227,80,815,289,1414,234,517,227,616,829,191,1211,92,591,279,22,139,67,214,60,145,468,10,521,807,1243,76,163,190,122,804,88,383,319,1127,399,376,423,304,126,10,297,377,1103,691,139,70,519,16,15,43,397,468,1183,90,28,1262,151,1448,62,64,1072,386,1330,1313,12,100,657,28,55,612,337,1865,704,263,565,249,564,565,1218,40,1146,150,718,1253,228,120,713,925,159,36,1087,1023,1490,316,540,1124,1127,781,417,656,0,174,1006,529,389,86,90,78,403,1500,253,35,655,650,933,815,108,168,321,345,147,251,258,25,173,243,740,48,476,1507,634,425,738,160,1415,395,448,156,636,1967,516,316,628,810,817,26,20,753,22,1133,352,204,211,47,22,874,43,12,18,1015,779,108,579,251,1398,33,1507,93,274,904,221,1062,868,3,363,42,14,435,62,1508,540,64,267,1690,418,205,502,152,142,414,178,50,344,780,81,635,128,355,239,1708,1814,29,251,624,22,38,789,948,186,529,895,76,150,416,502,975,1216,456,862,522,1149,131,10,121,1353,313,568,595,6,318,633,331,1652,656,214,21,35,289,80,860,229,244,1188,350,594,424,235,327,6,1083,40,134,839,279,172,1452,197,47,2,73,607,238,1151,844,533,110,1207,125,129,16,1000,965,236,228,497,589,111,1245,453,179,956,116,212,47,497,380,574,355,799,209,384,47,449,688,312,748,1531,1092,23,1001,69,155,924,1352,163,1561,743,609,1261,1231,32,1,739,513,300,370,36,568,89,487,201,11,146,274,163,1029,829,469,299,118,732,769,120,1093,776,610,1944,90,67,494,831,88,227,1257,344,662,401,310,664,56,94,183,935,179,643,4,1083,567,1525,208,204,899,123,36,438,1171,265,1406,177,202,1398,631,444,385,589,29,124,96,237,374,793,794,502,665,287,575,113,305,157,465,376,66,662,77,595,75,141,243,254,30,5,622,140,443,566,360,192,1531,1113,1299,598,147,469,732,1565,409,1380,550,173,232,361,131,99,37,547,132,1779,193,228,664,553,568,389,1069,58,71,610,738,624,261,491,158,105,416,131,198,35,823,9,313,6,429,1492,290,313,272,281,427,280,661,141,54,383,3,130,43,418,2,1040,1051,1006,38,151,1325,1357,117,1473,175,201,613,1458,1218,588,169,228,565,901,420,42,117,110,442,9,99,1685,979,84,35,129,248,1,21,360,123,203,1320,1200,209,510,362,106,148,313,292,63,842,93,88,134,720,565,156,118,983,119,1451,757,736,445,466,226,265,573,612,652,170,225,32,1049,1332,366,1375,692,270,388,321,1153,909,1266,93,5,495,377,212,429,90,199,278,631,693,63,816,395,281,315,0,737,575,121,865,1,485,262,49,804,518,109,600,358,221,14,370,450,947,448,67,576,22,1266,226,100,10,607,620,295,568,316,51,687,199,1478,45,489,1878,1035,298,219,363,85,664,1290,492,70,644,78,163,100,102,465,732,439,93,25,847,297,172,361,393,304,461,583,122,121,762,58,112,85,142,48,193,1617,386,685,1054,584,488,394,665,277,263,596,290,1231,171,1394,9,1218,77,54,487,182,528,695,662,413,345,51,690,1702,203,1500,461,1755,190,371,1122,1614,324,238,569,1482,15,711,1332,700,437,242,174,642,660,987,1232,121,620,17,389,22,105,847,36,251,285,1238,162,1227,1473,411,66,258,377,1135,438,117,664,281,1070,301,132,256,498,172,194,103,662,606,342,340,1501,802,549,380,58,179,361
 | 
			
		||||
							
								
								
									
										200
									
								
								2021/inputs/day8.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								2021/inputs/day8.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
			
		||||
caebgd dagc eabgd aebfgc fbdacge edg dg dbgcef eabfd cgeba | gbcdae dagc acgd gd
 | 
			
		||||
fgcbed bcedga cafb acgfd cgabd cgf dfaeg dfbcga bceagdf fc | cf gdfea fdagbc dfacg
 | 
			
		||||
gaed egcbdf edagcf fcaegdb facge afg ga ecbaf fgced fgdabc | cgeaf gfa ga efbac
 | 
			
		||||
cbdeg cbgeadf cgdfa cgdbae decgf efg cebf egbfdc fgbead ef | fge gfe dcegabf gdcfe
 | 
			
		||||
bacd cgdbe ecgbf cd cde degba cfaegd gfadbe gbdace baegcdf | cfgdea dce bacd cabd
 | 
			
		||||
gdbafc cedagb cebga bc edcb gbdefa cebgdaf agfce acb bgdae | afgedb bdce dabeg dbec
 | 
			
		||||
fadce bad edafbc cgbfa edcagf dacbge dfabc bgecadf edbf bd | efbd baegdc dab db
 | 
			
		||||
fcaed eb afcdge cfbae gacbf edab becgdaf gcedbf efb bdecaf | be gadbfec eb cedfa
 | 
			
		||||
cdgbea ebcga feacb age ge afcdgb faegdc acbgd agcfdbe bdeg | gedcab dcagb gea edbg
 | 
			
		||||
eda bgeaf eabdcg ad ebgdacf egdfac ecdbfg dcfge acdf dagfe | ad ad da beagf
 | 
			
		||||
cegfa bf ecfabd fgcb egcafd ebfga bgade afb eagbfc dgfbeca | bcegaf fcgb adgbe bcgf
 | 
			
		||||
fegacb dbagc gdcae fbcd bc dfbgca gdbfa cgb adefbg ecdabgf | cgb fbgdac cabfdg acdeg
 | 
			
		||||
gfbead cfbgea cfeb bf agcfb baf cdgaf begacd aebcg acgdfbe | fab gdcbeaf afcbeg bfa
 | 
			
		||||
df acgbf bedag gecbdf dgefacb fdagb gfadeb fbd abgecd efad | bcafg cafdgeb bdf fd
 | 
			
		||||
defbc dg gadc caebdfg bceagf gecba adegbf ebagdc gecdb dbg | bfgdea aefbdcg dgb dbceg
 | 
			
		||||
cegbd cafegb gedcab gcebdf ecdf dfbag fbgde ef efg fbaecgd | fedc ef fdec ebagcf
 | 
			
		||||
dbfag gabdcf dfgbeac efdcag gbcfe ed efbadg efd bade efbgd | bagfd def ed efgbda
 | 
			
		||||
gafbcde gfbdc fc geafbc cgf ecdfgb cfde dbgac gdfeb gedabf | fced gfc cdbag gfc
 | 
			
		||||
ef adbefg efdbc cfabd fcea fbe cebdg cbfgda abecfd dagbefc | degcbaf ef fecdagb dafebc
 | 
			
		||||
acdbf abefgd ea dgcfe acedgf agec faedcgb afe gcbdfe fecad | geca gebadfc fgeabcd efdca
 | 
			
		||||
agfecd acbg aefdb bg gdcfa gdafb cebdagf gfb dgcafb cgbefd | fbg dgafc fbg bafdg
 | 
			
		||||
db ebafd dcafeg bcedag eafgb bcdf ecafd adb eabdfc cdbgaef | bgafe dfbea bd daefc
 | 
			
		||||
egfacd cegfa afbdg facgbe de dfegbc cdae edafg egd ecdfbga | edg defcga aegfc de
 | 
			
		||||
abdgfce begca egcbf ag gdafbc afge fbdcge daecb cefabg cag | gbfced ga cgedbfa ag
 | 
			
		||||
faed abcedf eafdbcg aebcf cbagf cgebda ef fbe cbgfde bdcae | afbcg dafe fbe fbe
 | 
			
		||||
bcea cfdae dcafeb ab cfbdg dgeabf afbcd baf fdacge gacfdbe | baf decgfab fab abce
 | 
			
		||||
dbeacg agefcd agbefdc cagfe ae aeg aedf gdafc bfceg bacdfg | gea begcf fdcage ea
 | 
			
		||||
cagdeb ca bcfgad badgef cbaf cgbefad adc fcdga gdfec bfagd | aecbdfg afcb ac bcfa
 | 
			
		||||
bc begda gebfcad bfcd dbeac abdfce dcafe cbe cafdge bgcfae | bcdf ebdga gbfecda bce
 | 
			
		||||
dfacgb edbcg gfedab egfab bac begac fcea ca dgfcabe ebacfg | bac cba bgcde ca
 | 
			
		||||
fgacbe dgeba agebf afb fbcaed eafcgd fb dfegacb bgfc cfgea | cfegabd ceafg bf cbadef
 | 
			
		||||
fgcab ceabdgf fdabc da gdabcf gdcaeb ecfbag fadg cdbef acd | fagd gfad fcbgae adgf
 | 
			
		||||
afbgecd cedga cdfb ebgdcf gbfade bcfeag cedgb efgbc bd gdb | fedbcg cefdbg edcag dgb
 | 
			
		||||
bfcga gfadb egcadf cbeagfd bdfeag bcfegd bd edgaf dbae dfb | bfgadec dfb bfd cbfga
 | 
			
		||||
cbegad bacde eafdb bcgea cad cfgadb cd gced fgedcab bfecag | fdgbeac eacbdfg acdbe abdfe
 | 
			
		||||
cebaf dcegbaf edfgab cabgfe bafeg cgaf aegbdc cea febdc ca | ac ac ca cfga
 | 
			
		||||
db bfd ecdfg febdc debfac egdfab cadb efgacb defacgb bcfae | edbcagf bd debfac fdb
 | 
			
		||||
egfdcab dcgbe dacgef fbad bafcge ab degfa ebfgad gbdea gab | ba fabgecd ab agedbf
 | 
			
		||||
afbc efadc efcgabd dfbeac ac bdgeac cfgbed afgde cfdbe dac | ac fegcdb afedc facb
 | 
			
		||||
acbde cgfdea cdbge cfbdea abd ab gacbdfe fdcgab acefd fabe | fbae dagefbc aefbcgd dba
 | 
			
		||||
cedbfga dabecf afbge fab ecbfdg gedfba fbgde cbeag dfag af | beafg acbfed fa gdaf
 | 
			
		||||
ecbgfa eab agdfebc adbg gdfbe dfgecb dabfe afced bagfde ab | bdag gdba dfbge gbda
 | 
			
		||||
egfdac eadbg gfdab bcdega ae egabdfc cdfbeg dae gcbed bace | dgbefc gadefc ea eacb
 | 
			
		||||
bgacf dgfcea cbfgeda fdab fa fag fbgadc gcbef cdabeg bcgda | gfa fag afg aedcbg
 | 
			
		||||
egafdcb dcega dgfbc egdbaf ebdcg dbe eb cabdeg ceab fcdaeg | bed edcfag gadefc fcdbg
 | 
			
		||||
dgcab afgb bcg dcaeb dbgcaf bg ecfdgba gafced fbcdeg cfdga | cefgdb gacfbed afdgc gbcdfa
 | 
			
		||||
cgeda bafcg cgdfa dgfcae bceagd bdgface adf fd feabcd efdg | edfg gdeca cgbdfae dcfgaeb
 | 
			
		||||
dbefga eadcgb gbaedcf daebc geadc bd bcgd bafec bad gaecfd | edagc abcef fceba aecdg
 | 
			
		||||
bcegf cfbega bgedca befca gabecdf bgc gfca gebdf cg dcfabe | efdbg bcg acgf fecbadg
 | 
			
		||||
gfcdeba dbaec ecgaf gde agedfb bcafeg gdfc dgeac dg cadefg | egfca fegac edg daebgf
 | 
			
		||||
bea geadbf be efcad afecgb adfcbg cbefa fcabg gecb egbdfca | eab cbfae gbcafed cbeadgf
 | 
			
		||||
adgfec bgea fbcdg be fdceba bgedc edb acged bfdceag dgbcea | decfba efcdba gbdface aedgfc
 | 
			
		||||
ebgfc dcb dc ecfd fecbgd debcg bgfacd defcgab bacgef dgabe | dc adfbceg befgc cfed
 | 
			
		||||
cbgdea gafc fcegd eagdfb bfdce egc efdag gdafec cg gfbceda | cg ceg dgfea cg
 | 
			
		||||
fgdab egacbfd decgaf eaf edcfgb ea efdcb aefcbd eadbf abec | fdbea ea acefdb ea
 | 
			
		||||
bdegcf aegfb eacd ec acfgd gfdeca fce adcfbg begafdc gcaef | acde gbefcd adce fec
 | 
			
		||||
cdgfbe fdacg cegdf cebd cbeafdg efgcb aegcbf bgfead efd de | fcegdba cbde gbcadfe fed
 | 
			
		||||
adfge efgbda gacfde gecfba ce feacd adbfc cgde fce dfabgce | fgcaed cgde gfaced fdeac
 | 
			
		||||
ga cgaefdb dcebfg fbegac gbda acdef cdgeb gbaedc ecadg cag | bagd bgfdce cbgde dbfaecg
 | 
			
		||||
gec efdabg bfgdcae dfebc agbc aefbg afgbce agecfd cg cegbf | acfdgbe cbdef abcg afbedcg
 | 
			
		||||
ebcgaf cagdf afbdeg fbcda dcfbeag beacfd befca bfd bd cebd | dfb dbf feacbg gfdaecb
 | 
			
		||||
ecgdfa afe gbafd bfgdac ae decbf dgebaf afbed abeg cedabfg | egab cgeabfd eadgbfc ebag
 | 
			
		||||
agcfdeb fdabe gfcaeb edf cegfad badce gdbf fd gbafe fedbga | efd bfgd daecgfb cabefg
 | 
			
		||||
bcdef gefcadb fdeba fdega ba bgea bgdafc efbagd dfcgae dba | ba ba edafb ebga
 | 
			
		||||
acgbe age ga agebfd afcebg bdegc acfeb fgca cefdba cabegdf | ag eag afgc ag
 | 
			
		||||
bacfd feb gfea dabge fegadbc adegbf fe aefdb cbdgae gdcbfe | ef ebdfcg fgdeba efb
 | 
			
		||||
efgca fadbc daecgf ecbfgd gd daeg dfcagbe agfdc bafecg dgf | fgd cfeagb afegc dfg
 | 
			
		||||
cgeabd cdagf dfab afcbgd dceafbg adgbc cfd df efdgcb afgec | cdf cfabdg abfd df
 | 
			
		||||
bgacef acegf adgce cgbfaed dgbec gcdefa afed ad badcgf cda | ad egadc degbfac efcagd
 | 
			
		||||
de ceafb bfedacg decf cbeda aed gdefab dfacbe gadcb gecbfa | acefb eda edcf ead
 | 
			
		||||
fdebga dgbcef baf af caefb debcf baecg cgdfaeb dafc facdbe | af fdac fgceadb efcba
 | 
			
		||||
dgbfac cabdefg ag gda dgcbf gafdb dfaeb bedgcf cafg adcebg | fgadb egfbcad fgca gfbda
 | 
			
		||||
egcbfda fagbde cb egbcf fbc dcgb cdbafe fgdbe dcefbg ceafg | bfc gfcebda bcf bcf
 | 
			
		||||
cfeba ag fecag feacgb eag defgc egabfd gbcafed agcb bdacef | gcfabe efcadgb ga gabc
 | 
			
		||||
fgeadb gbfdace feacb ed bacfde fdbcg edca ecbdf cebgfa def | ebcfa acebdgf efd aced
 | 
			
		||||
fcgad aegfdb ea bdfcea dea egfbd aebg cgbedaf begfdc fedag | geba egbfd fdagbe dcbaef
 | 
			
		||||
faebdg efbca fadce bgefa fcbgae dbecfag bgcf cb ecb dgaecb | cadebgf ecb gcfb cb
 | 
			
		||||
ecdf begca cbagfd ed edb dfebacg cdgfb bcedg cgbfed edagbf | de dfce gedcbf de
 | 
			
		||||
badfec dfgcab gdbeafc cbf defc acefb ebdgaf cf abedf egacb | cdfe cdef fedc fc
 | 
			
		||||
afcgbd fdcg fbc bgdac acbgef cf fcabd gdebca fbaed fcdageb | cf fbc cf gfcd
 | 
			
		||||
cefba dbef fe gdafec dbcae fdebac bfadcge fec gceabd abcfg | gacedb debac bcaed gacfdbe
 | 
			
		||||
bagfe db bdf gafdc bfgda cgefbd cafedg fcgabd fdeacbg dacb | gabdf cdgbfa bd egfbdc
 | 
			
		||||
dbcaef bacfd begfcd gbafc cedbf da eabd gecdfa cda fbecgda | aedb cda efcdb adcfbe
 | 
			
		||||
faebgd afcbdg gf dbacfeg gdf degfa dcfea gebda dgaceb gfbe | bgfe decaf gf edgfa
 | 
			
		||||
fg aecgbfd ebcfa efabg adgeb fge egcbdf bedagf dbcaeg fagd | fg dfga gfda gafd
 | 
			
		||||
cedgabf dcba ab cedaf bae cabefd fgaced fdaeb fabgec dfgeb | bedfac ab fecbga debfcag
 | 
			
		||||
dec ce fcabde daefb fgabde aefc bdagc dcgfeb efcdabg caedb | gadbfec ecfa baefgd ce
 | 
			
		||||
egcaf ed adbe afbcd dgfecba acbdgf edf decfab edcaf egbcfd | dgecfab eabdfcg fbdaec abed
 | 
			
		||||
fea febcg eacgf ecda cdgfa agcedfb edgfba ae agcfde cbadgf | fcegb fgbaced dcafg caed
 | 
			
		||||
gebfd ec dec eabc bafcged debgc fecgda fdgabc dcgabe cgadb | adegbcf gbacfed bfgcdea ce
 | 
			
		||||
egfdab cad bcgad cd bcfga gfdbcea dgcaeb cedg defbac beagd | cadbfe decg cd cadfeb
 | 
			
		||||
cge gadebfc fbcgae gc dagec agdeb dcefga cgdf afbecd ecfda | ebgcaf dbeag fgcdbae dgcf
 | 
			
		||||
bdegca ecbdaf bfae cgdfb ebafdgc ba dfabc bac feagcd fdcea | bac ebcfadg ba ab
 | 
			
		||||
gceda eab agbfedc eafcdg ab gbac bgdef gacbed dgbea cfaebd | bgfcade ba abgc bae
 | 
			
		||||
gbfe eg gcfdeb daebcg bcdef cgefd cdfag fbdeac egcadfb gec | ge befgdc gce egc
 | 
			
		||||
bga gbeacd cbgde gdefcab cagbdf ab beda cfbegd aecgf agecb | agfce daeb bead agb
 | 
			
		||||
fedgba agecbf bc bcdf cgb febdcg ecgfabd gcade dgbec efgdb | bgedfac cb bc bc
 | 
			
		||||
gfaeb bcdfe cea gfca bdacge aecbdfg fegbca ac dfgbae caefb | cfga agcf cfga cbgade
 | 
			
		||||
cgeab fbegda adb dagbfec eafgbc bd bgcd adecf cegdba daebc | efbcdag gdcb bd deacfgb
 | 
			
		||||
bcagd cbgde gbfad eabdgf cda ceabfd fcag cdgabf agcbdfe ca | ca ca ac cda
 | 
			
		||||
agdce dageb eacdbf ecgdaf bafgd dgfacbe dgbaec bceg bea be | gceb bgdcaef edgac aedgc
 | 
			
		||||
bceadf adcfeg ga dfag geacd cabegdf ceafgb gca aecfd edcbg | ag acbfde gdfa ag
 | 
			
		||||
fdcegb abdfce cdega bgcad gfea cae ae bcafged fagedc fgdec | gfdce bafcde gfcdeb ae
 | 
			
		||||
egbcda cebadf bfe ef bedcg bgfda fgec fedbg begcfad gdbcef | bef gcbeda ef ecgf
 | 
			
		||||
egfdb cgd gdbfea cgbdf fdcba fgbdaec agbdec cg fecg cgdbfe | abgfedc fbcgd cegf gc
 | 
			
		||||
cfbegd ab gbacfd agefd ceab baf acfgdeb eafbgc bfegc bagef | ba abf beca baf
 | 
			
		||||
fcega fecda cbgaef fgaedb gbfc geadbc fag ecbdgaf eacgb fg | ecdfa bfgc dgebaf gcabe
 | 
			
		||||
aefdcg gfdcab ab fagb dbaegcf adb faecbd gcadb fcgad ebdgc | gadcef bfdaecg fgba fgecad
 | 
			
		||||
eabfc cdebf bgfca ecfbgad fbdceg aeb gceabd afde ea cbfade | abcdgef eabfc abe bdcfae
 | 
			
		||||
cd dgfceab dec cbegfd gedaf adfgec ecbag fgadbe cadf cgdea | fgedbc edc dce adcgfeb
 | 
			
		||||
agcdbf ecdgf adfcg agfcbed ef ecdfab efc agfe cgebd defagc | eadcfb cfdbega cef geaf
 | 
			
		||||
cdbafe deacf ga dbecag fecdagb bcfge gfda caedfg gae eagfc | ga eag gfcebad cfgae
 | 
			
		||||
ceadfg bdf gfbec adbe fbegd abgdfc bd gdefa gdfeba dgacefb | bagedfc facedgb fbd bd
 | 
			
		||||
ecdba ecdagb gcfeda fbdaeg cfedb befcdag ca agedb abcg ace | cea fbaged eca bcag
 | 
			
		||||
gfedc gdaf gaefc dcf bgcde gdeafc fcgadeb gecabf cdafbe df | fd gcaef df egfdca
 | 
			
		||||
afegb cefgb eadcbg cgfbad dbecg cfde aegbcdf fcb gdebfc fc | fbcged bcf gbced aefgdcb
 | 
			
		||||
ca bfeda cae ecdfgb edgcf dgceaf gbaced afcg gbeacdf aefcd | ac dfcebag cagf ace
 | 
			
		||||
begcad efdagb fbgeadc fedcba aec abedg fcegb ca cgda abegc | abcfgde fgebadc bagedf gdca
 | 
			
		||||
aegb cfeadb acdgf decgbf ecgdb gcfedab bgdcea ba gbdac bad | bgceda gdafc fgadc dafcbe
 | 
			
		||||
fgecba aec adfe deacb ae abegdcf bcdag ecbfd gecdbf dafceb | gdcab ae edfa daef
 | 
			
		||||
agfde eacg adebfg fdgcb cafdg fgdeca cfbaed ac gcadfbe acf | fca gdfae acge dbeacf
 | 
			
		||||
fbagce de deg edfa fcbdg gbdcae aegfb dbgfe dgacbfe gefbad | edfa de ged bdgcf
 | 
			
		||||
bacfdg cdeafgb aecbfd daefb agedc afc abdefg cebf deacf cf | gbdafc efbc cfead fc
 | 
			
		||||
cegfab cdag bdc dc febad gfdbce dcaefbg gfbac dcafbg cdabf | dgafcb cdag dcbgeaf gaefdbc
 | 
			
		||||
dagefb acefg afdcb gd dgfaecb facbgd bcdg gda badcfe fgacd | fbecgda cfadb gbdc fcaeg
 | 
			
		||||
gfbd cfeda gabcfe db dba baefg beafd bcgdae fedcbag efbdag | dba bad ebgaf dbegfca
 | 
			
		||||
cf fbdega aefbg afbcedg edgca dgbcfe gfaec febcag ecf afcb | aefbg gcaefb dbcegaf cef
 | 
			
		||||
gebdaf abgd cdabfe gacefbd agfed dg ged fegac aebfd fbdcge | egd abdegcf gadb afbgde
 | 
			
		||||
gcdf efdcb acfebd beagdc gd bdefg ebfcgd bdg fbega geabcfd | dgceba ecadgb adgfbce edbgf
 | 
			
		||||
fdcaebg efbdgc bgdacf dcae cbdge gebaf abd edgab da bgaedc | cebagd ad da gebcda
 | 
			
		||||
bfgcae cbd bcfea aedcb gbefcd cd adecfb adfc cagdfbe dbega | fcad cdabgfe dacf dcb
 | 
			
		||||
becg gfbace egacfbd acbfg acdfgb aec ce bdfea cgedaf fbcea | afcbg fedagc befac aecfgd
 | 
			
		||||
befa cgfed cfadb gdcfba acdfe ace edgbac fgcdbea ceafdb ae | feab eacdf bcdgafe bfae
 | 
			
		||||
bcdefag dafeg fgec dgeafc gea gdfbca cgdaeb bfdea eg dgafc | eg aefcdgb ecdfag gea
 | 
			
		||||
gfadb gedfb bdecgfa adbefg dcgaf abf gdcefb aebg ab bafced | gdbfe gbfed ebag cabgfde
 | 
			
		||||
dbegfa acgbdf eg gcfbed gdafb bfacegd ebg aged fageb bacfe | ge gefcdba ge bgdfa
 | 
			
		||||
adbgec fdceg afdgc bedf cfe fe gaecbdf faebgc gcbed fcbedg | acfdg gdeabc debf ef
 | 
			
		||||
dfgbe da ecbadg dafeg fadb gfdbea dagcfbe dbgfec cfgea dga | befdg agd eafdg fabd
 | 
			
		||||
bedc aefbc ceadfb fdb cbagfed fecgab dcfba gaebdf cfagd bd | db bfd bfcae adgefb
 | 
			
		||||
cabedgf edbfgc gedcfa bacegf fde dgbf baced fd fedbc fegbc | fcdeb adbgefc adecgbf fde
 | 
			
		||||
fged egafc ecafgd efcda dfa dfcabg becfag fd agcdfbe ecdab | dgef fd dgfe df
 | 
			
		||||
deafgb gbfdc dg dbg agdc dbcafg cadfb bafced fgbce daegbfc | gbfdac afdgcb dgb gdcfb
 | 
			
		||||
dfecb fabdge cegbaf fdca faecb aefcdb bdf gdbce afgcebd fd | dbf fbd edcabgf fadc
 | 
			
		||||
cbf egabfdc fdcgba fabecd cf dfagb gfac adbegf cdegb bcfgd | acfg afgbed cgdfab fc
 | 
			
		||||
ebdfagc bcfa gecfdb af daegbf fgcbd bcdfag egcda fgdca gfa | fcab gafcdb dbfega acfb
 | 
			
		||||
adfbg eacb abfcg ecafbg gface ecfgad bc degfbc cbg gabdefc | cb gabefcd cagfebd agcbfe
 | 
			
		||||
ebgad bef gacfe gceadf fb efcagbd eabfcd cegfab gbfc ebagf | cefadg fcgae fgbc ebacdgf
 | 
			
		||||
dcg aged efacd cfgdae edacbf edfcg bcagdef gd fecbg dcfbag | cdeabgf gd gcd adge
 | 
			
		||||
fecgda cdabefg gabfc gfacbd ecgabf cbafe bcdef ea ace bgea | egba gabe beagfdc fbcag
 | 
			
		||||
bacdgf eafbd cagde becad afgcedb bc fbegad cfbe cba fcdaeb | fcbe abc dbecaf edcba
 | 
			
		||||
ecbdf dagfceb abcfde cbade aebgc adb bfgead debfgc cafd ad | bad dcaf begac da
 | 
			
		||||
gbae deafb fdgbea cegfd ag cdaefb cgabefd degfa dag dfcgab | baeg agefdb bcdafg cbdfga
 | 
			
		||||
ebcdf gdeafbc cdgbfe eaf cdfa deafbc gedab aecfbg ebadf af | befacd ebfda af af
 | 
			
		||||
cfab dcb gfedbac bc cgaedb fbdge cbfdg acgbdf gdcaf acgdfe | bc fcab afcb dbc
 | 
			
		||||
edbag gebdc bedfag eacdbg bcedgfa ecab ec gaedcf bdcfg cge | ce ceab ec bdegcaf
 | 
			
		||||
fedcba fbgca cbafge ef gbdacf efbgcad gefca befg ecdga afe | fea adgfcb fcage bcdfae
 | 
			
		||||
da edfgc cgfdba adfecgb gfaeb dcefga fecdgb gad gdeaf ecad | cedfg dbfcega gfcaed abdcfeg
 | 
			
		||||
fcgbed fcbedga cafbe gdceba bcafge bfe fagb fb eacbg facde | cdfbeg fb ebgcadf fgcedba
 | 
			
		||||
fecdb fdcbae afdeg cdfea aec efgbadc ca cbfa dcagbe gbefdc | facb fabc fcdbega efadcb
 | 
			
		||||
dagcf gadfeb ad dfegbc cgdfba dbac abgecfd dcgfb cfgae adf | fgadc cbda ad cfagd
 | 
			
		||||
fdgcb agedbc cdbef feac efb ef febdac afdegb abced edgafcb | fe bfecd dcebf cafe
 | 
			
		||||
cafdbg eaf fe gebf befcag cfbga cgaef fdaecbg edcga febacd | gfbe egbf aebgcdf faceg
 | 
			
		||||
bfc febg cdfga dafbec cegbd fb cdbgfe cbfgd cadegb gbefdac | dcefgb dbfcg deafbc gbdec
 | 
			
		||||
bacgd cedfbg cf aefc dfc aecgdf adfcgeb gafed cafgd baefdg | dgafc fc dfc gfbced
 | 
			
		||||
bcge fgc efcdab ecgafb cfeab fabgd fagbc bgcdeaf efcagd cg | cbeg bdagf bcgaf fgc
 | 
			
		||||
cdaeg fbaec ceafd fd cfd adfceb bgaecf dbcegf bdaf cgeabdf | df cdf fdagbce cbedaf
 | 
			
		||||
dgcbf gecfadb gbdecf gfdbca fbagde ad cdgab dag afcd caegb | cgbedf dfac bdacfeg cafdbg
 | 
			
		||||
defacg bd cdbegaf cfaeb dbf cbefgd cgdaf cfbgda facbd gabd | gfadec bdf gbad adgcef
 | 
			
		||||
bagdce deagcf bcdf cfa abgfdc cf geacfbd afgeb bacfg dcagb | cf cdbf aedcbfg fbdc
 | 
			
		||||
fbceda bedcf dg gefcdb aefbgd gdf cgde gfacb bdcfg dfcegab | dfbagec dfg cabdfeg gd
 | 
			
		||||
gda cfgbde dgbfc fgabdc fcagd cagfe baecgdf faebdg ad adbc | efgdcb dag dacb ad
 | 
			
		||||
dagec eca fgeacd cdefab gfdacbe afged dabgfe ac dcebg afgc | bdgce ecdga eagdc ca
 | 
			
		||||
da bda gadc dbafg fabgc faedcb dfcbgea agcfbe bedgf gfbadc | acbfegd gfabdc bad da
 | 
			
		||||
gdce aebfdg faebc fcdabg acgfedb eacgdb adc adgeb cd daceb | cd cgbadf cad edcg
 | 
			
		||||
caedb agbed gfbcad eca fdce gbface baefdcg acfdb fbedca ce | eac cebadf fagcdb cae
 | 
			
		||||
fcbadeg fcae bfdca ceb ec cdebaf ecbdf gcedab bgdfe dfagcb | geabcd acef agbced gdbeafc
 | 
			
		||||
cbdef degba efbad eafc dbcfge ecdafb af fcbgad edfbcag baf | gbdea ecaf eacf egfcdab
 | 
			
		||||
fcde gabfd cdgeba fac fc dcabe bfaced dacbf ebgfac cgfbeda | adcfb fca gebdfca fadbc
 | 
			
		||||
fdceg cbd edcgfa cb cdgfeb gdebac edgcafb fceb agbdf bgcfd | adfgce beacdgf bc cedfbag
 | 
			
		||||
fcbegda dbcefg gcebad gbfc cdb gfbaed bc cebfd ecdfa bdegf | dcb gabedf beafdg bc
 | 
			
		||||
cfaed bacdg egd aegcdf gcef gedac cdbefga afdgbe bdfaec eg | gcade cefad bdgfea gaedc
 | 
			
		||||
ac dbeacg ace defba fcaebdg dabfce abfedg dcaf cbfae efbcg | fegdba cfbae cea dbacfe
 | 
			
		||||
dgcaef bgcaef cfdgeb gd fgecb dcgfbae gebfd bgdc adebf fdg | gdf dafgbec dfg adfeb
 | 
			
		||||
ag cadg cgfed aefbc bcegdf agdfbe agf egfca gefcdba gdfeac | dgca dgcaef cdga adebcfg
 | 
			
		||||
dfcgbe badg aedgc eabfc dfcbega cgdafe eagbc aegcdb gbe bg | acfdge bge adbg bg
 | 
			
		||||
bcfage adcefg dfagc fgaec cdf abcgd dcbgafe df dfae fgcbed | df cfd eacgf fdc
 | 
			
		||||
cbadfe bfg cfgebd cbdg edfgbca bg egbdf feagcb fedag cefdb | fgdeb gfb fbdeca bgcd
 | 
			
		||||
bcde fdcgba abfcde dbfac abefc befga aec ce acfdge afdegbc | fcbad eac ec becd
 | 
			
		||||
ce cbagdf gdcbf cfaebdg gcbe acfdge fcdegb dbaef cef bcefd | acbgdfe cfebd gcebdf ec
 | 
			
		||||
ecgbd eacbf cgadeb edf ecafbdg afgebd dcgf ecfbd fgcbed fd | bcfea edf efgabcd df
 | 
			
		||||
dgbf egafcd cfedbag cgb abcef dcefg ebcfg cgeadb bg cgbfed | adfgebc egbcf cfeab gaefbdc
 | 
			
		||||
gecbfd gbedc dgabcef baefgd abegc dbfce bfdace dg gdb dfcg | dfgc bedfac dg dbg
 | 
			
		||||
acbdgf daeb gcbeaf gdfce adefg fbdga cbdfega fae fgdbea ea | ea fcdgaeb ae gecfadb
 | 
			
		||||
ga bdgafe bcaed dcgaebf bacfed acedg gbadec edgfc agd bcga | adg dga agcb fdecgab
 | 
			
		||||
ebdcfg cfbdg ecgabf gcd edfc fdcbeag ebcdag dabgf dc cgebf | cd gcd gacbde cd
 | 
			
		||||
egdfac bf afebdg baf bfdeca bgdf fedga egacb gecbafd gbeaf | bfa fb gfdb fb
 | 
			
		||||
gcafb dc gecd fecbgda cfdbg dfebgc cdf fbegd dcfbea fgedab | edfcbg dgbcf cd dcf
 | 
			
		||||
badf fcagd agcefb dfgcab ba dcbeg cedabgf abgdc acegfd abg | ebfagc dfab ab fcbdeag
 | 
			
		||||
cfgbad gdbfe fe efgdacb cbdge dabgfe egdcaf befa bdgfa egf | decagfb eabf baef fe
 | 
			
		||||
dbfea bcaefdg dcfgeb ag bfceag egfcda becfg fgeba gcab ega | agbfecd aedfcgb gcba ga
 | 
			
		||||
							
								
								
									
										0
									
								
								2021/inputs/day9.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/inputs/day9.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										10
									
								
								2021/tests/day1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								2021/tests/day1.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
199
 | 
			
		||||
200
 | 
			
		||||
208
 | 
			
		||||
210
 | 
			
		||||
200
 | 
			
		||||
207
 | 
			
		||||
240
 | 
			
		||||
269
 | 
			
		||||
260
 | 
			
		||||
263
 | 
			
		||||
							
								
								
									
										0
									
								
								2021/tests/day10.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day10.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day11.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day11.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day12.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day12.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day13.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day13.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day14.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day14.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day15.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day15.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day16.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day16.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day17.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day17.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day18.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day18.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day19.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day19.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										6
									
								
								2021/tests/day2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								2021/tests/day2.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
forward 5
 | 
			
		||||
down 5
 | 
			
		||||
forward 8
 | 
			
		||||
up 3
 | 
			
		||||
down 8
 | 
			
		||||
forward 2
 | 
			
		||||
							
								
								
									
										0
									
								
								2021/tests/day20.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day20.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day21.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day21.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day22.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day22.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day23.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day23.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day24.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day24.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								2021/tests/day25.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day25.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										12
									
								
								2021/tests/day3.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								2021/tests/day3.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
00100
 | 
			
		||||
11110
 | 
			
		||||
10110
 | 
			
		||||
10111
 | 
			
		||||
10101
 | 
			
		||||
01111
 | 
			
		||||
00111
 | 
			
		||||
11100
 | 
			
		||||
10000
 | 
			
		||||
11001
 | 
			
		||||
00010
 | 
			
		||||
01010
 | 
			
		||||
							
								
								
									
										19
									
								
								2021/tests/day4.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								2021/tests/day4.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										0
									
								
								2021/tests/day5.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day5.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								2021/tests/day6.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								2021/tests/day6.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
3,4,3,1,2
 | 
			
		||||
							
								
								
									
										1
									
								
								2021/tests/day7.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								2021/tests/day7.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
16,1,2,0,4,2,7,1,2,14
 | 
			
		||||
							
								
								
									
										10
									
								
								2021/tests/day8.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								2021/tests/day8.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
 | 
			
		||||
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
 | 
			
		||||
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
 | 
			
		||||
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
 | 
			
		||||
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
 | 
			
		||||
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
 | 
			
		||||
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
 | 
			
		||||
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
 | 
			
		||||
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
 | 
			
		||||
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
 | 
			
		||||
							
								
								
									
										0
									
								
								2021/tests/day9.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021/tests/day9.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										22
									
								
								2022/day1.py
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								2022/day1.py
									
									
									
									
									
								
							@@ -1,19 +1,7 @@
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
blocks = sys.stdin.read().split("\n\n")
 | 
			
		||||
values = sorted(sum(map(int, block.split())) for block in blocks)
 | 
			
		||||
 | 
			
		||||
with open(Path(__file__).parent.joinpath("inputs", "day1.txt")) as fp:
 | 
			
		||||
    lines = fp.readlines()
 | 
			
		||||
 | 
			
		||||
values: list[int] = [0]
 | 
			
		||||
for line in lines:
 | 
			
		||||
    if not line.strip():
 | 
			
		||||
        values = values + [0]
 | 
			
		||||
    else:
 | 
			
		||||
        values[-1] += int(line.strip())
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
print(f"max is {max(values)}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
print(f"sum of top 3 is {sum(sorted(values)[-3:])}")
 | 
			
		||||
print(f"answer 1 is {values[-1]}")
 | 
			
		||||
print(f"answer 2 is {sum(values[-3:])}")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								2022/day10.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								2022/day10.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
cycle = 1
 | 
			
		||||
x = 1
 | 
			
		||||
 | 
			
		||||
values = {cycle: x}
 | 
			
		||||
 | 
			
		||||
for line in lines:
 | 
			
		||||
    cycle += 1
 | 
			
		||||
 | 
			
		||||
    if line == "noop":
 | 
			
		||||
        pass
 | 
			
		||||
    else:
 | 
			
		||||
        r = int(line.split()[1])
 | 
			
		||||
 | 
			
		||||
        values[cycle] = x
 | 
			
		||||
 | 
			
		||||
        cycle += 1
 | 
			
		||||
        x += r
 | 
			
		||||
 | 
			
		||||
    values[cycle] = x
 | 
			
		||||
 | 
			
		||||
answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40))
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for i in range(6):
 | 
			
		||||
    for j in range(40):
 | 
			
		||||
        v = values[1 + i * 40 + j]
 | 
			
		||||
 | 
			
		||||
        if j >= v - 1 and j <= v + 1:
 | 
			
		||||
            print("#", end="")
 | 
			
		||||
        else:
 | 
			
		||||
            print(".", end="")
 | 
			
		||||
 | 
			
		||||
    print()
 | 
			
		||||
							
								
								
									
										142
									
								
								2022/day11.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								2022/day11.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,142 @@
 | 
			
		||||
import copy
 | 
			
		||||
import sys
 | 
			
		||||
from functools import reduce
 | 
			
		||||
from typing import Callable, Final, Mapping, Sequence
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Monkey:
 | 
			
		||||
    id: Final[int]
 | 
			
		||||
    items: Final[Sequence[int]]
 | 
			
		||||
    worry_fn: Final[Callable[[int], int]]
 | 
			
		||||
    test_value: Final[int]
 | 
			
		||||
    throw_targets: Final[Mapping[bool, int]]
 | 
			
		||||
 | 
			
		||||
    def __init__(
 | 
			
		||||
        self,
 | 
			
		||||
        id: int,
 | 
			
		||||
        items: list[int],
 | 
			
		||||
        worry_fn: Callable[[int], int],
 | 
			
		||||
        test_value: int,
 | 
			
		||||
        throw_targets: dict[bool, int],
 | 
			
		||||
    ):
 | 
			
		||||
        self.id = id
 | 
			
		||||
        self.items = items
 | 
			
		||||
        self.worry_fn = worry_fn
 | 
			
		||||
        self.test_value = test_value
 | 
			
		||||
        self.throw_targets = throw_targets
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, o: object) -> bool:
 | 
			
		||||
        if not isinstance(o, Monkey):
 | 
			
		||||
            return False
 | 
			
		||||
        return self.id == o.id
 | 
			
		||||
 | 
			
		||||
    def __hash__(self) -> int:
 | 
			
		||||
        return hash(self.id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_monkey(lines: list[str]) -> Monkey:
 | 
			
		||||
    assert lines[0].startswith("Monkey")
 | 
			
		||||
 | 
			
		||||
    monkey_id = int(lines[0].split()[-1][:-1])
 | 
			
		||||
 | 
			
		||||
    # parse items
 | 
			
		||||
    items = [int(r.strip()) for r in lines[1].split(":")[1].split(",")]
 | 
			
		||||
 | 
			
		||||
    # parse worry
 | 
			
		||||
    worry_fn: Callable[[int], int]
 | 
			
		||||
    worry_s = lines[2].split("new =")[1].strip()
 | 
			
		||||
    operand = worry_s.split()[2].strip()
 | 
			
		||||
 | 
			
		||||
    if worry_s.startswith("old *"):
 | 
			
		||||
        if operand == "old":
 | 
			
		||||
            worry_fn = lambda w: w * w  # noqa: E731
 | 
			
		||||
        else:
 | 
			
		||||
            worry_fn = lambda w: w * int(operand)  # noqa: E731
 | 
			
		||||
    elif worry_s.startswith("old +"):
 | 
			
		||||
        if operand == "old":
 | 
			
		||||
            worry_fn = lambda w: w + w  # noqa: E731
 | 
			
		||||
        else:
 | 
			
		||||
            worry_fn = lambda w: w + int(operand)  # noqa: E731
 | 
			
		||||
    else:
 | 
			
		||||
        assert False, worry_s
 | 
			
		||||
 | 
			
		||||
    # parse test
 | 
			
		||||
    assert lines[3].split(":")[1].strip().startswith("divisible by")
 | 
			
		||||
    test_value = int(lines[3].split()[-1])
 | 
			
		||||
 | 
			
		||||
    assert lines[4].strip().startswith("If true")
 | 
			
		||||
    assert lines[5].strip().startswith("If false")
 | 
			
		||||
    throw_targets = {True: int(lines[4].split()[-1]), False: int(lines[5].split()[-1])}
 | 
			
		||||
 | 
			
		||||
    assert monkey_id not in throw_targets.values()
 | 
			
		||||
 | 
			
		||||
    return Monkey(monkey_id, items, worry_fn, test_value, throw_targets)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run(
 | 
			
		||||
    monkeys: list[Monkey], n_rounds: int, me_worry_fn: Callable[[int], int]
 | 
			
		||||
) -> dict[Monkey, int]:
 | 
			
		||||
    """
 | 
			
		||||
    Perform a full run.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        monkeys: Initial list of monkeys. The Monkey are not modified.
 | 
			
		||||
        n_rounds: Number of rounds to run.
 | 
			
		||||
        me_worry_fn: Worry function to apply after the Monkey operation (e.g., divide
 | 
			
		||||
            by 3 for round 1).
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        A mapping containing, for each monkey, the number of items inspected.
 | 
			
		||||
    """
 | 
			
		||||
    # copy of the items
 | 
			
		||||
    items = {monkey: list(monkey.items) for monkey in monkeys}
 | 
			
		||||
 | 
			
		||||
    # number of inspects
 | 
			
		||||
    inspects = {monkey: 0 for monkey in monkeys}
 | 
			
		||||
 | 
			
		||||
    for _ in range(n_rounds):
 | 
			
		||||
        for monkey in monkeys:
 | 
			
		||||
            for item in items[monkey]:
 | 
			
		||||
                inspects[monkey] += 1
 | 
			
		||||
 | 
			
		||||
                # compute the new worry level
 | 
			
		||||
                item = me_worry_fn(monkey.worry_fn(item))
 | 
			
		||||
 | 
			
		||||
                # find the target
 | 
			
		||||
                target = monkey.throw_targets[item % monkey.test_value == 0]
 | 
			
		||||
                assert target != monkey.id
 | 
			
		||||
 | 
			
		||||
                items[monkeys[target]].append(item)
 | 
			
		||||
 | 
			
		||||
            # clear after the loop
 | 
			
		||||
            items[monkey].clear()
 | 
			
		||||
 | 
			
		||||
    return inspects
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def monkey_business(inspects: dict[Monkey, int]) -> int:
 | 
			
		||||
    sorted_levels = sorted(inspects.values())
 | 
			
		||||
    return sorted_levels[-2] * sorted_levels[-1]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
monkeys = [parse_monkey(block.splitlines()) for block in sys.stdin.read().split("\n\n")]
 | 
			
		||||
 | 
			
		||||
# case 1: we simply divide the worry by 3 after applying the monkey worry operation
 | 
			
		||||
answer_1 = monkey_business(
 | 
			
		||||
    run(copy.deepcopy(monkeys), 20, me_worry_fn=lambda w: w // 3)
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# case 2: to keep reasonable level values, we can use a modulo operation, we need to
 | 
			
		||||
# use the product of all "divisible by" test so that the test remains valid
 | 
			
		||||
#
 | 
			
		||||
# (a + b) % c == ((a % c) + (b % c)) % c --- this would work for a single test value
 | 
			
		||||
#
 | 
			
		||||
# (a + b) % c == ((a % d) + (b % d)) % c --- if d is a multiple of c, which is why here
 | 
			
		||||
# we use the product of all test value
 | 
			
		||||
#
 | 
			
		||||
total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1)
 | 
			
		||||
answer_2 = monkey_business(
 | 
			
		||||
    run(copy.deepcopy(monkeys), 10_000, me_worry_fn=lambda w: w % total_test_value)
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										160
									
								
								2022/day12.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								2022/day12.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,160 @@
 | 
			
		||||
import heapq
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Callable, Iterator, TypeVar
 | 
			
		||||
 | 
			
		||||
Node = TypeVar("Node")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def dijkstra(
 | 
			
		||||
    start: Node,
 | 
			
		||||
    neighbors: Callable[[Node], Iterator[Node]],
 | 
			
		||||
    cost: Callable[[Node, Node], float],
 | 
			
		||||
) -> tuple[dict[Node, float], dict[Node, Node]]:
 | 
			
		||||
    """
 | 
			
		||||
    Compute shortest paths from one node to all reachable ones.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        start: Starting node.
 | 
			
		||||
        neighbors: Function returning the neighbors of a node.
 | 
			
		||||
        cost: Function to compute the cost of an edge.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        A tuple (lengths, parents) where lengths is a mapping from Node to distance
 | 
			
		||||
        (from the starting node) and parents a mapping from parents Node (in the
 | 
			
		||||
        shortest path). If keyset of lengths and parents is the same. If a Node is not
 | 
			
		||||
        in the mapping, it cannot be reached from the starting node.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    queue: list[tuple[float, Node]] = []
 | 
			
		||||
 | 
			
		||||
    visited: set[Node] = set()
 | 
			
		||||
    lengths: dict[Node, float] = {start: 0}
 | 
			
		||||
    parents: dict[Node, Node] = {}
 | 
			
		||||
 | 
			
		||||
    heapq.heappush(queue, (0, start))
 | 
			
		||||
 | 
			
		||||
    while queue:
 | 
			
		||||
        length, current = heapq.heappop(queue)
 | 
			
		||||
 | 
			
		||||
        if current in visited:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        visited.add(current)
 | 
			
		||||
 | 
			
		||||
        for neighbor in neighbors(current):
 | 
			
		||||
            if neighbor in visited:
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            neighbor_cost = length + cost(current, neighbor)
 | 
			
		||||
 | 
			
		||||
            if neighbor_cost < lengths.get(neighbor, float("inf")):
 | 
			
		||||
                lengths[neighbor] = neighbor_cost
 | 
			
		||||
                parents[neighbor] = current
 | 
			
		||||
 | 
			
		||||
                heapq.heappush(queue, (neighbor_cost, neighbor))
 | 
			
		||||
 | 
			
		||||
    return lengths, parents
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_path(parents: dict[Node, Node], start: Node, end: Node) -> list[Node] | None:
 | 
			
		||||
    if end not in parents:
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    path: list[Node] = [end]
 | 
			
		||||
 | 
			
		||||
    while path[-1] is not start:
 | 
			
		||||
        path.append(parents[path[-1]])
 | 
			
		||||
 | 
			
		||||
    return list(reversed(path))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_path(path: list[tuple[int, int]], n_rows: int, n_cols: int) -> None:
 | 
			
		||||
    end = path[-1]
 | 
			
		||||
 | 
			
		||||
    graph = [["." for _c in range(n_cols)] for _r in range(n_rows)]
 | 
			
		||||
    graph[end[0]][end[1]] = "E"
 | 
			
		||||
 | 
			
		||||
    for i in range(0, len(path) - 1):
 | 
			
		||||
        cr, cc = path[i]
 | 
			
		||||
        nr, nc = path[i + 1]
 | 
			
		||||
 | 
			
		||||
        if cr == nr and nc == cc - 1:
 | 
			
		||||
            graph[cr][cc] = "<"
 | 
			
		||||
        elif cr == nr and nc == cc + 1:
 | 
			
		||||
            graph[cr][cc] = ">"
 | 
			
		||||
        elif cr == nr - 1 and nc == cc:
 | 
			
		||||
            graph[cr][cc] = "v"
 | 
			
		||||
        elif cr == nr + 1 and nc == cc:
 | 
			
		||||
            graph[cr][cc] = "^"
 | 
			
		||||
        else:
 | 
			
		||||
            assert False, "{} -> {} infeasible".format(path[i], path[i + 1])
 | 
			
		||||
 | 
			
		||||
    print("\n".join("".join(row) for row in graph))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def neighbors(
 | 
			
		||||
    grid: list[list[int]], node: tuple[int, int], up: bool
 | 
			
		||||
) -> Iterator[tuple[int, int]]:
 | 
			
		||||
    n_rows = len(grid)
 | 
			
		||||
    n_cols = len(grid[0])
 | 
			
		||||
 | 
			
		||||
    c_row, c_col = node
 | 
			
		||||
    for n_row, n_col in (
 | 
			
		||||
        (c_row - 1, c_col),
 | 
			
		||||
        (c_row + 1, c_col),
 | 
			
		||||
        (c_row, c_col - 1),
 | 
			
		||||
        (c_row, c_col + 1),
 | 
			
		||||
    ):
 | 
			
		||||
        if not (n_row >= 0 and n_row < n_rows and n_col >= 0 and n_col < n_cols):
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if up and grid[n_row][n_col] > grid[c_row][c_col] + 1:
 | 
			
		||||
            continue
 | 
			
		||||
        elif not up and grid[n_row][n_col] < grid[c_row][c_col] - 1:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        yield n_row, n_col
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# === main code ===
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
 | 
			
		||||
 | 
			
		||||
start: tuple[int, int]
 | 
			
		||||
end: tuple[int, int]
 | 
			
		||||
 | 
			
		||||
# for part 2
 | 
			
		||||
start_s: list[tuple[int, int]] = []
 | 
			
		||||
 | 
			
		||||
for i_row, row in enumerate(grid):
 | 
			
		||||
    for i_col, col in enumerate(row):
 | 
			
		||||
        if chr(col + ord("a")) == "S":
 | 
			
		||||
            start = (i_row, i_col)
 | 
			
		||||
            start_s.append(start)
 | 
			
		||||
        elif chr(col + ord("a")) == "E":
 | 
			
		||||
            end = (i_row, i_col)
 | 
			
		||||
        elif col == 0:
 | 
			
		||||
            start_s.append((i_row, i_col))
 | 
			
		||||
 | 
			
		||||
# fix values
 | 
			
		||||
grid[start[0]][start[1]] = 0
 | 
			
		||||
grid[end[0]][end[1]] = ord("z") - ord("a")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lengths_1, parents_1 = dijkstra(
 | 
			
		||||
    start=start, neighbors=lambda n: neighbors(grid, n, True), cost=lambda lhs, rhs: 1
 | 
			
		||||
)
 | 
			
		||||
path_1 = make_path(parents_1, start, end)
 | 
			
		||||
assert path_1 is not None
 | 
			
		||||
 | 
			
		||||
print_path(path_1, n_rows=len(grid), n_cols=len(grid[0]))
 | 
			
		||||
 | 
			
		||||
print(f"answer 1 is {lengths_1[end] - 1}")
 | 
			
		||||
 | 
			
		||||
lengths_2, parents_2 = dijkstra(
 | 
			
		||||
    start=end, neighbors=lambda n: neighbors(grid, n, False), cost=lambda lhs, rhs: 1
 | 
			
		||||
)
 | 
			
		||||
answer_2 = min(lengths_2.get(start, float("inf")) for start in start_s)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										41
									
								
								2022/day13.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								2022/day13.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
import json
 | 
			
		||||
import sys
 | 
			
		||||
from functools import cmp_to_key
 | 
			
		||||
from typing import TypeAlias, cast
 | 
			
		||||
 | 
			
		||||
blocks = sys.stdin.read().strip().split("\n\n")
 | 
			
		||||
 | 
			
		||||
pairs = [tuple(json.loads(p) for p in block.split("\n")) for block in blocks]
 | 
			
		||||
 | 
			
		||||
Packet: TypeAlias = list[int | list["Packet"]]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def compare(lhs: Packet, rhs: Packet) -> int:
 | 
			
		||||
    for lhs_a, rhs_a in zip(lhs, rhs):
 | 
			
		||||
        if isinstance(lhs_a, int) and isinstance(rhs_a, int):
 | 
			
		||||
            if lhs_a != rhs_a:
 | 
			
		||||
                return rhs_a - lhs_a
 | 
			
		||||
        else:
 | 
			
		||||
            if not isinstance(lhs_a, list):
 | 
			
		||||
                lhs_a = [lhs_a]  # type: ignore
 | 
			
		||||
            elif not isinstance(rhs_a, list):
 | 
			
		||||
                rhs_a = [rhs_a]  # type: ignore
 | 
			
		||||
            assert isinstance(rhs_a, list) and isinstance(lhs_a, list)
 | 
			
		||||
            r = compare(cast(Packet, lhs_a), cast(Packet, rhs_a))
 | 
			
		||||
            if r != 0:
 | 
			
		||||
                return r
 | 
			
		||||
 | 
			
		||||
    return len(rhs) - len(lhs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
answer_1 = sum(i + 1 for i, (lhs, rhs) in enumerate(pairs) if compare(lhs, rhs) > 0)
 | 
			
		||||
print(f"answer_1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
dividers = [[[2]], [[6]]]
 | 
			
		||||
 | 
			
		||||
packets = [packet for packets in pairs for packet in packets]
 | 
			
		||||
packets.extend(dividers)
 | 
			
		||||
packets = list(reversed(sorted(packets, key=cmp_to_key(compare))))
 | 
			
		||||
 | 
			
		||||
d_index = [packets.index(d) + 1 for d in dividers]
 | 
			
		||||
print(f"answer 2 is {d_index[0] * d_index[1]}")
 | 
			
		||||
							
								
								
									
										140
									
								
								2022/day14.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								2022/day14.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
import sys
 | 
			
		||||
from enum import Enum, auto
 | 
			
		||||
from typing import Callable, cast
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Cell(Enum):
 | 
			
		||||
    AIR = auto()
 | 
			
		||||
    ROCK = auto()
 | 
			
		||||
    SAND = auto()
 | 
			
		||||
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        return {Cell.AIR: ".", Cell.ROCK: "#", Cell.SAND: "O"}[self]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_blocks(blocks: dict[tuple[int, int], Cell]):
 | 
			
		||||
    """
 | 
			
		||||
    Print the given set of blocks on a grid.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        blocks: Set of blocks to print.
 | 
			
		||||
    """
 | 
			
		||||
    x_min, y_min, x_max, y_max = (
 | 
			
		||||
        min(x for x, _ in blocks),
 | 
			
		||||
        0,
 | 
			
		||||
        max(x for x, _ in blocks),
 | 
			
		||||
        max(y for _, y in blocks),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    for y in range(y_min, y_max + 1):
 | 
			
		||||
        print(
 | 
			
		||||
            "".join(str(blocks.get((x, y), Cell.AIR)) for x in range(x_min, x_max + 1))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flow(
 | 
			
		||||
    blocks: dict[tuple[int, int], Cell],
 | 
			
		||||
    stop_fn: Callable[[int, int], bool],
 | 
			
		||||
    fill_fn: Callable[[int, int], Cell],
 | 
			
		||||
) -> dict[tuple[int, int], Cell]:
 | 
			
		||||
    """
 | 
			
		||||
    Flow sands onto the given set of blocks
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        blocks: Blocks containing ROCK position. Modified in-place.
 | 
			
		||||
        stop_fn: Function called with the last (assumed) position of a grain of
 | 
			
		||||
            sand BEFORE adding it to blocks. If the function returns True, the grain
 | 
			
		||||
            is added and a new one is flowed, otherwise, the whole procedure stops
 | 
			
		||||
            and the function returns (without adding the final grain).
 | 
			
		||||
        fill_fn: Function called when the target position of a grain (during the
 | 
			
		||||
            flowing process) is missing from blocks.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        The input blocks.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    y_max = max(y for _, y in blocks)
 | 
			
		||||
 | 
			
		||||
    while True:
 | 
			
		||||
        x, y = 500, 0
 | 
			
		||||
 | 
			
		||||
        while y <= y_max:
 | 
			
		||||
            moved = False
 | 
			
		||||
            for cx, cy in ((x, y + 1), (x - 1, y + 1), (x + 1, y + 1)):
 | 
			
		||||
                if (cx, cy) not in blocks and fill_fn(cx, cy) == Cell.AIR:
 | 
			
		||||
                    x, y = cx, cy
 | 
			
		||||
                    moved = True
 | 
			
		||||
                elif blocks[cx, cy] == Cell.AIR:
 | 
			
		||||
                    x, y = cx, cy
 | 
			
		||||
                    moved = True
 | 
			
		||||
 | 
			
		||||
                if moved:
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
            if not moved:
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        if stop_fn(x, y):
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
        blocks[x, y] = Cell.SAND
 | 
			
		||||
 | 
			
		||||
    return blocks
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# === inputs ===
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
paths: list[list[tuple[int, int]]] = []
 | 
			
		||||
for line in lines:
 | 
			
		||||
    parts = line.split(" -> ")
 | 
			
		||||
    paths.append(
 | 
			
		||||
        [
 | 
			
		||||
            cast(tuple[int, int], tuple(int(c.strip()) for c in part.split(",")))
 | 
			
		||||
            for part in parts
 | 
			
		||||
        ]
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
blocks: dict[tuple[int, int], Cell] = {}
 | 
			
		||||
for path in paths:
 | 
			
		||||
    for start, end in zip(path[:-1], path[1:]):
 | 
			
		||||
        x_start = min(start[0], end[0])
 | 
			
		||||
        x_end = max(start[0], end[0]) + 1
 | 
			
		||||
        y_start = min(start[1], end[1])
 | 
			
		||||
        y_end = max(start[1], end[1]) + 1
 | 
			
		||||
 | 
			
		||||
        for x in range(x_start, x_end):
 | 
			
		||||
            for y in range(y_start, y_end):
 | 
			
		||||
                blocks[x, y] = Cell.ROCK
 | 
			
		||||
 | 
			
		||||
print_blocks(blocks)
 | 
			
		||||
print()
 | 
			
		||||
 | 
			
		||||
x_min, y_min, x_max, y_max = (
 | 
			
		||||
    min(x for x, _ in blocks),
 | 
			
		||||
    0,
 | 
			
		||||
    max(x for x, _ in blocks),
 | 
			
		||||
    max(y for _, y in blocks),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# === part 1 ===
 | 
			
		||||
 | 
			
		||||
blocks_1 = flow(
 | 
			
		||||
    blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR
 | 
			
		||||
)
 | 
			
		||||
print_blocks(blocks_1)
 | 
			
		||||
print(f"answer 1 is {sum(v == Cell.SAND for v in blocks_1.values())}")
 | 
			
		||||
print()
 | 
			
		||||
 | 
			
		||||
# === part 2 ===
 | 
			
		||||
 | 
			
		||||
blocks_2 = flow(
 | 
			
		||||
    blocks.copy(),
 | 
			
		||||
    stop_fn=lambda x, y: x == 500 and y == 0,
 | 
			
		||||
    fill_fn=lambda x, y: Cell.AIR if y < y_max + 2 else Cell.ROCK,
 | 
			
		||||
)
 | 
			
		||||
blocks_2[500, 0] = Cell.SAND
 | 
			
		||||
print_blocks(blocks_2)
 | 
			
		||||
print(f"answer 2 is {sum(v == Cell.SAND for v in blocks_2.values())}")
 | 
			
		||||
							
								
								
									
										87
									
								
								2022/day15.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								2022/day15.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
import parse
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def part1(sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], row: int) -> int:
 | 
			
		||||
    no_beacons_row_l: list[np.ndarray] = []
 | 
			
		||||
 | 
			
		||||
    for (sx, sy), (bx, by) in sensor_to_beacon.items():
 | 
			
		||||
        d = abs(sx - bx) + abs(sy - by)  # closest
 | 
			
		||||
 | 
			
		||||
        no_beacons_row_l.append(sx - np.arange(0, d - abs(sy - row) + 1))
 | 
			
		||||
        no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1))
 | 
			
		||||
 | 
			
		||||
    beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row)
 | 
			
		||||
    no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(beacons_at_row)
 | 
			
		||||
 | 
			
		||||
    return len(no_beacons_row)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def part2_intervals(
 | 
			
		||||
    sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], xy_max: int
 | 
			
		||||
) -> tuple[int, int, int]:
 | 
			
		||||
    from tqdm import trange
 | 
			
		||||
 | 
			
		||||
    for y in trange(xy_max + 1):
 | 
			
		||||
        its: list[tuple[int, int]] = []
 | 
			
		||||
        for (sx, sy), (bx, by) in sensor_to_beacon.items():
 | 
			
		||||
            d = abs(sx - bx) + abs(sy - by)
 | 
			
		||||
            dx = d - abs(sy - y)
 | 
			
		||||
 | 
			
		||||
            if dx >= 0:
 | 
			
		||||
                its.append((max(0, sx - dx), min(sx + dx, xy_max)))
 | 
			
		||||
 | 
			
		||||
        its = sorted(its)
 | 
			
		||||
        _, e = its[0]
 | 
			
		||||
 | 
			
		||||
        for si, ei in its[1:]:
 | 
			
		||||
            if si > e + 1:
 | 
			
		||||
                return si - 1, y, 4_000_000 * (si - 1) + y
 | 
			
		||||
            if ei > e:
 | 
			
		||||
                e = ei
 | 
			
		||||
 | 
			
		||||
    return (0, 0, 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def part2_cplex(
 | 
			
		||||
    sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], xy_max: int
 | 
			
		||||
) -> tuple[int, int, int]:
 | 
			
		||||
    from docplex.mp.model import Model
 | 
			
		||||
 | 
			
		||||
    m = Model()
 | 
			
		||||
 | 
			
		||||
    x, y = m.continuous_var_list(2, ub=xy_max, name=["x", "y"])
 | 
			
		||||
 | 
			
		||||
    for (sx, sy), (bx, by) in sensor_to_beacon.items():
 | 
			
		||||
        d = abs(sx - bx) + abs(sy - by)
 | 
			
		||||
        m.add_constraint(m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}")
 | 
			
		||||
 | 
			
		||||
    m.set_objective("min", x + y)
 | 
			
		||||
 | 
			
		||||
    s = m.solve()
 | 
			
		||||
 | 
			
		||||
    vx = int(s.get_value(x))
 | 
			
		||||
    vy = int(s.get_value(y))
 | 
			
		||||
    return vx, vy, 4_000_000 * vx + vy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
sensor_to_beacon: dict[tuple[int, int], tuple[int, int]] = {}
 | 
			
		||||
 | 
			
		||||
for line in lines:
 | 
			
		||||
    r = parse.parse(
 | 
			
		||||
        "Sensor at x={sx}, y={sy}: closest beacon is at x={bx}, y={by}", line
 | 
			
		||||
    )
 | 
			
		||||
    sensor_to_beacon[int(r["sx"]), int(r["sy"])] = (int(r["bx"]), int(r["by"]))
 | 
			
		||||
 | 
			
		||||
xy_max = 4_000_000 if max(sensor_to_beacon) > (1_000, 0) else 20
 | 
			
		||||
row = 2_000_000 if max(sensor_to_beacon) > (1_000, 0) else 10
 | 
			
		||||
 | 
			
		||||
print(f"answer 1 is {part1(sensor_to_beacon, row)}")
 | 
			
		||||
 | 
			
		||||
# x, y, a2 = part2_cplex(sensor_to_beacon, xy_max)
 | 
			
		||||
x, y, a2 = part2_intervals(sensor_to_beacon, xy_max)
 | 
			
		||||
print(f"answer 2 is {a2} (x={x}, y={y})")
 | 
			
		||||
							
								
								
									
										158
									
								
								2022/day16.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								2022/day16.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
			
		||||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
import heapq
 | 
			
		||||
import itertools
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from typing import FrozenSet, NamedTuple
 | 
			
		||||
 | 
			
		||||
from tqdm import tqdm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Pipe(NamedTuple):
 | 
			
		||||
    name: str
 | 
			
		||||
    flow: int
 | 
			
		||||
    tunnels: list[str]
 | 
			
		||||
 | 
			
		||||
    def __lt__(self, other: object) -> bool:
 | 
			
		||||
        return isinstance(other, Pipe) and other.name < self.name
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other: object) -> bool:
 | 
			
		||||
        return isinstance(other, Pipe) and other.name == self.name
 | 
			
		||||
 | 
			
		||||
    def __hash__(self) -> int:
 | 
			
		||||
        return hash(self.name)
 | 
			
		||||
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
    def __repr__(self) -> str:
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def breadth_first_search(pipes: dict[str, Pipe], pipe: Pipe) -> dict[Pipe, int]:
 | 
			
		||||
    """
 | 
			
		||||
    Runs a BFS from the given pipe and return the shortest distance (in term of hops)
 | 
			
		||||
    to all other pipes.
 | 
			
		||||
    """
 | 
			
		||||
    queue = [(0, pipe_1)]
 | 
			
		||||
    visited = set()
 | 
			
		||||
    distances: dict[Pipe, int] = {}
 | 
			
		||||
 | 
			
		||||
    while len(distances) < len(pipes):
 | 
			
		||||
        distance, current = heapq.heappop(queue)
 | 
			
		||||
 | 
			
		||||
        if current in visited:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        visited.add(current)
 | 
			
		||||
        distances[current] = distance
 | 
			
		||||
 | 
			
		||||
        for tunnel in current.tunnels:
 | 
			
		||||
            heapq.heappush(queue, (distance + 1, pipes[tunnel]))
 | 
			
		||||
 | 
			
		||||
    return distances
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_with_better(
 | 
			
		||||
    node_at_times: dict[FrozenSet[Pipe], int], flow: int, flowing: FrozenSet[Pipe]
 | 
			
		||||
) -> None:
 | 
			
		||||
    node_at_times[flowing] = max(node_at_times[flowing], flow)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def part_1(
 | 
			
		||||
    start_pipe: Pipe,
 | 
			
		||||
    max_time: int,
 | 
			
		||||
    distances: dict[tuple[Pipe, Pipe], int],
 | 
			
		||||
    relevant_pipes: FrozenSet[Pipe],
 | 
			
		||||
):
 | 
			
		||||
    node_at_times: dict[int, dict[Pipe, dict[FrozenSet[Pipe], int]]] = defaultdict(
 | 
			
		||||
        lambda: defaultdict(lambda: defaultdict(lambda: 0))
 | 
			
		||||
    )
 | 
			
		||||
    node_at_times[0] = {start_pipe: {frozenset(): 0}}
 | 
			
		||||
 | 
			
		||||
    for time in range(max_time):
 | 
			
		||||
        for c_pipe, nodes in node_at_times[time].items():
 | 
			
		||||
            for flowing, flow in nodes.items():
 | 
			
		||||
                for target in relevant_pipes:
 | 
			
		||||
                    distance = distances[c_pipe, target] + 1
 | 
			
		||||
                    if time + distance >= max_time or target in flowing:
 | 
			
		||||
                        continue
 | 
			
		||||
 | 
			
		||||
                    update_with_better(
 | 
			
		||||
                        node_at_times[time + distance][target],
 | 
			
		||||
                        flow + sum(pipe.flow for pipe in flowing) * distance,
 | 
			
		||||
                        flowing | {target},
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                update_with_better(
 | 
			
		||||
                    node_at_times[max_time][c_pipe],
 | 
			
		||||
                    flow + sum(pipe.flow for pipe in flowing) * (max_time - time),
 | 
			
		||||
                    flowing,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    return max(
 | 
			
		||||
        flow
 | 
			
		||||
        for nodes_of_pipe in node_at_times[max_time].values()
 | 
			
		||||
        for flow in nodes_of_pipe.values()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def part_2(
 | 
			
		||||
    start_pipe: Pipe,
 | 
			
		||||
    max_time: int,
 | 
			
		||||
    distances: dict[tuple[Pipe, Pipe], int],
 | 
			
		||||
    relevant_pipes: FrozenSet[Pipe],
 | 
			
		||||
):
 | 
			
		||||
    def compute(pipes_for_me: FrozenSet[Pipe]) -> int:
 | 
			
		||||
        return part_1(start_pipe, max_time, distances, pipes_for_me) + part_1(
 | 
			
		||||
            start_pipe, max_time, distances, relevant_pipes - pipes_for_me
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    combs = [
 | 
			
		||||
        frozenset(relevant_pipes_1)
 | 
			
		||||
        for r in range(2, len(relevant_pipes) // 2 + 1)
 | 
			
		||||
        for relevant_pipes_1 in itertools.combinations(relevant_pipes, r)
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    return max(compute(comb) for comb in tqdm(combs))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# === MAIN ===
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pipes: dict[str, Pipe] = {}
 | 
			
		||||
for line in lines:
 | 
			
		||||
    r = re.match(
 | 
			
		||||
        R"Valve ([A-Z]+) has flow rate=([0-9]+); tunnels? leads? to valves? (.+)",
 | 
			
		||||
        line,
 | 
			
		||||
    )
 | 
			
		||||
    assert r
 | 
			
		||||
 | 
			
		||||
    g = r.groups()
 | 
			
		||||
 | 
			
		||||
    pipes[g[0]] = Pipe(g[0], int(g[1]), g[2].split(", "))
 | 
			
		||||
 | 
			
		||||
# compute distances from one valve to any other
 | 
			
		||||
distances: dict[tuple[Pipe, Pipe], int] = {}
 | 
			
		||||
for pipe_1 in pipes.values():
 | 
			
		||||
    distances.update(
 | 
			
		||||
        {
 | 
			
		||||
            (pipe_1, pipe_2): distance
 | 
			
		||||
            for pipe_2, distance in breadth_first_search(pipes, pipe_1).items()
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
# valves with flow
 | 
			
		||||
relevant_pipes = frozenset(pipe for pipe in pipes.values() if pipe.flow > 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# 1651, 1653
 | 
			
		||||
print(part_1(pipes["AA"], 30, distances, relevant_pipes))
 | 
			
		||||
 | 
			
		||||
# 1707, 2223
 | 
			
		||||
print(part_2(pipes["AA"], 26, distances, relevant_pipes))
 | 
			
		||||
							
								
								
									
										120
									
								
								2022/day17.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								2022/day17.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Sequence, TypeVar
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
T = TypeVar("T")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_tower(tower: np.ndarray, out: str = "#"):
 | 
			
		||||
    print("-" * (tower.shape[1] + 2))
 | 
			
		||||
    non_empty = False
 | 
			
		||||
    for row in reversed(range(1, tower.shape[0])):
 | 
			
		||||
        if not non_empty and not tower[row, :].any():
 | 
			
		||||
            continue
 | 
			
		||||
        non_empty = True
 | 
			
		||||
        print("|" + "".join(out if c else "." for c in tower[row, :]) + "|")
 | 
			
		||||
    print("+" + "-" * tower.shape[1] + "+")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def tower_height(tower: np.ndarray) -> int:
 | 
			
		||||
    return int(tower.shape[0] - tower[::-1, :].argmax(axis=0).min() - 1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def next_cycle(sequence: Sequence[T], index: int) -> tuple[T, int]:
 | 
			
		||||
    t = sequence[index]
 | 
			
		||||
    index = (index + 1) % len(sequence)
 | 
			
		||||
    return t, index
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ROCKS = [
 | 
			
		||||
    np.array([(0, 0), (0, 1), (0, 2), (0, 3)]),
 | 
			
		||||
    np.array([(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)]),
 | 
			
		||||
    np.array([(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]),
 | 
			
		||||
    np.array([(0, 0), (1, 0), (2, 0), (3, 0)]),
 | 
			
		||||
    np.array([(0, 0), (0, 1), (1, 0), (1, 1)]),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
WIDTH = 7
 | 
			
		||||
START_X = 2
 | 
			
		||||
 | 
			
		||||
EMPTY_BLOCKS = np.zeros((10, WIDTH), dtype=bool)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_tower(
 | 
			
		||||
    n_rocks: int,
 | 
			
		||||
    jets: str,
 | 
			
		||||
    early_stop: bool = False,
 | 
			
		||||
    init: np.ndarray = np.ones(WIDTH, dtype=bool),
 | 
			
		||||
) -> tuple[np.ndarray, int, int, dict[int, int]]:
 | 
			
		||||
    tower = EMPTY_BLOCKS.copy()
 | 
			
		||||
    tower[0, :] = init
 | 
			
		||||
 | 
			
		||||
    done_at: dict[tuple[int, int], int] = {}
 | 
			
		||||
    heights: dict[int, int] = {}
 | 
			
		||||
    i_jet, i_rock = 0, 0
 | 
			
		||||
    rock_count = 0
 | 
			
		||||
 | 
			
		||||
    for rock_count in range(n_rocks):
 | 
			
		||||
        if early_stop:
 | 
			
		||||
            if i_rock == 0 and (i_rock, i_jet) in done_at:
 | 
			
		||||
                break
 | 
			
		||||
            done_at[i_rock, i_jet] = rock_count
 | 
			
		||||
 | 
			
		||||
        y_start = tower.shape[0] - tower[::-1, :].argmax(axis=0).min() + 3
 | 
			
		||||
        rock, i_rock = next_cycle(ROCKS, i_rock)
 | 
			
		||||
 | 
			
		||||
        rock_y = rock[:, 0] + y_start
 | 
			
		||||
        rock_x = rock[:, 1] + START_X
 | 
			
		||||
 | 
			
		||||
        if rock_y.max() >= tower.shape[0]:
 | 
			
		||||
            tower = np.concatenate([tower, EMPTY_BLOCKS], axis=0)
 | 
			
		||||
 | 
			
		||||
        while True:
 | 
			
		||||
            jet, i_jet = next_cycle(jets, i_jet)
 | 
			
		||||
 | 
			
		||||
            dx = 0
 | 
			
		||||
            if jet == ">" and rock_x.max() < WIDTH - 1:
 | 
			
		||||
                dx = 1
 | 
			
		||||
            elif jet == "<" and rock_x.min() > 0:
 | 
			
		||||
                dx = -1
 | 
			
		||||
 | 
			
		||||
            if dx != 0 and not tower[rock_y, rock_x + dx].any():
 | 
			
		||||
                rock_x = rock_x + dx
 | 
			
		||||
 | 
			
		||||
            # move down
 | 
			
		||||
            rock_y -= 1
 | 
			
		||||
 | 
			
		||||
            if tower[rock_y, rock_x].any():
 | 
			
		||||
                rock_y += 1
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        heights[rock_count] = tower_height(tower)
 | 
			
		||||
        tower[rock_y, rock_x] = True
 | 
			
		||||
 | 
			
		||||
    return tower, rock_count, done_at.get((i_rock, i_jet), -1), heights
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
line = sys.stdin.read().strip()
 | 
			
		||||
 | 
			
		||||
tower, *_ = build_tower(2022, line)
 | 
			
		||||
answer_1 = tower_height(tower)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
TOTAL_ROCKS = 1_000_000_000_000
 | 
			
		||||
tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, line, True)
 | 
			
		||||
assert prev_1 > 0
 | 
			
		||||
 | 
			
		||||
# 2767 1513
 | 
			
		||||
remaining_rocks = TOTAL_ROCKS - n_rocks_1
 | 
			
		||||
n_repeat_rocks = n_rocks_1 - prev_1
 | 
			
		||||
n_repeat_towers = remaining_rocks // n_repeat_rocks
 | 
			
		||||
 | 
			
		||||
base_height = heights_1[prev_1]
 | 
			
		||||
repeat_height = heights_1[prev_1 + n_repeat_rocks - 1] - heights_1[prev_1]
 | 
			
		||||
remaining_height = (
 | 
			
		||||
    heights_1[prev_1 + remaining_rocks % n_repeat_rocks] - heights_1[prev_1]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
answer_2 = base_height + (n_repeat_towers + 1) * repeat_height + remaining_height
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										51
									
								
								2022/day18.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								2022/day18.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
import sys
 | 
			
		||||
from typing import FrozenSet
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
xyz = np.asarray(
 | 
			
		||||
    [
 | 
			
		||||
        tuple(int(x) for x in row.split(","))  # type: ignore
 | 
			
		||||
        for row in sys.stdin.read().splitlines()
 | 
			
		||||
    ]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
xyz = xyz - xyz.min(axis=0) + 1
 | 
			
		||||
 | 
			
		||||
cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool)
 | 
			
		||||
cubes[xyz[:, 0], xyz[:, 1], xyz[:, 2]] = True
 | 
			
		||||
 | 
			
		||||
n_dims = len(cubes.shape)
 | 
			
		||||
 | 
			
		||||
faces = [(-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1), (0, 0, 1)]
 | 
			
		||||
 | 
			
		||||
answer_1 = sum(
 | 
			
		||||
    1 for x, y, z in xyz for dx, dy, dz in faces if not cubes[x + dx, y + dy, z + dz]
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
visited = np.zeros_like(cubes, dtype=bool)
 | 
			
		||||
queue = [(0, 0, 0)]
 | 
			
		||||
 | 
			
		||||
n_faces = 0
 | 
			
		||||
while queue:
 | 
			
		||||
    x, y, z = queue.pop(0)
 | 
			
		||||
 | 
			
		||||
    if visited[x, y, z]:
 | 
			
		||||
        continue
 | 
			
		||||
 | 
			
		||||
    visited[x, y, z] = True
 | 
			
		||||
 | 
			
		||||
    for dx, dy, dz in faces:
 | 
			
		||||
        nx, ny, nz = x + dx, y + dy, z + dz
 | 
			
		||||
        if not all(n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))):
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if visited[nx, ny, nz]:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if cubes[nx, ny, nz]:
 | 
			
		||||
            n_faces += 1
 | 
			
		||||
        else:
 | 
			
		||||
            queue.append((nx, ny, nz))
 | 
			
		||||
print(f"answer 2 is {n_faces}")
 | 
			
		||||
							
								
								
									
										182
									
								
								2022/day19.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								2022/day19.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,182 @@
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Literal
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
import parse
 | 
			
		||||
from tqdm import tqdm
 | 
			
		||||
 | 
			
		||||
Reagent = Literal["ore", "clay", "obsidian", "geode"]
 | 
			
		||||
REAGENTS: tuple[Reagent, ...] = (
 | 
			
		||||
    "ore",
 | 
			
		||||
    "clay",
 | 
			
		||||
    "obsidian",
 | 
			
		||||
    "geode",
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
IntOfReagent = dict[Reagent, int]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class State:
 | 
			
		||||
    robots: IntOfReagent
 | 
			
		||||
    reagents: IntOfReagent
 | 
			
		||||
 | 
			
		||||
    def __init__(
 | 
			
		||||
        self,
 | 
			
		||||
        robots: IntOfReagent | None = None,
 | 
			
		||||
        reagents: IntOfReagent | None = None,
 | 
			
		||||
    ):
 | 
			
		||||
        if robots is None:
 | 
			
		||||
            assert reagents is None
 | 
			
		||||
            self.reagents = {reagent: 0 for reagent in REAGENTS}
 | 
			
		||||
            self.robots = {reagent: 0 for reagent in REAGENTS}
 | 
			
		||||
            self.robots["ore"] = 1
 | 
			
		||||
        else:
 | 
			
		||||
            assert robots is not None and reagents is not None
 | 
			
		||||
            self.robots = robots
 | 
			
		||||
            self.reagents = reagents
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other) -> bool:
 | 
			
		||||
        return (
 | 
			
		||||
            isinstance(other, State)
 | 
			
		||||
            and self.robots == other.robots
 | 
			
		||||
            and self.reagents == other.reagents
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def __hash__(self) -> int:
 | 
			
		||||
        return hash(tuple((self.robots[r], self.reagents[r]) for r in REAGENTS))
 | 
			
		||||
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        return "State({}, {})".format(
 | 
			
		||||
            "/".join(str(self.robots[k]) for k in REAGENTS),
 | 
			
		||||
            "/".join(str(self.reagents[k]) for k in REAGENTS),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def __repr__(self) -> str:
 | 
			
		||||
        return str(self)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def dominates(lhs: State, rhs: State):
 | 
			
		||||
    return all(
 | 
			
		||||
        lhs.robots[r] >= rhs.robots[r] and lhs.reagents[r] >= rhs.reagents[r]
 | 
			
		||||
        for r in REAGENTS
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
blueprints: list[dict[Reagent, IntOfReagent]] = []
 | 
			
		||||
for line in lines:
 | 
			
		||||
    r = parse.parse(
 | 
			
		||||
        "Blueprint {}: "
 | 
			
		||||
        "Each ore robot costs {:d} ore. "
 | 
			
		||||
        "Each clay robot costs {:d} ore. "
 | 
			
		||||
        "Each obsidian robot costs {:d} ore and {:d} clay. "
 | 
			
		||||
        "Each geode robot costs {:d} ore and {:d} obsidian.",
 | 
			
		||||
        line,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    blueprints.append(
 | 
			
		||||
        {
 | 
			
		||||
            "ore": {"ore": r[1]},
 | 
			
		||||
            "clay": {"ore": r[2]},
 | 
			
		||||
            "obsidian": {"ore": r[3], "clay": r[4]},
 | 
			
		||||
            "geode": {"ore": r[5], "obsidian": r[6]},
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
 | 
			
		||||
    # since we can only build one robot per time, we do not need more than X robots
 | 
			
		||||
    # of type K where X is the maximum number of K required among all robots, e.g.,
 | 
			
		||||
    # in the first toy blueprint, we need at most 4 ore robots, 14 clay ones and 7
 | 
			
		||||
    # obsidian ones
 | 
			
		||||
    maximums = {
 | 
			
		||||
        name: max(blueprint[r].get(name, 0) for r in REAGENTS) for name in REAGENTS
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state_after_t: dict[int, set[State]] = {0: [State()]}
 | 
			
		||||
 | 
			
		||||
    for t in range(1, max_time + 1):
 | 
			
		||||
        # list of new states at the end of step t that we are going to prune later
 | 
			
		||||
        states_for_t: set[State] = set()
 | 
			
		||||
 | 
			
		||||
        for state in state_after_t[t - 1]:
 | 
			
		||||
            robots_that_can_be_built = [
 | 
			
		||||
                robot
 | 
			
		||||
                for robot in REAGENTS
 | 
			
		||||
                if all(
 | 
			
		||||
                    state.reagents[reagent] >= blueprint[robot].get(reagent, 0)
 | 
			
		||||
                    for reagent in REAGENTS
 | 
			
		||||
                )
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
            states_for_t.add(
 | 
			
		||||
                State(
 | 
			
		||||
                    robots=state.robots,
 | 
			
		||||
                    reagents={
 | 
			
		||||
                        reagent: state.reagents[reagent] + state.robots[reagent]
 | 
			
		||||
                        for reagent in REAGENTS
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if "geode" in robots_that_can_be_built:
 | 
			
		||||
                robots_that_can_be_built = ["geode"]
 | 
			
		||||
            else:
 | 
			
		||||
                robots_that_can_be_built = [
 | 
			
		||||
                    robot
 | 
			
		||||
                    for robot in robots_that_can_be_built
 | 
			
		||||
                    if state.robots[robot] < maximums[robot]
 | 
			
		||||
                ]
 | 
			
		||||
 | 
			
		||||
            for robot in robots_that_can_be_built:
 | 
			
		||||
                robots = state.robots.copy()
 | 
			
		||||
                robots[robot] += 1
 | 
			
		||||
                reagents = {
 | 
			
		||||
                    reagent: state.reagents[reagent]
 | 
			
		||||
                    + state.robots[reagent]
 | 
			
		||||
                    - blueprint[robot].get(reagent, 0)
 | 
			
		||||
                    for reagent in REAGENTS
 | 
			
		||||
                }
 | 
			
		||||
                states_for_t.add(State(robots=robots, reagents=reagents))
 | 
			
		||||
 | 
			
		||||
        # use numpy to switch computation of dominated states -> store each state
 | 
			
		||||
        # as a 8 array and use numpy broadcasting to find dominated states
 | 
			
		||||
        states_after = np.asarray(list(states_for_t))
 | 
			
		||||
        np_states = np.array(
 | 
			
		||||
            [
 | 
			
		||||
                [state.robots[r] for r in REAGENTS]
 | 
			
		||||
                + [state.reagents[r] for r in REAGENTS]
 | 
			
		||||
                for state in states_after
 | 
			
		||||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        to_keep = []
 | 
			
		||||
        while len(np_states) > 0:
 | 
			
		||||
            first_dom = (np_states[1:] >= np_states[0]).all(axis=1).any()
 | 
			
		||||
 | 
			
		||||
            if first_dom:
 | 
			
		||||
                np_states = np_states[1:]
 | 
			
		||||
            else:
 | 
			
		||||
                to_keep.append(np_states[0])
 | 
			
		||||
                np_states = np_states[1:][~(np_states[1:] <= np_states[0]).all(axis=1)]
 | 
			
		||||
 | 
			
		||||
        state_after_t[t] = {
 | 
			
		||||
            State(
 | 
			
		||||
                robots=dict(zip(REAGENTS, row[:4])),
 | 
			
		||||
                reagents=dict(zip(REAGENTS, row[4:])),
 | 
			
		||||
            )
 | 
			
		||||
            for row in to_keep
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    return max(state.reagents["geode"] for state in state_after_t[max_time])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
answer_1 = sum(
 | 
			
		||||
    (i_blueprint + 1) * run(blueprint, 24)
 | 
			
		||||
    for i_blueprint, blueprint in enumerate(blueprints)
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
answer_2 = run(blueprints[0], 32) * run(blueprints[1], 32) * run(blueprints[2], 32)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										53
									
								
								2022/day2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								2022/day2.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def score_1(ux: int, vx: int) -> int:
 | 
			
		||||
    # here ux and vx are both moves: 0 = rock, 1 = paper, 2 = scissor
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    # 1. to get the score of the move/shape, we simply add 1 -> vx + 1
 | 
			
		||||
    # 2. to get the score of the outcome (loss/draw/win), we use the fact that the
 | 
			
		||||
    #    winning hand is always the opponent hand (ux) + 1 in modulo-3 arithmetic:
 | 
			
		||||
    #    - (ux - vx) % 3 gives us 0 for a draw, 1 for a loss and 2 for a win
 | 
			
		||||
    #    - 1 - ((ux - vx) % 3) gives us -1 for a win, 0 for a loss and 1 for a draw
 | 
			
		||||
    #    - (1 - ((ux - vx) % 3)) gives us 0 / 1 / 2 for loss / draw / win
 | 
			
		||||
    #    - the above can be rewritten as ((1 - (ux - vx)) % 3)
 | 
			
		||||
    #    we can then simply multiply this by 3 to get the outcome score
 | 
			
		||||
    #
 | 
			
		||||
    return (vx + 1) + ((1 - (ux - vx)) % 3) * 3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def score_2(ux: int, vx: int) -> int:
 | 
			
		||||
    # here ux is the opponent move (0 = rock, 1 = paper, 2 = scissor) and vx is the
 | 
			
		||||
    # outcome (0 = loss, 1 = draw, 2 = win)
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    # 1. to get the score to the move/shape, we need to find it (as 0, 1 or 2) and then
 | 
			
		||||
    #    add 1 to it
 | 
			
		||||
    #    - (vx - 1) gives the offset from the opponent shape (-1 for a loss, 0 for a
 | 
			
		||||
    #      draw and 1 for a win)
 | 
			
		||||
    #    - from the offset, we can retrieve the shape by adding the opponent shape and
 | 
			
		||||
    #      using modulo-3 arithmetic -> (ux + vx - 1) % 3
 | 
			
		||||
    #    - we then add 1 to get the final shape score
 | 
			
		||||
    # 2. to get the score of the outcome, we can simply multiply vx by 3 -> vx * 3
 | 
			
		||||
    return (ux + vx - 1) % 3 + 1 + vx * 3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.readlines()
 | 
			
		||||
 | 
			
		||||
# the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using
 | 
			
		||||
# modulo-3 arithmetic
 | 
			
		||||
#
 | 
			
		||||
# in modulo-3 arithmetic, the winning move is 1 + the opponent move (e.g., winning move
 | 
			
		||||
# if opponent plays 0 is 1, or 0 if opponent plays 2 (0 = (2 + 1 % 3)))
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# we read the lines in a Nx2 in array with value 0/1/2 instead of A/B/C or X/Y/Z for
 | 
			
		||||
# easier manipulation
 | 
			
		||||
values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines]
 | 
			
		||||
 | 
			
		||||
# part 1 - 13526
 | 
			
		||||
print(f"answer 1 is {sum(score_1(*v) for v in values)}")
 | 
			
		||||
 | 
			
		||||
# part 2 - 14204
 | 
			
		||||
print(f"answer 2 is {sum(score_2(*v) for v in values)}")
 | 
			
		||||
							
								
								
									
										74
									
								
								2022/day20.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								2022/day20.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Number:
 | 
			
		||||
    current: int
 | 
			
		||||
    value: int
 | 
			
		||||
 | 
			
		||||
    def __init__(self, value: int):
 | 
			
		||||
        self.current = 0
 | 
			
		||||
        self.value = value
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return str(self.value)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return str(self)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
 | 
			
		||||
    numbers = numbers.copy()
 | 
			
		||||
    original = numbers.copy()
 | 
			
		||||
 | 
			
		||||
    for index, number in enumerate(numbers):
 | 
			
		||||
        number.current = index
 | 
			
		||||
 | 
			
		||||
    for _ in range(rounds):
 | 
			
		||||
        for number in original:
 | 
			
		||||
            index = number.current
 | 
			
		||||
            offset = (number.value * key) % (len(numbers) - 1)
 | 
			
		||||
            target = index + offset
 | 
			
		||||
 | 
			
		||||
            # need to wrap
 | 
			
		||||
            if target >= len(numbers):
 | 
			
		||||
                target = offset - (len(numbers) - index) + 1
 | 
			
		||||
 | 
			
		||||
                for number_2 in numbers[target:index]:
 | 
			
		||||
                    number_2.current += 1
 | 
			
		||||
 | 
			
		||||
                numbers = (
 | 
			
		||||
                    numbers[:target]
 | 
			
		||||
                    + [number]
 | 
			
		||||
                    + numbers[target:index]
 | 
			
		||||
                    + numbers[index + 1 :]
 | 
			
		||||
                )
 | 
			
		||||
            else:
 | 
			
		||||
                for number_2 in numbers[index : target + 1]:
 | 
			
		||||
                    number_2.current -= 1
 | 
			
		||||
 | 
			
		||||
                numbers = (
 | 
			
		||||
                    numbers[:index]
 | 
			
		||||
                    + numbers[index + 1 : target + 1]
 | 
			
		||||
                    + [number]
 | 
			
		||||
                    + numbers[target + 1 :]
 | 
			
		||||
                )
 | 
			
		||||
            number.current = target
 | 
			
		||||
 | 
			
		||||
    index_of_0 = next(
 | 
			
		||||
        filter(lambda index: numbers[index].value == 0, range(len(numbers)))
 | 
			
		||||
    )
 | 
			
		||||
    return sum(
 | 
			
		||||
        numbers[(index_of_0 + offset) % len(numbers)].value * key
 | 
			
		||||
        for offset in (1000, 2000, 3000)
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
numbers = [Number(int(x)) for i, x in enumerate(sys.stdin.readlines())]
 | 
			
		||||
 | 
			
		||||
answer_1 = decrypt(numbers, 1, 1)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
answer_2 = decrypt(numbers, 811589153, 10)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										107
									
								
								2022/day21.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								2022/day21.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
import operator
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Callable
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int:
 | 
			
		||||
    value = monkeys[monkey]
 | 
			
		||||
    if isinstance(value, int):
 | 
			
		||||
        return value
 | 
			
		||||
    else:
 | 
			
		||||
        op: dict[str, Callable[[int, int], int]] = {
 | 
			
		||||
            "+": operator.add,
 | 
			
		||||
            "-": operator.sub,
 | 
			
		||||
            "*": operator.mul,
 | 
			
		||||
            "/": operator.floordiv,
 | 
			
		||||
        }
 | 
			
		||||
        value = op[value[1]](compute(monkeys, value[0]), compute(monkeys, value[2]))
 | 
			
		||||
        monkeys[monkey] = value
 | 
			
		||||
        return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def invert(
 | 
			
		||||
    monkeys: dict[str, int | tuple[str, str, str]], monkey: str, target: int
 | 
			
		||||
) -> dict[str, int | tuple[str, str, str]]:
 | 
			
		||||
    """
 | 
			
		||||
    Revert the given mapping from monkey name to value or operation such that
 | 
			
		||||
    the value from 'monkey' is computable by inverting operation until the root is
 | 
			
		||||
    found.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        monkeys: Dictionary of monkeys, that will be updated and returned.
 | 
			
		||||
        monkey: Name of the monkey to start from.
 | 
			
		||||
        target: Target value to set for the monkey that depends on root.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        The given dictionary of monkeys.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    monkeys = monkeys.copy()
 | 
			
		||||
 | 
			
		||||
    depends: dict[str, str] = {}
 | 
			
		||||
    for m, v in monkeys.items():
 | 
			
		||||
        if isinstance(v, int):
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        op1, _, op2 = v
 | 
			
		||||
 | 
			
		||||
        assert op1 not in depends
 | 
			
		||||
        assert op2 not in depends
 | 
			
		||||
        depends[op1] = m
 | 
			
		||||
        depends[op2] = m
 | 
			
		||||
 | 
			
		||||
    invert_op = {"+": "-", "-": "+", "*": "/", "/": "*"}
 | 
			
		||||
 | 
			
		||||
    current = monkey
 | 
			
		||||
    while True:
 | 
			
		||||
        dep = depends[current]
 | 
			
		||||
 | 
			
		||||
        if dep == "root":
 | 
			
		||||
            monkeys[current] = target
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
        val = monkeys[dep]
 | 
			
		||||
        assert not isinstance(val, int)
 | 
			
		||||
 | 
			
		||||
        op1, ope, op2 = val
 | 
			
		||||
 | 
			
		||||
        if op1 == current:
 | 
			
		||||
            monkeys[current] = (dep, invert_op[ope], op2)
 | 
			
		||||
        elif ope in ("+", "*"):
 | 
			
		||||
            monkeys[current] = (dep, invert_op[ope], op1)
 | 
			
		||||
        else:
 | 
			
		||||
            monkeys[current] = (op1, ope, dep)
 | 
			
		||||
 | 
			
		||||
        current = dep
 | 
			
		||||
 | 
			
		||||
    return monkeys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
monkeys: dict[str, int | tuple[str, str, str]] = {}
 | 
			
		||||
 | 
			
		||||
op_monkeys: set[str] = set()
 | 
			
		||||
 | 
			
		||||
for line in lines:
 | 
			
		||||
    parts = line.split(":")
 | 
			
		||||
    name = parts[0].strip()
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        value = int(parts[1].strip())
 | 
			
		||||
        monkeys[name] = value
 | 
			
		||||
    except ValueError:
 | 
			
		||||
        op1, ope, op2 = parts[1].strip().split()
 | 
			
		||||
        monkeys[name] = (op1, ope, op2)
 | 
			
		||||
 | 
			
		||||
        op_monkeys.add(name)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
answer_1 = compute(monkeys.copy(), "root")
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# assume the second operand of 'root' can be computed, and the first one depends on
 | 
			
		||||
# humn, which is the case is my input and the test input
 | 
			
		||||
p1, _, p2 = monkeys["root"]  # type: ignore
 | 
			
		||||
answer_2 = compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn")
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										223
									
								
								2022/day22.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								2022/day22.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Callable
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
VOID, EMPTY, WALL = 0, 1, 2
 | 
			
		||||
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
 | 
			
		||||
 | 
			
		||||
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
board_map_s, direction_s = sys.stdin.read().split("\n\n")
 | 
			
		||||
 | 
			
		||||
# board
 | 
			
		||||
board_lines = board_map_s.splitlines()
 | 
			
		||||
max_line = max(len(line) for line in board_lines)
 | 
			
		||||
board = np.array(
 | 
			
		||||
    [
 | 
			
		||||
        [TILE_FROM_CHAR[c] for c in row] + [VOID] * (max_line - len(row))
 | 
			
		||||
        for row in board_map_s.splitlines()
 | 
			
		||||
    ]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
directions = [
 | 
			
		||||
    int(p1) if p2 else p1 for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# find on each row and column the first and last non-void
 | 
			
		||||
row_first_non_void = np.argmax(board != VOID, axis=1)
 | 
			
		||||
row_last_non_void = board.shape[1] - np.argmax(board[:, ::-1] != VOID, axis=1) - 1
 | 
			
		||||
col_first_non_void = np.argmax(board != VOID, axis=0)
 | 
			
		||||
col_last_non_void = board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
faces = np.zeros_like(board)
 | 
			
		||||
size = np.gcd(board.shape[0], board.shape[1])
 | 
			
		||||
for row in range(0, board.shape[0], size):
 | 
			
		||||
    for col in range(row_first_non_void[row], row_last_non_void[row], size):
 | 
			
		||||
        faces[row : row + size, col : col + size] = faces.max() + 1
 | 
			
		||||
 | 
			
		||||
SIZE = np.gcd(*board.shape)
 | 
			
		||||
 | 
			
		||||
# TODO: deduce this from the actual cube...
 | 
			
		||||
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
 | 
			
		||||
 | 
			
		||||
if board.shape == (12, 16):  # example
 | 
			
		||||
    faces_wrap = {
 | 
			
		||||
        1: {
 | 
			
		||||
            "W": lambda y, x: (4, 4 + y, "S"),  # 3N
 | 
			
		||||
            "N": lambda y, x: (4, 11 - x, "S"),  # 2N
 | 
			
		||||
            "E": lambda y, x: (11 - y, 15, "W"),  # 6E
 | 
			
		||||
        },
 | 
			
		||||
        2: {
 | 
			
		||||
            "W": lambda y, x: (11, 19 - y, "N"),  # 6S
 | 
			
		||||
            "N": lambda y, x: (0, 11 - y, "S"),  # 1N
 | 
			
		||||
            "S": lambda y, x: (11, 11 - x, "N"),  # 5S
 | 
			
		||||
        },
 | 
			
		||||
        3: {
 | 
			
		||||
            "N": lambda y, x: (x - 4, 8, "E"),  # 1W
 | 
			
		||||
            "S": lambda y, x: (15 - x, 8, "E"),  # 5W
 | 
			
		||||
        },
 | 
			
		||||
        4: {"E": lambda y, x: (8, 19 - y, "S")},  # 6N
 | 
			
		||||
        5: {
 | 
			
		||||
            "W": lambda y, x: (7, 15 - y, "N"),  # 3S
 | 
			
		||||
            "S": lambda y, x: (7, 11 - x, "N"),  # 2S
 | 
			
		||||
        },
 | 
			
		||||
        6: {
 | 
			
		||||
            "N": lambda y, x: (19 - x, 11, "W"),  # 4E
 | 
			
		||||
            "E": lambda y, x: (11 - y, 11, "W"),  # 1E
 | 
			
		||||
            "S": lambda y, x: (19 - x, 0, "E"),  # 2W
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
else:
 | 
			
		||||
    faces_wrap = {
 | 
			
		||||
        1: {
 | 
			
		||||
            "W": lambda y, x: (3 * SIZE - y - 1, 0, "E"),  # 4W
 | 
			
		||||
            "N": lambda y, x: (2 * SIZE + x, 0, "E"),  # 6W
 | 
			
		||||
        },
 | 
			
		||||
        2: {
 | 
			
		||||
            "N": lambda y, x: (4 * SIZE - 1, x - 2 * SIZE, "N"),  # 6S
 | 
			
		||||
            "E": lambda y, x: (3 * SIZE - y - 1, 2 * SIZE - 1, "W"),  # 5E
 | 
			
		||||
            "S": lambda y, x: (x - SIZE, 2 * SIZE - 1, "W"),  # 3E
 | 
			
		||||
        },
 | 
			
		||||
        3: {
 | 
			
		||||
            "W": lambda y, x: (2 * SIZE, y - SIZE, "S"),  # 4N
 | 
			
		||||
            "E": lambda y, x: (SIZE - 1, SIZE + y, "N"),  # 2S
 | 
			
		||||
        },
 | 
			
		||||
        4: {
 | 
			
		||||
            "W": lambda y, x: (3 * SIZE - y - 1, SIZE, "E"),  # 1W
 | 
			
		||||
            "N": lambda y, x: (SIZE + x, SIZE, "E"),  # 3W
 | 
			
		||||
        },
 | 
			
		||||
        5: {
 | 
			
		||||
            "E": lambda y, x: (3 * SIZE - y - 1, 3 * SIZE - 1, "W"),  # 2E
 | 
			
		||||
            "S": lambda y, x: (2 * SIZE + x, SIZE - 1, "W"),  # 6E
 | 
			
		||||
        },
 | 
			
		||||
        6: {
 | 
			
		||||
            "W": lambda y, x: (0, y - 2 * SIZE, "S"),  # 1N
 | 
			
		||||
            "E": lambda y, x: (3 * SIZE - 1, y - 2 * SIZE, "N"),  # 5S
 | 
			
		||||
            "S": lambda y, x: (0, x + 2 * SIZE, "S"),  # 2N
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
 | 
			
		||||
    if r0 == "E":
 | 
			
		||||
        return y0, row_first_non_void[y0], r0
 | 
			
		||||
    elif r0 == "S":
 | 
			
		||||
        return col_first_non_void[x0], x0, r0
 | 
			
		||||
    elif r0 == "W":
 | 
			
		||||
        return y0, row_last_non_void[y0], r0
 | 
			
		||||
    elif r0 == "N":
 | 
			
		||||
        return col_last_non_void[x0], x0, r0
 | 
			
		||||
 | 
			
		||||
    assert False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
 | 
			
		||||
    cube = faces[y0, x0]
 | 
			
		||||
    assert r0 in faces_wrap[cube]
 | 
			
		||||
    return faces_wrap[cube][r0](y0, x0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run(wrap: Callable[[int, int, str], tuple[int, int, str]]) -> tuple[int, int, str]:
 | 
			
		||||
    y0 = 0
 | 
			
		||||
    x0 = np.where(board[0] == EMPTY)[0][0]
 | 
			
		||||
    r0 = "E"
 | 
			
		||||
 | 
			
		||||
    for direction in directions:
 | 
			
		||||
        if isinstance(direction, int):
 | 
			
		||||
            while direction > 0:
 | 
			
		||||
                if r0 == "E":
 | 
			
		||||
                    xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
 | 
			
		||||
                    if len(xi):
 | 
			
		||||
                        x0 = x0 + xi[0]
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    elif (
 | 
			
		||||
                        x0 + direction < board.shape[1]
 | 
			
		||||
                        and board[y0, x0 + direction] == EMPTY
 | 
			
		||||
                    ):
 | 
			
		||||
                        x0 = x0 + direction
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    else:
 | 
			
		||||
                        y0_t, x0_t, r0_t = wrap(y0, x0, r0)
 | 
			
		||||
                        if board[y0_t, x0_t] == WALL:
 | 
			
		||||
                            x0 = row_last_non_void[y0]
 | 
			
		||||
                            direction = 0
 | 
			
		||||
                        else:
 | 
			
		||||
                            direction = direction - (row_last_non_void[y0] - x0) - 1
 | 
			
		||||
                            y0, x0, r0 = y0_t, x0_t, r0_t
 | 
			
		||||
                elif r0 == "S":
 | 
			
		||||
                    yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
 | 
			
		||||
                    if len(yi):
 | 
			
		||||
                        y0 = y0 + yi[0]
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    elif (
 | 
			
		||||
                        y0 + direction < board.shape[0]
 | 
			
		||||
                        and board[y0 + direction, x0] == EMPTY
 | 
			
		||||
                    ):
 | 
			
		||||
                        y0 = y0 + direction
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    else:
 | 
			
		||||
                        y0_t, x0_t, r0_t = wrap(y0, x0, r0)
 | 
			
		||||
                        if board[y0_t, x0_t] == WALL:
 | 
			
		||||
                            y0 = col_last_non_void[x0]
 | 
			
		||||
                            direction = 0
 | 
			
		||||
                        else:
 | 
			
		||||
                            direction = direction - (col_last_non_void[x0] - y0) - 1
 | 
			
		||||
                            y0, x0, r0 = y0_t, x0_t, r0_t
 | 
			
		||||
                elif r0 == "W":
 | 
			
		||||
                    left = max(x0 - direction - 1, 0)
 | 
			
		||||
                    xi = np.where(board[y0, left:x0] == WALL)[0]
 | 
			
		||||
                    if len(xi):
 | 
			
		||||
                        x0 = left + xi[-1] + 1
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
 | 
			
		||||
                        x0 = x0 - direction
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    else:
 | 
			
		||||
                        y0_t, x0_t, r0_t = wrap(y0, x0, r0)
 | 
			
		||||
                        if board[y0_t, x0_t] == WALL:
 | 
			
		||||
                            x0 = row_first_non_void[y0]
 | 
			
		||||
                            direction = 0
 | 
			
		||||
                        else:
 | 
			
		||||
                            direction = direction - (x0 - row_first_non_void[y0]) - 1
 | 
			
		||||
                            y0, x0, r0 = y0_t, x0_t, r0_t
 | 
			
		||||
                elif r0 == "N":
 | 
			
		||||
                    top = max(y0 - direction - 1, 0)
 | 
			
		||||
                    yi = np.where(board[top:y0, x0] == WALL)[0]
 | 
			
		||||
                    if len(yi):
 | 
			
		||||
                        y0 = top + yi[-1] + 1
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
 | 
			
		||||
                        y0 = y0 - direction
 | 
			
		||||
                        direction = 0
 | 
			
		||||
                    else:
 | 
			
		||||
                        y0_t, x0_t, r0_t = wrap(y0, x0, r0)
 | 
			
		||||
                        if board[y0_t, x0_t] == WALL:
 | 
			
		||||
                            y0 = col_first_non_void[x0]
 | 
			
		||||
                            direction = 0
 | 
			
		||||
                        else:
 | 
			
		||||
                            direction = direction - (y0 - col_first_non_void[x0]) - 1
 | 
			
		||||
                            y0, x0, r0 = y0_t, x0_t, r0_t
 | 
			
		||||
        else:
 | 
			
		||||
            r0 = {
 | 
			
		||||
                "E": {"L": "N", "R": "S"},
 | 
			
		||||
                "N": {"L": "W", "R": "E"},
 | 
			
		||||
                "W": {"L": "S", "R": "N"},
 | 
			
		||||
                "S": {"L": "E", "R": "W"},
 | 
			
		||||
            }[r0][direction]
 | 
			
		||||
 | 
			
		||||
    return y0, x0, r0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
y1, x1, r1 = run(wrap_part_1)
 | 
			
		||||
answer_1 = 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
y2, x2, r2 = run(wrap_part_2)
 | 
			
		||||
answer_2 = 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										103
									
								
								2022/day23.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								2022/day23.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
import itertools
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
 | 
			
		||||
Directions = list[
 | 
			
		||||
    tuple[
 | 
			
		||||
        str, tuple[int, int], tuple[tuple[int, int], tuple[int, int], tuple[int, int]]
 | 
			
		||||
    ]
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
# (Y, X)
 | 
			
		||||
DIRECTIONS: Directions = [
 | 
			
		||||
    ("N", (-1, 0), ((-1, -1), (-1, 0), (-1, 1))),
 | 
			
		||||
    ("S", (1, 0), ((1, -1), (1, 0), (1, 1))),
 | 
			
		||||
    ("W", (0, -1), ((-1, -1), (0, -1), (1, -1))),
 | 
			
		||||
    ("E", (0, 1), ((-1, 1), (0, 1), (1, 1))),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def min_max_yx(positions: set[tuple[int, int]]) -> tuple[int, int, int, int]:
 | 
			
		||||
    ys, xs = {y for y, x in positions}, {x for y, x in positions}
 | 
			
		||||
    return min(ys), min(xs), max(ys), max(xs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_positions(positions: set[tuple[int, int]]):
 | 
			
		||||
    min_y, min_x, max_y, max_x = min_max_yx(positions)
 | 
			
		||||
    print(
 | 
			
		||||
        "\n".join(
 | 
			
		||||
            "".join(
 | 
			
		||||
                "#" if (y, x) in positions else "." for x in range(min_x - 1, max_x + 2)
 | 
			
		||||
            )
 | 
			
		||||
            for y in range(min_y - 1, max_y + 2)
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def round(
 | 
			
		||||
    positions: set[tuple[int, int]],
 | 
			
		||||
    directions: Directions,
 | 
			
		||||
):
 | 
			
		||||
    to_move: dict[tuple[int, int], list[tuple[int, int]]] = defaultdict(lambda: [])
 | 
			
		||||
    for y, x in positions:
 | 
			
		||||
        elves = {
 | 
			
		||||
            (dy, dx): (y + dy, x + dx) in positions
 | 
			
		||||
            for dy, dx in itertools.product((-1, 0, 1), (-1, 0, 1))
 | 
			
		||||
            if (dy, dx) != (0, 0)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if not any(elves.values()):
 | 
			
		||||
            to_move[y, x].append((y, x))
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        found: str | None = None
 | 
			
		||||
        for d, (dy, dx), d_yx_check in directions:
 | 
			
		||||
            if not any(elves[dy, dx] for dy, dx in d_yx_check):
 | 
			
		||||
                found = d
 | 
			
		||||
                to_move[y + dy, x + dx].append((y, x))
 | 
			
		||||
                break
 | 
			
		||||
        if found is None:
 | 
			
		||||
            to_move[y, x].append((y, x))
 | 
			
		||||
 | 
			
		||||
    positions.clear()
 | 
			
		||||
    for ty, tx in to_move:
 | 
			
		||||
        if len(to_move[ty, tx]) > 1:
 | 
			
		||||
            positions.update(to_move[ty, tx])
 | 
			
		||||
        else:
 | 
			
		||||
            positions.add((ty, tx))
 | 
			
		||||
 | 
			
		||||
    directions.append(directions.pop(0))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
POSITIONS = {
 | 
			
		||||
    (i, j)
 | 
			
		||||
    for i, row in enumerate(sys.stdin.read().splitlines())
 | 
			
		||||
    for j, col in enumerate(row)
 | 
			
		||||
    if col == "#"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# === part 1 ===
 | 
			
		||||
 | 
			
		||||
p1, d1 = POSITIONS.copy(), DIRECTIONS.copy()
 | 
			
		||||
for r in range(10):
 | 
			
		||||
    round(p1, d1)
 | 
			
		||||
 | 
			
		||||
min_y, min_x, max_y, max_x = min_max_yx(p1)
 | 
			
		||||
answer_1 = sum(
 | 
			
		||||
    (y, x) not in p1 for y in range(min_y, max_y + 1) for x in range(min_x, max_x + 1)
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# === part 2 ===
 | 
			
		||||
 | 
			
		||||
p2, d2 = POSITIONS.copy(), DIRECTIONS.copy()
 | 
			
		||||
answer_2 = 0
 | 
			
		||||
while True:
 | 
			
		||||
    answer_2 += 1
 | 
			
		||||
    backup = p2.copy()
 | 
			
		||||
    round(p2, d2)
 | 
			
		||||
 | 
			
		||||
    if backup == p2:
 | 
			
		||||
        break
 | 
			
		||||
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										98
									
								
								2022/day24.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								2022/day24.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
import heapq
 | 
			
		||||
import math
 | 
			
		||||
import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
winds = {
 | 
			
		||||
    (i - 1, j - 1, lines[i][j])
 | 
			
		||||
    for i in range(1, len(lines) - 1)
 | 
			
		||||
    for j in range(1, len(lines[i]) - 1)
 | 
			
		||||
    if lines[i][j] != "."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2
 | 
			
		||||
CYCLE = math.lcm(n_rows, n_cols)
 | 
			
		||||
 | 
			
		||||
east_winds = [{j for j in range(n_cols) if (i, j, ">") in winds} for i in range(n_rows)]
 | 
			
		||||
west_winds = [{j for j in range(n_cols) if (i, j, "<") in winds} for i in range(n_rows)]
 | 
			
		||||
north_winds = [
 | 
			
		||||
    {i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols)
 | 
			
		||||
]
 | 
			
		||||
south_winds = [
 | 
			
		||||
    {i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols)
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]):
 | 
			
		||||
    def heuristic(y: int, x: int) -> int:
 | 
			
		||||
        return abs(end[0] - y) + abs(end[1] - x)
 | 
			
		||||
 | 
			
		||||
    # (distance + heuristic, distance, (start_pos, cycle))
 | 
			
		||||
    queue = [(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))]
 | 
			
		||||
    visited: set[tuple[tuple[int, int], int]] = set()
 | 
			
		||||
    distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {})
 | 
			
		||||
 | 
			
		||||
    while queue:
 | 
			
		||||
        _, distance, ((y, x), cycle) = heapq.heappop(queue)
 | 
			
		||||
 | 
			
		||||
        if ((y, x), cycle) in visited:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        distances[y, x][cycle] = distance
 | 
			
		||||
 | 
			
		||||
        visited.add(((y, x), cycle))
 | 
			
		||||
 | 
			
		||||
        if (y, x) == (end[0], end[1]):
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
        for dy, dx in (0, 0), (-1, 0), (1, 0), (0, -1), (0, 1):
 | 
			
		||||
            ty = y + dy
 | 
			
		||||
            tx = x + dx
 | 
			
		||||
 | 
			
		||||
            n_cycle = (cycle + 1) % CYCLE
 | 
			
		||||
 | 
			
		||||
            if (ty, tx) == end:
 | 
			
		||||
                heapq.heappush(queue, (distance + 1, distance + 1, ((ty, tx), n_cycle)))
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
            if ((ty, tx), n_cycle) in visited:
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            if (ty, tx) != start and (ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols):
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            if (ty, tx) != start:
 | 
			
		||||
                if (ty - n_cycle) % n_rows in south_winds[tx]:
 | 
			
		||||
                    continue
 | 
			
		||||
                if (ty + n_cycle) % n_rows in north_winds[tx]:
 | 
			
		||||
                    continue
 | 
			
		||||
                if (tx + n_cycle) % n_cols in west_winds[ty]:
 | 
			
		||||
                    continue
 | 
			
		||||
                if (tx - n_cycle) % n_cols in east_winds[ty]:
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
            heapq.heappush(
 | 
			
		||||
                queue,
 | 
			
		||||
                ((heuristic(ty, tx) + distance + 1, distance + 1, ((ty, tx), n_cycle))),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    return distances, next(iter(distances[end].values()))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
start = (
 | 
			
		||||
    -1,
 | 
			
		||||
    next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1,
 | 
			
		||||
)
 | 
			
		||||
end = (
 | 
			
		||||
    n_rows,
 | 
			
		||||
    next(j for j in range(1, len(lines[-1]) - 1) if lines[-1][j] == ".") - 1,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
distances_1, forward_1 = run(start, 0, end)
 | 
			
		||||
print(f"answer 1 is {forward_1}")
 | 
			
		||||
 | 
			
		||||
distances_2, return_1 = run(end, next(iter(distances_1[end].keys())), start)
 | 
			
		||||
distances_3, forward_2 = run(start, next(iter(distances_2[start].keys())), end)
 | 
			
		||||
print(f"answer 2 is {forward_1 + return_1 + forward_2}")
 | 
			
		||||
							
								
								
									
										27
									
								
								2022/day25.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								2022/day25.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
coeffs = {"2": 2, "1": 1, "0": 0, "-": -1, "=": -2}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def snafu2number(number: str) -> int:
 | 
			
		||||
    value = 0
 | 
			
		||||
    for c in number:
 | 
			
		||||
        value *= 5
 | 
			
		||||
        value += coeffs[c]
 | 
			
		||||
    return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def number2snafu(number: int) -> str:
 | 
			
		||||
    values = ["0", "1", "2", "=", "-"]
 | 
			
		||||
    res = ""
 | 
			
		||||
    while number > 0:
 | 
			
		||||
        mod = number % 5
 | 
			
		||||
        res = res + values[mod]
 | 
			
		||||
        number = number // 5 + int(mod >= 3)
 | 
			
		||||
    return "".join(reversed(res))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
answer_1 = number2snafu(sum(map(snafu2number, lines)))
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
							
								
								
									
										23
									
								
								2022/day3.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								2022/day3.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
import string
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
lines = [line.strip() for line in sys.stdin.readlines()]
 | 
			
		||||
 | 
			
		||||
# extract content of each part
 | 
			
		||||
parts = [(set(line[: len(line) // 2]), set(line[len(line) // 2 :])) for line in lines]
 | 
			
		||||
 | 
			
		||||
# priorities
 | 
			
		||||
priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)}
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
part1 = sum(priorities[c] for p1, p2 in parts for c in p1.intersection(p2))
 | 
			
		||||
print(f"answer 1 is {part1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
n_per_group = 3
 | 
			
		||||
part2 = sum(
 | 
			
		||||
    priorities[c]
 | 
			
		||||
    for i in range(0, len(lines), n_per_group)
 | 
			
		||||
    for c in set(lines[i]).intersection(*lines[i + 1 : i + n_per_group])
 | 
			
		||||
)
 | 
			
		||||
print(f"answer 2 is {part2}")
 | 
			
		||||
							
								
								
									
										17
									
								
								2022/day4.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								2022/day4.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
lines = [line.strip() for line in sys.stdin.readlines()]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_range(value: str) -> set[int]:
 | 
			
		||||
    parts = value.split("-")
 | 
			
		||||
    return set(range(int(parts[0]), int(parts[1]) + 1))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sections = [tuple(make_range(part) for part in line.split(",")) for line in lines]
 | 
			
		||||
 | 
			
		||||
answer_1 = sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
answer_2 = sum(bool(s1.intersection(s2)) for s1, s2 in sections)
 | 
			
		||||
print(f"answer 1 is {answer_2}")
 | 
			
		||||
							
								
								
									
										41
									
								
								2022/day5.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								2022/day5.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
import copy
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
blocks_s, moves_s = (part.splitlines() for part in sys.stdin.read().split("\n\n"))
 | 
			
		||||
 | 
			
		||||
blocks: dict[str, list[str]] = {stack: [] for stack in blocks_s[-1].split()}
 | 
			
		||||
 | 
			
		||||
# this codes assumes that the lines are regular, i.e., 4 characters per "crate" in the
 | 
			
		||||
# form of '[X] ' (including the trailing space)
 | 
			
		||||
#
 | 
			
		||||
for block in blocks_s[-2::-1]:
 | 
			
		||||
    for stack, index in zip(blocks, range(0, len(block), 4)):
 | 
			
		||||
        crate = block[index + 1 : index + 2].strip()
 | 
			
		||||
 | 
			
		||||
        if crate:
 | 
			
		||||
            blocks[stack].append(crate)
 | 
			
		||||
 | 
			
		||||
# part 1 - deep copy for part 2
 | 
			
		||||
blocks_1 = copy.deepcopy(blocks)
 | 
			
		||||
 | 
			
		||||
for move in moves_s:
 | 
			
		||||
    _, count_s, _, from_, _, to_ = move.strip().split()
 | 
			
		||||
 | 
			
		||||
    for _i in range(int(count_s)):
 | 
			
		||||
        blocks_1[to_].append(blocks_1[from_].pop())
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
blocks_2 = copy.deepcopy(blocks)
 | 
			
		||||
 | 
			
		||||
for move in moves_s:
 | 
			
		||||
    _, count_s, _, from_, _, to_ = move.strip().split()
 | 
			
		||||
    count = int(count_s)
 | 
			
		||||
 | 
			
		||||
    blocks_2[to_].extend(blocks_2[from_][-count:])
 | 
			
		||||
    del blocks_2[from_][-count:]
 | 
			
		||||
 | 
			
		||||
answer_1 = "".join(s[-1] for s in blocks_1.values())
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
answer_2 = "".join(s[-1] for s in blocks_2.values())
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										15
									
								
								2022/day6.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								2022/day6.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def index_of_first_n_differents(data: str, n: int) -> int:
 | 
			
		||||
    for i in range(len(data)):
 | 
			
		||||
        if len(set(data[i : i + n])) == n:
 | 
			
		||||
            return i + n
 | 
			
		||||
    return -1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
data = sys.stdin.read().strip()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
print(f"answer 1 is {index_of_first_n_differents(data, 4)}")
 | 
			
		||||
print(f"answer 2 is {index_of_first_n_differents(data, 14)}")
 | 
			
		||||
							
								
								
									
										80
									
								
								2022/day7.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								2022/day7.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
import sys
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# we are going to use Path to create path and go up/down in the file tree since it
 | 
			
		||||
# implements everything we need
 | 
			
		||||
#
 | 
			
		||||
# we can use .resolve() to get normalized path, although this will add C:\ to all paths
 | 
			
		||||
# on Windows but that is not an issue since only the sizes matter
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# mapping from path to list of files or directories
 | 
			
		||||
trees: dict[Path, list[Path]] = {}
 | 
			
		||||
 | 
			
		||||
# mapping from paths to either size (for file) or -1 for directory
 | 
			
		||||
sizes: dict[Path, int] = {}
 | 
			
		||||
 | 
			
		||||
# first line must be a cd otherwise we have no idea where we are
 | 
			
		||||
assert lines[0].startswith("$ cd")
 | 
			
		||||
base_path = Path(lines[0].strip("$").split()[1]).resolve()
 | 
			
		||||
cur_path = base_path
 | 
			
		||||
 | 
			
		||||
trees[cur_path] = []
 | 
			
		||||
sizes[cur_path] = -1
 | 
			
		||||
 | 
			
		||||
for line in lines[1:]:
 | 
			
		||||
    # command
 | 
			
		||||
    if line.startswith("$"):
 | 
			
		||||
        parts = line.strip("$").strip().split()
 | 
			
		||||
        command = parts[0]
 | 
			
		||||
 | 
			
		||||
        if command == "cd":
 | 
			
		||||
            cur_path = cur_path.joinpath(parts[1]).resolve()
 | 
			
		||||
 | 
			
		||||
            # just initialize the lis of files if not already done
 | 
			
		||||
            if cur_path not in trees:
 | 
			
		||||
                trees[cur_path] = []
 | 
			
		||||
        else:
 | 
			
		||||
            # nothing to do here
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    # fill the current path
 | 
			
		||||
    else:
 | 
			
		||||
        parts = line.split()
 | 
			
		||||
        name: str = parts[1]
 | 
			
		||||
        if line.startswith("dir"):
 | 
			
		||||
            size = -1
 | 
			
		||||
        else:
 | 
			
		||||
            size = int(parts[0])
 | 
			
		||||
 | 
			
		||||
        path = cur_path.joinpath(name)
 | 
			
		||||
        trees[cur_path].append(path)
 | 
			
		||||
        sizes[path] = size
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def compute_size(path: Path) -> int:
 | 
			
		||||
    size = sizes[path]
 | 
			
		||||
 | 
			
		||||
    if size >= 0:
 | 
			
		||||
        return size
 | 
			
		||||
 | 
			
		||||
    return sum(compute_size(sub) for sub in trees[path])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
acc_sizes = {path: compute_size(path) for path in trees}
 | 
			
		||||
 | 
			
		||||
# part 1
 | 
			
		||||
answer_1 = sum(size for size in acc_sizes.values() if size <= 100_000)
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
# part 2
 | 
			
		||||
total_space = 70_000_000
 | 
			
		||||
update_space = 30_000_000
 | 
			
		||||
free_space = total_space - acc_sizes[base_path]
 | 
			
		||||
 | 
			
		||||
to_free_space = update_space - free_space
 | 
			
		||||
 | 
			
		||||
answer_2 = min(size for size in acc_sizes.values() if size >= to_free_space)
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										53
									
								
								2022/day8.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								2022/day8.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
from numpy.typing import NDArray
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
trees = np.array([[int(x) for x in row] for row in lines])
 | 
			
		||||
 | 
			
		||||
# answer 1
 | 
			
		||||
highest_trees = np.ones(trees.shape + (4,), dtype=int) * -1
 | 
			
		||||
highest_trees[1:-1, 1:-1] = [
 | 
			
		||||
    [
 | 
			
		||||
        [
 | 
			
		||||
            trees[:i, j].max(),
 | 
			
		||||
            trees[i + 1 :, j].max(),
 | 
			
		||||
            trees[i, :j].max(),
 | 
			
		||||
            trees[i, j + 1 :].max(),
 | 
			
		||||
        ]
 | 
			
		||||
        for j in range(1, trees.shape[1] - 1)
 | 
			
		||||
    ]
 | 
			
		||||
    for i in range(1, trees.shape[0] - 1)
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
answer_1 = (highest_trees.min(axis=2) < trees).sum()
 | 
			
		||||
print(f"answer 1 is {answer_1}")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def viewing_distance(row_of_trees: NDArray[np.int_], value: int) -> int:
 | 
			
		||||
    w = np.where(row_of_trees >= value)[0]
 | 
			
		||||
 | 
			
		||||
    if not w.size:
 | 
			
		||||
        return len(row_of_trees)
 | 
			
		||||
 | 
			
		||||
    return w[0] + 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# answer 2
 | 
			
		||||
v_distances = np.zeros(trees.shape + (4,), dtype=int)
 | 
			
		||||
v_distances[1:-1, 1:-1, :] = [
 | 
			
		||||
    [
 | 
			
		||||
        [
 | 
			
		||||
            viewing_distance(trees[i - 1 :: -1, j], trees[i, j]),
 | 
			
		||||
            viewing_distance(trees[i, j - 1 :: -1], trees[i, j]),
 | 
			
		||||
            viewing_distance(trees[i, j + 1 :], trees[i, j]),
 | 
			
		||||
            viewing_distance(trees[i + 1 :, j], trees[i, j]),
 | 
			
		||||
        ]
 | 
			
		||||
        for j in range(1, trees.shape[1] - 1)
 | 
			
		||||
    ]
 | 
			
		||||
    for i in range(1, trees.shape[0] - 1)
 | 
			
		||||
]
 | 
			
		||||
answer_2 = np.prod(v_distances, axis=2).max()
 | 
			
		||||
print(f"answer 2 is {answer_2}")
 | 
			
		||||
							
								
								
									
										59
									
								
								2022/day9.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								2022/day9.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def move(head: tuple[int, int], command: str) -> tuple[int, int]:
 | 
			
		||||
    h_col, h_row = head
 | 
			
		||||
 | 
			
		||||
    if command == "L":
 | 
			
		||||
        head = (h_col - 1, h_row)
 | 
			
		||||
    elif command == "R":
 | 
			
		||||
        head = (h_col + 1, h_row)
 | 
			
		||||
    elif command == "U":
 | 
			
		||||
        head = (h_col, h_row + 1)
 | 
			
		||||
    elif command == "D":
 | 
			
		||||
        head = (h_col, h_row - 1)
 | 
			
		||||
 | 
			
		||||
    return head
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def follow(head: tuple[int, int], tail: tuple[int, int]) -> tuple[int, int]:
 | 
			
		||||
    h_col, h_row = head
 | 
			
		||||
    t_col, t_row = tail
 | 
			
		||||
 | 
			
		||||
    if abs(t_col - h_col) <= 1 and abs(t_row - h_row) <= 1:
 | 
			
		||||
        return tail
 | 
			
		||||
 | 
			
		||||
    return t_col + np.sign(h_col - t_col), t_row + np.sign(h_row - t_row)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run(commands: list[str], n_blocks: int) -> list[tuple[int, int]]:
 | 
			
		||||
    blocks: list[tuple[int, int]] = [(0, 0) for _ in range(n_blocks)]
 | 
			
		||||
    visited = [blocks[-1]]
 | 
			
		||||
 | 
			
		||||
    for command in commands:
 | 
			
		||||
        blocks[0] = move(blocks[0], command)
 | 
			
		||||
 | 
			
		||||
        for i in range(0, n_blocks - 1):
 | 
			
		||||
            blocks[i + 1] = follow(blocks[i], blocks[i + 1])
 | 
			
		||||
 | 
			
		||||
        visited.append(blocks[-1])
 | 
			
		||||
 | 
			
		||||
    return visited
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lines = sys.stdin.read().splitlines()
 | 
			
		||||
 | 
			
		||||
# flatten the commands
 | 
			
		||||
commands: list[str] = []
 | 
			
		||||
for line in lines:
 | 
			
		||||
    d, c = line.split()
 | 
			
		||||
    commands.extend(d * int(c))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
visited_1 = run(commands, n_blocks=2)
 | 
			
		||||
print(f"answer 1 is {len(set(visited_1))}")
 | 
			
		||||
 | 
			
		||||
visited_2 = run(commands, n_blocks=10)
 | 
			
		||||
print(f"answer 2 is {len(set(visited_2))}")
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user