Compare commits

...

100 commits

Author SHA1 Message Date
efa485c08c 2015: d25: ex2: add solution 2025-05-22 04:24:15 +01:00
fad5b0ba26 2015: d25: ex2: add input 2025-05-22 04:24:09 +01:00
6a8aa06859 2015: d25: ex1: add solution 2025-05-22 04:24:04 +01:00
65f558bf0e 2015: d25: ex1: add input 2025-05-22 04:23:54 +01:00
587896b43f 2015: d24: ex2: add solution 2025-05-22 04:00:02 +01:00
57b3f7bbf6 2015: d24: ex2: add input 2025-05-22 03:59:26 +01:00
a001f39ff0 2015: d24: ex1: add solution 2025-05-22 03:59:20 +01:00
e8c323465f 2015: d24: ex1: add input 2025-05-22 03:59:14 +01:00
3f1533b6e0 2015: d23: ex2: add solution 2025-05-22 03:08:05 +01:00
8abe651cf0 2015: d23: ex2: add input 2025-05-22 03:07:56 +01:00
5da03de585 2015: d23: ex1: add solution 2025-05-22 03:07:51 +01:00
a5fbfbbedf 2015: d23: ex1: add input 2025-05-22 03:07:43 +01:00
1ecb0bf7be 2015: d22: ex2: add solution 2025-05-22 02:44:26 +01:00
6d4fb1e418 2015: d22: ex2: add input 2025-05-22 02:44:22 +01:00
43018d1302 2015: d22: ex1: add solution 2025-05-22 02:44:17 +01:00
d045384d20 2015: d22: ex1: add input 2025-05-22 02:44:02 +01:00
6a11f30a2f 2015: d21: ex2: add solution 2025-05-22 01:11:01 +01:00
e3db77cae2 2015: d21: ex2: add input 2025-05-22 01:10:57 +01:00
d9406a4258 2015: d21: ex1: add solution 2025-05-22 01:10:52 +01:00
ae67526c40 2015: d21: ex1: add input 2025-05-22 01:10:46 +01:00
235f801f41 2015: d20: ex2: add solution 2025-05-22 00:44:09 +01:00
0259d9bbf7 2015: d20: ex2: add input 2025-05-22 00:43:59 +01:00
4c511702fc 2015: d20: ex1: add solution 2025-05-22 00:43:54 +01:00
8d739cd487 2015: d20: ex1: add input 2025-05-22 00:43:43 +01:00
54a04e458a 2015: d19: ex2: add solution 2025-05-22 00:24:09 +01:00
e4ffdd2bfb 2015: d19: ex2: add input 2025-05-22 00:23:59 +01:00
9d15c56597 2015: d19: ex1: add solution 2025-05-22 00:23:54 +01:00
e275f1f03c 2015: d19: ex1: add input 2025-05-22 00:23:47 +01:00
68d99c7890 2015: d18: ex2: add solution 2025-05-21 23:06:42 +01:00
ebf5f6307a 2015: d18: ex2: add input 2025-05-21 23:06:38 +01:00
03e99e9d07 2015: d18: ex1: add solution 2025-05-21 23:06:32 +01:00
c7bdbede80 2015: d18: ex1: add input 2025-05-21 23:06:21 +01:00
86cdf0c8b6 2015: d17: ex2: add solution 2025-05-21 22:26:44 +01:00
6b2144fd2e 2015: d17: ex2: add input 2025-05-21 22:26:30 +01:00
a6a126cc3d 2015: d17: ex1: add solution 2025-05-21 22:26:24 +01:00
89caeed157 2015: d17: ex1: add input 2025-05-21 22:25:32 +01:00
fc2cad488b 2015: d16: ex2: add solution 2025-05-21 22:19:08 +01:00
0aefdfa457 2015: d16: ex2: add input 2025-05-21 22:18:59 +01:00
5cce56ced2 2015: d16: ex1: add solution 2025-05-21 22:18:54 +01:00
74843640bd 2015: d16: ex1: add input 2025-05-21 22:18:48 +01:00
151ab3e24f 2015: d15: ex2: add solution 2025-05-21 04:37:06 +01:00
e8ef80c528 2015: d15: ex2: add input 2025-05-21 04:36:33 +01:00
9caa6f9b98 2015: d15: ex1: add solution 2025-05-21 04:36:27 +01:00
5f561f0208 2015: d15: ex1: add input 2025-05-21 04:36:22 +01:00
ea5b2dfdfc 2015: d14: ex2: add solution 2025-05-21 04:05:45 +01:00
41de5c0abc 2015: d14: ex2: add input 2025-05-21 04:05:36 +01:00
b634beec24 2015: d14: ex1: add solution 2025-05-21 04:05:22 +01:00
c0a1916466 2015: d14: ex1: add input 2025-05-21 04:05:12 +01:00
d19850f8d0 2015: d13: ex2: add solution 2025-05-21 03:48:33 +01:00
6e5baf38c2 2015: d13: ex2: add input 2025-05-21 03:48:18 +01:00
34aaa729d6 2015: d13: ex1: add solution 2025-05-21 03:48:12 +01:00
a0ca39ca72 2015: d13: ex1: add input 2025-05-21 03:48:00 +01:00
3c69c64c18 2015: d12: ex2: add solution 2025-05-21 03:38:37 +01:00
8ac7dfe5a7 2015: d12: ex2: add input 2025-05-21 03:38:33 +01:00
a0d227c53e 2015: d12: ex1: add solution 2025-05-21 03:38:29 +01:00
b1ae9d9a06 2015: d12: ex1: add input 2025-05-21 03:38:24 +01:00
ba05a1b3a0 2015: d11: ex2: add solution 2025-05-21 03:31:13 +01:00
e8fc688ac3 2015: d11: ex2: add input 2025-05-21 03:31:08 +01:00
baa134a8b2 2015: d11: ex1: add solution 2025-05-21 03:31:03 +01:00
9a1a48e5f8 2015: d11: ex1: add input 2025-05-21 03:30:57 +01:00
2b377c9b9b 2015: d10: ex2: add solution 2025-05-21 02:58:43 +01:00
a5539ea9ca 2015: d10: ex2: add input 2025-05-21 02:58:33 +01:00
e85f35a361 2015: d10: ex1: add solution 2025-05-21 02:58:26 +01:00
04dc121ae8 2015: d10: ex1: add input 2025-05-21 02:58:15 +01:00
a3f3f2e5f6 2015: d09: ex2: add solution 2025-05-21 02:41:55 +01:00
dc7d58b076 2015: d09: ex2: add input 2025-05-21 02:41:50 +01:00
53326d7598 2015: d09: ex1: add solution 2025-05-21 02:41:46 +01:00
332e7ebcfd 2015: d09: ex1: add input 2025-05-21 02:41:40 +01:00
40f9ff8ae8 2015: d08: ex2: add solution 2025-05-21 02:35:42 +01:00
797b104850 2015: d08: ex2: add input 2025-05-21 02:35:38 +01:00
0c458813d4 2015: d08: ex1: add solution 2025-05-21 02:35:33 +01:00
72d37ffa5c 2015: d08: ex1: add input 2025-05-21 02:35:28 +01:00
0a500256da 2015: d07: ex2: add solution 2025-05-21 02:24:30 +01:00
8bb151fd6a 2015: d07: ex2: add input 2025-05-21 02:24:20 +01:00
de56afd64b 2015: d07: ex1: add solution 2025-05-21 02:24:14 +01:00
06950b6c72 2015: d07: ex1: add input 2025-05-21 02:24:03 +01:00
211b4ef910 2015: d06: ex2: add solution 2025-05-21 01:44:14 +01:00
a3feed2595 2015: d06: ex2: add input 2025-05-21 01:44:08 +01:00
6808196ffe 2015: d06: ex1: add solution 2025-05-21 01:44:02 +01:00
7b51b229f3 2015: d06: ex1: add input 2025-05-21 01:43:57 +01:00
e3ed06e246 2015: d05: ex2: add solution 2025-05-21 01:19:55 +01:00
0cc937849a 2015: d05: ex2: add input 2025-05-21 01:19:50 +01:00
5134d471d9 2015: d05: ex1: add solution 2025-05-21 01:19:44 +01:00
a1c3ca2381 2015: d05: ex1: add input 2025-05-21 01:19:38 +01:00
b46027ca9e 2015: d04: ex2: add solution 2025-05-21 00:59:37 +01:00
5eda64047c 2015: d04: ex2: add input 2025-05-21 00:59:22 +01:00
b364263838 2015: d04: ex1: add solution 2025-05-21 00:59:17 +01:00
6dcb0c3c3b 2015: d04: ex1: add input 2025-05-21 00:59:09 +01:00
6d318ff84d 2015: d03: ex2: add solution 2025-05-21 00:55:56 +01:00
5183d84bf7 2015: d03: ex2: add input 2025-05-21 00:55:45 +01:00
b27649bb65 2015: d03: ex1: add solution 2025-05-21 00:55:40 +01:00
3d6c560449 2015: d03: ex1: add input 2025-05-21 00:55:28 +01:00
175f1773bd 2015: d02: ex2: add solution 2025-05-21 00:47:45 +01:00
3e12df9ac7 2015: d02: ex2: add input 2025-05-21 00:47:40 +01:00
948e946f1d 2015: d02: ex1: add solution 2025-05-21 00:47:33 +01:00
79e75fe0a5 2015: d02: ex1: add input 2025-05-21 00:47:26 +01:00
c6afe68ac5 2015: d01: ex2: add solution 2025-05-21 00:39:52 +01:00
8c3207a385 2015: d01: ex2: add input 2025-05-21 00:39:44 +01:00
380b527017 2015: d01: ex1: add solution 2025-05-21 00:39:38 +01:00
086fef2122 2015: d01: ex1: add input 2025-05-21 00:39:33 +01:00
100 changed files with 10874 additions and 0 deletions

18
2015/d01/ex1/ex1.py Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env python
import collections
import sys
def solve(input: str) -> int:
directions = collections.Counter(input.strip())
return directions["("] - directions[")"]
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d01/ex1/input Normal file

File diff suppressed because one or more lines are too long

22
2015/d01/ex2/ex2.py Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env python
import sys
def solve(input: str) -> int:
BASEMENT = -1
current = 0
for i, c in enumerate(input, start=1):
current += 1 if c == "(" else -1
if current == BASEMENT:
return i
assert False # Sanity check
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d01/ex2/input Normal file

File diff suppressed because one or more lines are too long

28
2015/d02/ex1/ex1.py Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python
import sys
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[int, int, int]:
x, y, z = map(int, input.split("x"))
return x, y, z
def parse(input: str) -> list[tuple[int, int, int]]:
return [parse_line(line) for line in input.splitlines()]
def wrapping_paper(x: int, y: int, z: int) -> int:
slack = min(x * y, y * z, z * x)
return 2 * (x * y + y * z + z * x) + slack
presents = parse(input)
return sum(wrapping_paper(*present) for present in presents)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1000
2015/d02/ex1/input Normal file

File diff suppressed because it is too large Load diff

28
2015/d02/ex2/ex2.py Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python
import sys
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[int, int, int]:
x, y, z = map(int, input.split("x"))
return x, y, z
def parse(input: str) -> list[tuple[int, int, int]]:
return [parse_line(line) for line in input.splitlines()]
def ribbon(x: int, y: int, z: int) -> int:
bow = x * y * z
return 2 * min(x + y, y + z, z + x) + bow
presents = parse(input)
return sum(ribbon(*present) for present in presents)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1000
2015/d02/ex2/input Normal file

File diff suppressed because it is too large Load diff

55
2015/d03/ex1/ex1.py Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env python
import enum
import sys
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
class Direction(enum.StrEnum):
NORTH = "^"
EAST = ">"
SOUTH = "v"
WEST = "<"
def apply(self, p: Point) -> Point:
match self:
case Direction.NORTH:
dx, dy = -1, 0
case Direction.EAST:
dx, dy = 0, 1
case Direction.SOUTH:
dx, dy = 1, 0
case Direction.WEST:
dx, dy = 0, -1
return Point(p.x + dx, p.y + dy)
def solve(input: str) -> int:
def parse(input: str) -> list[Direction]:
return [Direction(c) for c in input.strip()]
def distribute_presents(moves: list[Direction]) -> set[Point]:
pos = Point(0, 0)
seen = {pos}
for move in moves:
pos = move.apply(pos)
seen.add(pos)
return seen
moves = parse(input)
presents = distribute_presents(moves)
return len(presents)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d03/ex1/input Normal file

File diff suppressed because one or more lines are too long

55
2015/d03/ex2/ex2.py Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env python
import enum
import sys
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
class Direction(enum.StrEnum):
NORTH = "^"
EAST = ">"
SOUTH = "v"
WEST = "<"
def apply(self, p: Point) -> Point:
match self:
case Direction.NORTH:
dx, dy = -1, 0
case Direction.EAST:
dx, dy = 0, 1
case Direction.SOUTH:
dx, dy = 1, 0
case Direction.WEST:
dx, dy = 0, -1
return Point(p.x + dx, p.y + dy)
def solve(input: str) -> int:
def parse(input: str) -> list[Direction]:
return [Direction(c) for c in input.strip()]
def distribute_presents(moves: list[Direction]) -> set[Point]:
pos = Point(0, 0)
seen = {pos}
for move in moves:
pos = move.apply(pos)
seen.add(pos)
return seen
moves = parse(input)
presents = distribute_presents(moves[::2]) | distribute_presents(moves[1::2])
return len(presents)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d03/ex2/input Normal file

File diff suppressed because one or more lines are too long

23
2015/d04/ex1/ex1.py Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env python
import hashlib
import itertools
import sys
def solve(input: str) -> int:
key = input.strip()
for i in itertools.count(1):
hash = hashlib.md5((key + str(i)).encode()).hexdigest()
if hash.startswith("00000"):
return i
assert False # Sanity check
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d04/ex1/input Normal file
View file

@ -0,0 +1 @@
yzbqklnj

23
2015/d04/ex2/ex2.py Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env python
import hashlib
import itertools
import sys
def solve(input: str) -> int:
key = input.strip()
for i in itertools.count(1):
hash = hashlib.md5((key + str(i)).encode()).hexdigest()
if hash.startswith("000000"):
return i
assert False # Sanity check
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d04/ex2/input Normal file
View file

@ -0,0 +1 @@
yzbqklnj

28
2015/d05/ex1/ex1.py Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python
import collections
import sys
def solve(input: str) -> int:
def is_nice(input: str) -> bool:
counts = collections.Counter(input)
if sum(counts[c] for c in "aeiou") < 3:
return False
if not any((c + c) in input for c in (chr(ord("a") + i) for i in range(26))):
return False
for bad in ("ab", "cd", "pq", "xy"):
if bad in input:
return False
return True
return sum(map(is_nice, input.splitlines()))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1000
2015/d05/ex1/input Normal file

File diff suppressed because it is too large Load diff

42
2015/d05/ex2/ex2.py Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env python
import collections
import itertools
import sys
from collections.abc import Iterable, Iterator
from typing import TypeVar
T = TypeVar("T")
def sliding_window(iterable: Iterable[T], n: int) -> Iterator[tuple[T, ...]]:
iterator = iter(iterable)
window = collections.deque(itertools.islice(iterator, n - 1), maxlen=n)
for x in iterator:
window.append(x)
yield tuple(window)
def solve(input: str) -> int:
def is_nice(input: str) -> bool:
if not any(
ab in rest
for ab, rest in (
(input[i : i + 2], input[i + 2 :]) for i in range(len(input) - 1)
)
):
return False
if not any(a == c for a, _, c in sliding_window(input, 3)):
return False
return True
return sum(map(is_nice, input.splitlines()))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1000
2015/d05/ex2/input Normal file

File diff suppressed because it is too large Load diff

70
2015/d06/ex1/ex1.py Executable file
View file

@ -0,0 +1,70 @@
#!/usr/bin/env python
import enum
import itertools
import sys
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
class Op(enum.StrEnum):
TURN_ON = "on"
TOGGLE = "toggle"
TURN_OFF = "off"
class Instruction(NamedTuple):
op: Op
a: Point
b: Point
@classmethod
def from_str(cls, input: str) -> "Instruction":
split_input = input.split()
raw_a, raw_b = split_input[-3], split_input[-1]
op = Op(split_input[1]) if split_input[0] == "turn" else Op(split_input[0])
return Instruction(
op,
Point(*map(int, raw_a.split(","))),
Point(*map(int, raw_b.split(","))),
)
def apply(self, screen: set[Point]) -> set[Point]:
points = {
Point(x, y)
for x, y in itertools.product(
range(self.a.x, self.b.x + 1),
range(self.a.y, self.b.y + 1),
)
}
match self.op:
case Op.TURN_ON:
return screen | points
case Op.TOGGLE:
return screen ^ points
case Op.TURN_OFF:
return screen - points
def solve(input: str) -> int:
def parse(input: str) -> list[Instruction]:
return [Instruction.from_str(line) for line in input.splitlines()]
instructions = parse(input)
screen: set[Point] = set()
for instr in instructions:
screen = instr.apply(screen)
return len(screen)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

300
2015/d06/ex1/input Normal file
View file

@ -0,0 +1,300 @@
turn on 489,959 through 759,964
turn off 820,516 through 871,914
turn off 427,423 through 929,502
turn on 774,14 through 977,877
turn on 410,146 through 864,337
turn on 931,331 through 939,812
turn off 756,53 through 923,339
turn off 313,787 through 545,979
turn off 12,823 through 102,934
toggle 756,965 through 812,992
turn off 743,684 through 789,958
toggle 120,314 through 745,489
toggle 692,845 through 866,994
turn off 587,176 through 850,273
turn off 674,321 through 793,388
toggle 749,672 through 973,965
turn on 943,30 through 990,907
turn on 296,50 through 729,664
turn on 212,957 through 490,987
toggle 171,31 through 688,88
turn off 991,989 through 994,998
turn off 913,943 through 958,953
turn off 278,258 through 367,386
toggle 275,796 through 493,971
turn off 70,873 through 798,923
toggle 258,985 through 663,998
turn on 601,259 through 831,486
turn off 914,94 through 941,102
turn off 558,161 through 994,647
turn on 119,662 through 760,838
toggle 378,775 through 526,852
turn off 384,670 through 674,972
turn off 249,41 through 270,936
turn on 614,742 through 769,780
turn on 427,70 through 575,441
turn on 410,478 through 985,753
turn off 619,46 through 931,342
turn on 284,55 through 768,922
turn off 40,592 through 728,685
turn on 825,291 through 956,950
turn on 147,843 through 592,909
turn off 218,675 through 972,911
toggle 249,291 through 350,960
turn off 556,80 through 967,675
toggle 609,148 through 968,279
toggle 217,605 through 961,862
toggle 407,177 through 548,910
toggle 400,936 through 599,938
turn off 721,101 through 925,455
turn on 268,631 through 735,814
toggle 549,969 through 612,991
toggle 553,268 through 689,432
turn off 817,668 through 889,897
toggle 801,544 through 858,556
toggle 615,729 through 832,951
turn off 427,477 through 958,948
turn on 164,49 through 852,946
turn on 542,449 through 774,776
turn off 923,196 through 980,446
toggle 90,310 through 718,846
turn off 657,215 through 744,252
turn off 800,239 through 811,712
turn on 502,90 through 619,760
toggle 649,512 through 862,844
turn off 334,903 through 823,935
turn off 630,233 through 839,445
turn on 713,67 through 839,865
turn on 932,50 through 982,411
turn off 480,729 through 984,910
turn on 100,219 through 796,395
turn on 758,108 through 850,950
turn off 427,276 through 439,938
turn on 178,284 through 670,536
toggle 540,27 through 625,102
turn off 906,722 through 936,948
toggle 345,418 through 859,627
toggle 175,775 through 580,781
toggle 863,28 through 929,735
turn off 824,858 through 905,973
toggle 752,312 through 863,425
turn on 985,716 through 988,852
turn off 68,504 through 763,745
toggle 76,209 through 810,720
turn off 657,607 through 676,664
toggle 596,869 through 896,921
turn off 915,411 through 968,945
turn off 368,39 through 902,986
turn on 11,549 through 393,597
turn off 842,893 through 976,911
toggle 274,106 through 581,329
toggle 406,403 through 780,950
toggle 408,988 through 500,994
toggle 217,73 through 826,951
turn on 917,872 through 961,911
toggle 394,34 through 510,572
toggle 424,603 through 583,626
toggle 106,159 through 755,738
turn off 244,610 through 472,709
turn on 350,265 through 884,690
turn on 688,184 through 928,280
toggle 279,443 through 720,797
turn off 615,493 through 888,610
toggle 118,413 through 736,632
turn on 798,782 through 829,813
turn off 250,934 through 442,972
turn on 68,503 through 400,949
toggle 297,482 through 313,871
toggle 710,3 through 839,859
turn on 125,300 through 546,888
toggle 482,39 through 584,159
turn off 536,89 through 765,962
turn on 530,518 through 843,676
turn on 994,467 through 994,676
turn on 623,628 through 744,927
toggle 704,912 through 837,983
turn on 154,364 through 517,412
toggle 344,409 through 780,524
turn off 578,740 through 725,879
turn on 251,933 through 632,957
turn on 827,705 through 971,789
toggle 191,282 through 470,929
toggle 324,525 through 446,867
toggle 534,343 through 874,971
toggle 550,650 through 633,980
toggle 837,404 through 881,915
toggle 338,881 through 845,905
turn on 469,462 through 750,696
turn on 741,703 through 892,870
turn off 570,215 through 733,562
turn on 445,576 through 870,775
turn on 466,747 through 554,878
turn off 820,453 through 868,712
turn off 892,706 through 938,792
turn off 300,238 through 894,746
turn off 306,44 through 457,444
turn off 912,569 through 967,963
toggle 109,756 through 297,867
turn on 37,546 through 41,951
turn on 321,637 through 790,910
toggle 66,50 through 579,301
toggle 933,221 through 933,791
turn on 486,676 through 878,797
turn on 417,231 through 556,317
toggle 904,468 through 981,873
turn on 417,675 through 749,712
turn on 692,371 through 821,842
toggle 324,73 through 830,543
turn on 912,490 through 977,757
turn off 634,872 through 902,949
toggle 266,779 through 870,798
turn on 772,982 through 990,996
turn off 607,46 through 798,559
turn on 295,602 through 963,987
turn on 657,86 through 944,742
turn off 334,639 through 456,821
turn off 997,667 through 997,670
turn off 725,832 through 951,945
turn off 30,120 through 952,984
turn on 860,965 through 917,976
toggle 471,997 through 840,998
turn off 319,307 through 928,504
toggle 823,631 through 940,908
toggle 969,984 through 981,993
turn off 691,319 through 865,954
toggle 911,926 through 938,929
turn on 953,937 through 968,991
toggle 914,643 through 975,840
turn on 266,982 through 436,996
turn off 101,896 through 321,932
turn off 193,852 through 751,885
turn off 576,532 through 863,684
turn on 761,456 through 940,783
turn on 20,290 through 398,933
turn off 435,335 through 644,652
turn on 830,569 through 905,770
turn off 630,517 through 905,654
turn on 664,53 through 886,976
toggle 275,416 through 408,719
turn on 370,621 through 515,793
turn on 483,373 through 654,749
turn on 656,786 through 847,928
turn off 532,752 through 945,974
toggle 301,150 through 880,792
turn off 951,488 through 958,952
turn on 207,729 through 882,828
toggle 694,532 through 973,961
toggle 676,639 through 891,802
turn off 653,6 through 905,519
toggle 391,109 through 418,312
turn on 877,423 through 957,932
turn on 340,145 through 563,522
turn off 978,467 through 988,895
turn off 396,418 through 420,885
turn off 31,308 through 816,316
turn on 107,675 through 758,824
turn on 61,82 through 789,876
turn on 750,743 through 754,760
toggle 88,733 through 736,968
turn off 754,349 through 849,897
toggle 157,50 through 975,781
turn off 230,231 through 865,842
turn off 516,317 through 630,329
turn off 697,820 through 829,903
turn on 218,250 through 271,732
toggle 56,167 through 404,431
toggle 626,891 through 680,927
toggle 370,207 through 791,514
toggle 860,74 through 949,888
turn on 416,527 through 616,541
turn off 745,449 through 786,908
turn on 485,554 through 689,689
turn on 586,62 through 693,141
toggle 506,759 through 768,829
turn on 473,109 through 929,166
turn on 760,617 through 773,789
toggle 595,683 through 618,789
turn off 210,775 through 825,972
toggle 12,426 through 179,982
turn on 774,539 through 778,786
turn on 102,498 through 121,807
turn off 706,897 through 834,965
turn off 678,529 through 824,627
turn on 7,765 through 615,870
turn off 730,872 through 974,943
turn off 595,626 through 836,711
turn off 215,424 through 841,959
toggle 341,780 through 861,813
toggle 507,503 through 568,822
turn on 252,603 through 349,655
toggle 93,521 through 154,834
turn on 565,682 through 951,954
turn on 544,318 through 703,418
toggle 756,953 through 891,964
turn on 531,123 through 856,991
turn on 148,315 through 776,559
turn off 925,835 through 963,971
turn on 895,944 through 967,964
turn off 102,527 through 650,747
toggle 626,105 through 738,720
turn off 160,75 through 384,922
toggle 813,724 through 903,941
turn on 207,107 through 982,849
toggle 750,505 through 961,697
toggle 105,410 through 885,819
turn on 226,104 through 298,283
turn off 224,604 through 508,762
turn on 477,368 through 523,506
turn off 477,901 through 627,936
turn off 887,131 through 889,670
turn on 896,994 through 938,999
toggle 401,580 through 493,728
toggle 987,184 through 991,205
turn on 821,643 through 882,674
toggle 784,940 through 968,959
turn off 251,293 through 274,632
turn off 339,840 through 341,844
turn off 675,351 through 675,836
toggle 918,857 through 944,886
toggle 70,253 through 918,736
turn off 612,604 through 772,680
turn off 277,40 through 828,348
toggle 692,139 through 698,880
toggle 124,446 through 883,453
toggle 969,932 through 990,945
toggle 855,692 through 993,693
toggle 722,472 through 887,899
toggle 978,149 through 985,442
toggle 837,540 through 916,889
turn off 612,2 through 835,82
toggle 560,767 through 878,856
turn on 461,734 through 524,991
toggle 206,824 through 976,912
turn on 826,610 through 879,892
turn on 577,699 through 956,933
turn off 9,250 through 50,529
turn off 77,657 through 817,677
turn on 68,419 through 86,426
turn on 991,720 through 992,784
turn on 668,20 through 935,470
turn off 133,418 through 613,458
turn off 487,286 through 540,328
toggle 247,874 through 840,955
toggle 301,808 through 754,970
turn off 34,194 through 578,203
turn off 451,49 through 492,921
turn on 907,256 through 912,737
turn off 479,305 through 702,587
turn on 545,583 through 732,749
toggle 11,16 through 725,868
turn on 965,343 through 986,908
turn on 674,953 through 820,965
toggle 398,147 through 504,583
turn off 778,194 through 898,298
turn on 179,140 through 350,852
turn off 241,118 through 530,832
turn off 41,447 through 932,737
turn off 820,663 through 832,982
turn on 550,460 through 964,782
turn on 31,760 through 655,892
toggle 628,958 through 811,992

71
2015/d06/ex2/ex2.py Executable file
View file

@ -0,0 +1,71 @@
#!/usr/bin/env python
import collections
import enum
import itertools
import sys
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
class Op(enum.StrEnum):
TURN_ON = "on"
TOGGLE = "toggle"
TURN_OFF = "off"
class Instruction(NamedTuple):
op: Op
a: Point
b: Point
@classmethod
def from_str(cls, input: str) -> "Instruction":
split_input = input.split()
raw_a, raw_b = split_input[-3], split_input[-1]
op = Op(split_input[1]) if split_input[0] == "turn" else Op(split_input[0])
return Instruction(
op,
Point(*map(int, raw_a.split(","))),
Point(*map(int, raw_b.split(","))),
)
def apply(self, screen: collections.Counter[Point]) -> collections.Counter[Point]:
points = collections.Counter(
Point(x, y)
for x, y in itertools.product(
range(self.a.x, self.b.x + 1),
range(self.a.y, self.b.y + 1),
)
)
match self.op:
case Op.TURN_ON:
return screen + points
case Op.TOGGLE:
return screen + points + points
case Op.TURN_OFF:
return screen - points
def solve(input: str) -> int:
def parse(input: str) -> list[Instruction]:
return [Instruction.from_str(line) for line in input.splitlines()]
instructions = parse(input)
screen: collections.Counter[Point] = collections.Counter()
for instr in instructions:
screen = instr.apply(screen)
return screen.total()
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

300
2015/d06/ex2/input Normal file
View file

@ -0,0 +1,300 @@
turn on 489,959 through 759,964
turn off 820,516 through 871,914
turn off 427,423 through 929,502
turn on 774,14 through 977,877
turn on 410,146 through 864,337
turn on 931,331 through 939,812
turn off 756,53 through 923,339
turn off 313,787 through 545,979
turn off 12,823 through 102,934
toggle 756,965 through 812,992
turn off 743,684 through 789,958
toggle 120,314 through 745,489
toggle 692,845 through 866,994
turn off 587,176 through 850,273
turn off 674,321 through 793,388
toggle 749,672 through 973,965
turn on 943,30 through 990,907
turn on 296,50 through 729,664
turn on 212,957 through 490,987
toggle 171,31 through 688,88
turn off 991,989 through 994,998
turn off 913,943 through 958,953
turn off 278,258 through 367,386
toggle 275,796 through 493,971
turn off 70,873 through 798,923
toggle 258,985 through 663,998
turn on 601,259 through 831,486
turn off 914,94 through 941,102
turn off 558,161 through 994,647
turn on 119,662 through 760,838
toggle 378,775 through 526,852
turn off 384,670 through 674,972
turn off 249,41 through 270,936
turn on 614,742 through 769,780
turn on 427,70 through 575,441
turn on 410,478 through 985,753
turn off 619,46 through 931,342
turn on 284,55 through 768,922
turn off 40,592 through 728,685
turn on 825,291 through 956,950
turn on 147,843 through 592,909
turn off 218,675 through 972,911
toggle 249,291 through 350,960
turn off 556,80 through 967,675
toggle 609,148 through 968,279
toggle 217,605 through 961,862
toggle 407,177 through 548,910
toggle 400,936 through 599,938
turn off 721,101 through 925,455
turn on 268,631 through 735,814
toggle 549,969 through 612,991
toggle 553,268 through 689,432
turn off 817,668 through 889,897
toggle 801,544 through 858,556
toggle 615,729 through 832,951
turn off 427,477 through 958,948
turn on 164,49 through 852,946
turn on 542,449 through 774,776
turn off 923,196 through 980,446
toggle 90,310 through 718,846
turn off 657,215 through 744,252
turn off 800,239 through 811,712
turn on 502,90 through 619,760
toggle 649,512 through 862,844
turn off 334,903 through 823,935
turn off 630,233 through 839,445
turn on 713,67 through 839,865
turn on 932,50 through 982,411
turn off 480,729 through 984,910
turn on 100,219 through 796,395
turn on 758,108 through 850,950
turn off 427,276 through 439,938
turn on 178,284 through 670,536
toggle 540,27 through 625,102
turn off 906,722 through 936,948
toggle 345,418 through 859,627
toggle 175,775 through 580,781
toggle 863,28 through 929,735
turn off 824,858 through 905,973
toggle 752,312 through 863,425
turn on 985,716 through 988,852
turn off 68,504 through 763,745
toggle 76,209 through 810,720
turn off 657,607 through 676,664
toggle 596,869 through 896,921
turn off 915,411 through 968,945
turn off 368,39 through 902,986
turn on 11,549 through 393,597
turn off 842,893 through 976,911
toggle 274,106 through 581,329
toggle 406,403 through 780,950
toggle 408,988 through 500,994
toggle 217,73 through 826,951
turn on 917,872 through 961,911
toggle 394,34 through 510,572
toggle 424,603 through 583,626
toggle 106,159 through 755,738
turn off 244,610 through 472,709
turn on 350,265 through 884,690
turn on 688,184 through 928,280
toggle 279,443 through 720,797
turn off 615,493 through 888,610
toggle 118,413 through 736,632
turn on 798,782 through 829,813
turn off 250,934 through 442,972
turn on 68,503 through 400,949
toggle 297,482 through 313,871
toggle 710,3 through 839,859
turn on 125,300 through 546,888
toggle 482,39 through 584,159
turn off 536,89 through 765,962
turn on 530,518 through 843,676
turn on 994,467 through 994,676
turn on 623,628 through 744,927
toggle 704,912 through 837,983
turn on 154,364 through 517,412
toggle 344,409 through 780,524
turn off 578,740 through 725,879
turn on 251,933 through 632,957
turn on 827,705 through 971,789
toggle 191,282 through 470,929
toggle 324,525 through 446,867
toggle 534,343 through 874,971
toggle 550,650 through 633,980
toggle 837,404 through 881,915
toggle 338,881 through 845,905
turn on 469,462 through 750,696
turn on 741,703 through 892,870
turn off 570,215 through 733,562
turn on 445,576 through 870,775
turn on 466,747 through 554,878
turn off 820,453 through 868,712
turn off 892,706 through 938,792
turn off 300,238 through 894,746
turn off 306,44 through 457,444
turn off 912,569 through 967,963
toggle 109,756 through 297,867
turn on 37,546 through 41,951
turn on 321,637 through 790,910
toggle 66,50 through 579,301
toggle 933,221 through 933,791
turn on 486,676 through 878,797
turn on 417,231 through 556,317
toggle 904,468 through 981,873
turn on 417,675 through 749,712
turn on 692,371 through 821,842
toggle 324,73 through 830,543
turn on 912,490 through 977,757
turn off 634,872 through 902,949
toggle 266,779 through 870,798
turn on 772,982 through 990,996
turn off 607,46 through 798,559
turn on 295,602 through 963,987
turn on 657,86 through 944,742
turn off 334,639 through 456,821
turn off 997,667 through 997,670
turn off 725,832 through 951,945
turn off 30,120 through 952,984
turn on 860,965 through 917,976
toggle 471,997 through 840,998
turn off 319,307 through 928,504
toggle 823,631 through 940,908
toggle 969,984 through 981,993
turn off 691,319 through 865,954
toggle 911,926 through 938,929
turn on 953,937 through 968,991
toggle 914,643 through 975,840
turn on 266,982 through 436,996
turn off 101,896 through 321,932
turn off 193,852 through 751,885
turn off 576,532 through 863,684
turn on 761,456 through 940,783
turn on 20,290 through 398,933
turn off 435,335 through 644,652
turn on 830,569 through 905,770
turn off 630,517 through 905,654
turn on 664,53 through 886,976
toggle 275,416 through 408,719
turn on 370,621 through 515,793
turn on 483,373 through 654,749
turn on 656,786 through 847,928
turn off 532,752 through 945,974
toggle 301,150 through 880,792
turn off 951,488 through 958,952
turn on 207,729 through 882,828
toggle 694,532 through 973,961
toggle 676,639 through 891,802
turn off 653,6 through 905,519
toggle 391,109 through 418,312
turn on 877,423 through 957,932
turn on 340,145 through 563,522
turn off 978,467 through 988,895
turn off 396,418 through 420,885
turn off 31,308 through 816,316
turn on 107,675 through 758,824
turn on 61,82 through 789,876
turn on 750,743 through 754,760
toggle 88,733 through 736,968
turn off 754,349 through 849,897
toggle 157,50 through 975,781
turn off 230,231 through 865,842
turn off 516,317 through 630,329
turn off 697,820 through 829,903
turn on 218,250 through 271,732
toggle 56,167 through 404,431
toggle 626,891 through 680,927
toggle 370,207 through 791,514
toggle 860,74 through 949,888
turn on 416,527 through 616,541
turn off 745,449 through 786,908
turn on 485,554 through 689,689
turn on 586,62 through 693,141
toggle 506,759 through 768,829
turn on 473,109 through 929,166
turn on 760,617 through 773,789
toggle 595,683 through 618,789
turn off 210,775 through 825,972
toggle 12,426 through 179,982
turn on 774,539 through 778,786
turn on 102,498 through 121,807
turn off 706,897 through 834,965
turn off 678,529 through 824,627
turn on 7,765 through 615,870
turn off 730,872 through 974,943
turn off 595,626 through 836,711
turn off 215,424 through 841,959
toggle 341,780 through 861,813
toggle 507,503 through 568,822
turn on 252,603 through 349,655
toggle 93,521 through 154,834
turn on 565,682 through 951,954
turn on 544,318 through 703,418
toggle 756,953 through 891,964
turn on 531,123 through 856,991
turn on 148,315 through 776,559
turn off 925,835 through 963,971
turn on 895,944 through 967,964
turn off 102,527 through 650,747
toggle 626,105 through 738,720
turn off 160,75 through 384,922
toggle 813,724 through 903,941
turn on 207,107 through 982,849
toggle 750,505 through 961,697
toggle 105,410 through 885,819
turn on 226,104 through 298,283
turn off 224,604 through 508,762
turn on 477,368 through 523,506
turn off 477,901 through 627,936
turn off 887,131 through 889,670
turn on 896,994 through 938,999
toggle 401,580 through 493,728
toggle 987,184 through 991,205
turn on 821,643 through 882,674
toggle 784,940 through 968,959
turn off 251,293 through 274,632
turn off 339,840 through 341,844
turn off 675,351 through 675,836
toggle 918,857 through 944,886
toggle 70,253 through 918,736
turn off 612,604 through 772,680
turn off 277,40 through 828,348
toggle 692,139 through 698,880
toggle 124,446 through 883,453
toggle 969,932 through 990,945
toggle 855,692 through 993,693
toggle 722,472 through 887,899
toggle 978,149 through 985,442
toggle 837,540 through 916,889
turn off 612,2 through 835,82
toggle 560,767 through 878,856
turn on 461,734 through 524,991
toggle 206,824 through 976,912
turn on 826,610 through 879,892
turn on 577,699 through 956,933
turn off 9,250 through 50,529
turn off 77,657 through 817,677
turn on 68,419 through 86,426
turn on 991,720 through 992,784
turn on 668,20 through 935,470
turn off 133,418 through 613,458
turn off 487,286 through 540,328
toggle 247,874 through 840,955
toggle 301,808 through 754,970
turn off 34,194 through 578,203
turn off 451,49 through 492,921
turn on 907,256 through 912,737
turn off 479,305 through 702,587
turn on 545,583 through 732,749
toggle 11,16 through 725,868
turn on 965,343 through 986,908
turn on 674,953 through 820,965
toggle 398,147 through 504,583
turn off 778,194 through 898,298
turn on 179,140 through 350,852
turn off 241,118 through 530,832
turn off 41,447 through 932,737
turn off 820,663 through 832,982
turn on 550,460 through 964,782
turn on 31,760 through 655,892
toggle 628,958 through 811,992

121
2015/d07/ex1/ex1.py Executable file
View file

@ -0,0 +1,121 @@
#!/usr/bin/env python
import enum
import operator
import sys
from typing import NamedTuple
class Op(enum.StrEnum):
AND = "AND_"
OR = "OR_"
LSHIFT = "LSHIFT"
RSHIFT = "RSHIFT"
NOT = "NOT"
IDENTITY = "" # For the output to `a`, which has no operator
def apply(self, lhs: int, rhs: int | None) -> int:
if self == Op.IDENTITY:
assert rhs is None
return lhs
if self == Op.NOT:
assert rhs is None
return ~lhs
assert rhs is not None
return getattr(operator, self.lower())(lhs, rhs)
class Instruction(NamedTuple):
op: Op
lhs: str
rhs: str | None = None
@classmethod
def from_str(cls, input: str) -> "Instruction":
split_input = input.split()
if len(split_input) == 1:
op = ""
lhs = split_input[0]
rest = []
elif split_input[0] == "NOT":
op, lhs, *rest = split_input
else:
lhs, op, *rest = split_input
# Hacky way to match with the function in the `operator` module...
if op in ("AND", "OR"):
op = op + "_"
return cls(Op(op), lhs, *rest)
Circuit = dict[str, Instruction | int]
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, Instruction | int]:
raw_instr, wire = input.split(" -> ")
if raw_instr.isdigit():
return wire, int(raw_instr)
return wire, Instruction.from_str(raw_instr)
def parse(input: str) -> Circuit:
return {wire: val for wire, val in map(parse_line, input.splitlines())}
def dependencies(circuit: Circuit) -> dict[str, set[str]]:
res: dict[str, set[str]] = {wire: set() for wire in circuit.keys()}
for wire, val in circuit.items():
if isinstance(val, int):
continue
for dep in (val.lhs, val.rhs):
if dep is None:
continue
if dep.isdigit():
continue
res[wire].add(dep)
return res
def topo_sort(dep_graph: dict[str, set[str]]) -> list[str]:
res: list[str] = []
queue = {n for n, deps in dep_graph.items() if not deps}
seen: set[str] = set()
while queue:
node = queue.pop()
res.append(node)
seen.add(node)
# Iterate over all nodes as we don't have information on children
for child, deps in dep_graph.items():
if child in seen:
continue
if deps - seen:
continue
queue.add(child)
return res
def run(circuit: Circuit) -> dict[str, int]:
res: dict[str, int] = {}
for wire in topo_sort(dependencies(circuit)):
match circuit[wire]:
case int(n):
res[wire] = n
case Instruction(op, lhs, rhs):
resolve = lambda v: int(v) if v.isdigit() else res[v]
lhs_n = resolve(lhs)
rhs_n = None if rhs is None else resolve(rhs)
res[wire] = op.apply(lhs_n, rhs_n)
return res
circuit = parse(input)
wires = run(circuit)
return wires["a"]
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

339
2015/d07/ex1/input Normal file
View file

@ -0,0 +1,339 @@
lf AND lq -> ls
iu RSHIFT 1 -> jn
bo OR bu -> bv
gj RSHIFT 1 -> hc
et RSHIFT 2 -> eu
bv AND bx -> by
is OR it -> iu
b OR n -> o
gf OR ge -> gg
NOT kt -> ku
ea AND eb -> ed
kl OR kr -> ks
hi AND hk -> hl
au AND av -> ax
lf RSHIFT 2 -> lg
dd RSHIFT 3 -> df
eu AND fa -> fc
df AND dg -> di
ip LSHIFT 15 -> it
NOT el -> em
et OR fe -> ff
fj LSHIFT 15 -> fn
t OR s -> u
ly OR lz -> ma
ko AND kq -> kr
NOT fx -> fy
et RSHIFT 1 -> fm
eu OR fa -> fb
dd RSHIFT 2 -> de
NOT go -> gp
kb AND kd -> ke
hg OR hh -> hi
jm LSHIFT 1 -> kg
NOT cn -> co
jp RSHIFT 2 -> jq
jp RSHIFT 5 -> js
1 AND io -> ip
eo LSHIFT 15 -> es
1 AND jj -> jk
g AND i -> j
ci RSHIFT 3 -> ck
gn AND gp -> gq
fs AND fu -> fv
lj AND ll -> lm
jk LSHIFT 15 -> jo
iu RSHIFT 3 -> iw
NOT ii -> ij
1 AND cc -> cd
bn RSHIFT 3 -> bp
NOT gw -> gx
NOT ft -> fu
jn OR jo -> jp
iv OR jb -> jc
hv OR hu -> hw
19138 -> b
gj RSHIFT 5 -> gm
hq AND hs -> ht
dy RSHIFT 1 -> er
ao OR an -> ap
ld OR le -> lf
bk LSHIFT 1 -> ce
bz AND cb -> cc
bi LSHIFT 15 -> bm
il AND in -> io
af AND ah -> ai
as RSHIFT 1 -> bl
lf RSHIFT 3 -> lh
er OR es -> et
NOT ax -> ay
ci RSHIFT 1 -> db
et AND fe -> fg
lg OR lm -> ln
k AND m -> n
hz RSHIFT 2 -> ia
kh LSHIFT 1 -> lb
NOT ey -> ez
NOT di -> dj
dz OR ef -> eg
lx -> a
NOT iz -> ja
gz LSHIFT 15 -> hd
ce OR cd -> cf
fq AND fr -> ft
at AND az -> bb
ha OR gz -> hb
fp AND fv -> fx
NOT gb -> gc
ia AND ig -> ii
gl OR gm -> gn
0 -> c
NOT ca -> cb
bn RSHIFT 1 -> cg
c LSHIFT 1 -> t
iw OR ix -> iy
kg OR kf -> kh
dy OR ej -> ek
km AND kn -> kp
NOT fc -> fd
hz RSHIFT 3 -> ib
NOT dq -> dr
NOT fg -> fh
dy RSHIFT 2 -> dz
kk RSHIFT 2 -> kl
1 AND fi -> fj
NOT hr -> hs
jp RSHIFT 1 -> ki
bl OR bm -> bn
1 AND gy -> gz
gr AND gt -> gu
db OR dc -> dd
de OR dk -> dl
as RSHIFT 5 -> av
lf RSHIFT 5 -> li
hm AND ho -> hp
cg OR ch -> ci
gj AND gu -> gw
ge LSHIFT 15 -> gi
e OR f -> g
fp OR fv -> fw
fb AND fd -> fe
cd LSHIFT 15 -> ch
b RSHIFT 1 -> v
at OR az -> ba
bn RSHIFT 2 -> bo
lh AND li -> lk
dl AND dn -> do
eg AND ei -> ej
ex AND ez -> fa
NOT kp -> kq
NOT lk -> ll
x AND ai -> ak
jp OR ka -> kb
NOT jd -> je
iy AND ja -> jb
jp RSHIFT 3 -> jr
fo OR fz -> ga
df OR dg -> dh
gj RSHIFT 2 -> gk
gj OR gu -> gv
NOT jh -> ji
ap LSHIFT 1 -> bj
NOT ls -> lt
ir LSHIFT 1 -> jl
bn AND by -> ca
lv LSHIFT 15 -> lz
ba AND bc -> bd
cy LSHIFT 15 -> dc
ln AND lp -> lq
x RSHIFT 1 -> aq
gk OR gq -> gr
NOT kx -> ky
jg AND ji -> jj
bn OR by -> bz
fl LSHIFT 1 -> gf
bp OR bq -> br
he OR hp -> hq
et RSHIFT 5 -> ew
iu RSHIFT 2 -> iv
gl AND gm -> go
x OR ai -> aj
hc OR hd -> he
lg AND lm -> lo
lh OR li -> lj
da LSHIFT 1 -> du
fo RSHIFT 2 -> fp
gk AND gq -> gs
bj OR bi -> bk
lf OR lq -> lr
cj AND cp -> cr
hu LSHIFT 15 -> hy
1 AND bh -> bi
fo RSHIFT 3 -> fq
NOT lo -> lp
hw LSHIFT 1 -> iq
dd RSHIFT 1 -> dw
dt LSHIFT 15 -> dx
dy AND ej -> el
an LSHIFT 15 -> ar
aq OR ar -> as
1 AND r -> s
fw AND fy -> fz
NOT im -> in
et RSHIFT 3 -> ev
1 AND ds -> dt
ec AND ee -> ef
NOT ak -> al
jl OR jk -> jm
1 AND en -> eo
lb OR la -> lc
iu AND jf -> jh
iu RSHIFT 5 -> ix
bo AND bu -> bw
cz OR cy -> da
iv AND jb -> jd
iw AND ix -> iz
lf RSHIFT 1 -> ly
iu OR jf -> jg
NOT dm -> dn
lw OR lv -> lx
gg LSHIFT 1 -> ha
lr AND lt -> lu
fm OR fn -> fo
he RSHIFT 3 -> hg
aj AND al -> am
1 AND kz -> la
dy RSHIFT 5 -> eb
jc AND je -> jf
cm AND co -> cp
gv AND gx -> gy
ev OR ew -> ex
jp AND ka -> kc
fk OR fj -> fl
dy RSHIFT 3 -> ea
NOT bs -> bt
NOT ag -> ah
dz AND ef -> eh
cf LSHIFT 1 -> cz
NOT cv -> cw
1 AND cx -> cy
de AND dk -> dm
ck AND cl -> cn
x RSHIFT 5 -> aa
dv LSHIFT 1 -> ep
he RSHIFT 2 -> hf
NOT bw -> bx
ck OR cl -> cm
bp AND bq -> bs
as OR bd -> be
he AND hp -> hr
ev AND ew -> ey
1 AND lu -> lv
kk RSHIFT 3 -> km
b AND n -> p
NOT kc -> kd
lc LSHIFT 1 -> lw
km OR kn -> ko
id AND if -> ig
ih AND ij -> ik
jr AND js -> ju
ci RSHIFT 5 -> cl
hz RSHIFT 1 -> is
1 AND ke -> kf
NOT gs -> gt
aw AND ay -> az
x RSHIFT 2 -> y
ab AND ad -> ae
ff AND fh -> fi
ci AND ct -> cv
eq LSHIFT 1 -> fk
gj RSHIFT 3 -> gl
u LSHIFT 1 -> ao
NOT bb -> bc
NOT hj -> hk
kw AND ky -> kz
as AND bd -> bf
dw OR dx -> dy
br AND bt -> bu
kk AND kv -> kx
ep OR eo -> eq
he RSHIFT 1 -> hx
ki OR kj -> kk
NOT ju -> jv
ek AND em -> en
kk RSHIFT 5 -> kn
NOT eh -> ei
hx OR hy -> hz
ea OR eb -> ec
s LSHIFT 15 -> w
fo RSHIFT 1 -> gh
kk OR kv -> kw
bn RSHIFT 5 -> bq
NOT ed -> ee
1 AND ht -> hu
cu AND cw -> cx
b RSHIFT 5 -> f
kl AND kr -> kt
iq OR ip -> ir
ci RSHIFT 2 -> cj
cj OR cp -> cq
o AND q -> r
dd RSHIFT 5 -> dg
b RSHIFT 2 -> d
ks AND ku -> kv
b RSHIFT 3 -> e
d OR j -> k
NOT p -> q
NOT cr -> cs
du OR dt -> dv
kf LSHIFT 15 -> kj
NOT ac -> ad
fo RSHIFT 5 -> fr
hz OR ik -> il
jx AND jz -> ka
gh OR gi -> gj
kk RSHIFT 1 -> ld
hz RSHIFT 5 -> ic
as RSHIFT 2 -> at
NOT jy -> jz
1 AND am -> an
ci OR ct -> cu
hg AND hh -> hj
jq OR jw -> jx
v OR w -> x
la LSHIFT 15 -> le
dh AND dj -> dk
dp AND dr -> ds
jq AND jw -> jy
au OR av -> aw
NOT bf -> bg
z OR aa -> ab
ga AND gc -> gd
hz AND ik -> im
jt AND jv -> jw
z AND aa -> ac
jr OR js -> jt
hb LSHIFT 1 -> hv
hf OR hl -> hm
ib OR ic -> id
fq OR fr -> fs
cq AND cs -> ct
ia OR ig -> ih
dd OR do -> dp
d AND j -> l
ib AND ic -> ie
as RSHIFT 3 -> au
be AND bg -> bh
dd AND do -> dq
NOT l -> m
1 AND gd -> ge
y AND ae -> ag
fo AND fz -> gb
NOT ie -> if
e AND f -> h
x RSHIFT 3 -> z
y OR ae -> af
hf AND hl -> hn
NOT h -> i
NOT hn -> ho
he RSHIFT 5 -> hh

122
2015/d07/ex2/ex2.py Executable file
View file

@ -0,0 +1,122 @@
#!/usr/bin/env python
import enum
import operator
import sys
from typing import NamedTuple
class Op(enum.StrEnum):
AND = "AND_"
OR = "OR_"
LSHIFT = "LSHIFT"
RSHIFT = "RSHIFT"
NOT = "NOT"
IDENTITY = "" # For the output to `a`, which has no operator
def apply(self, lhs: int, rhs: int | None) -> int:
if self == Op.IDENTITY:
assert rhs is None
return lhs
if self == Op.NOT:
assert rhs is None
return ~lhs
assert rhs is not None
return getattr(operator, self.lower())(lhs, rhs)
class Instruction(NamedTuple):
op: Op
lhs: str
rhs: str | None = None
@classmethod
def from_str(cls, input: str) -> "Instruction":
split_input = input.split()
if len(split_input) == 1:
op = ""
lhs = split_input[0]
rest = []
elif split_input[0] == "NOT":
op, lhs, *rest = split_input
else:
lhs, op, *rest = split_input
# Hacky way to match with the function in the `operator` module...
if op in ("AND", "OR"):
op = op + "_"
return cls(Op(op), lhs, *rest)
Circuit = dict[str, Instruction | int]
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, Instruction | int]:
raw_instr, wire = input.split(" -> ")
if raw_instr.isdigit():
return wire, int(raw_instr)
return wire, Instruction.from_str(raw_instr)
def parse(input: str) -> Circuit:
return {wire: val for wire, val in map(parse_line, input.splitlines())}
def dependencies(circuit: Circuit) -> dict[str, set[str]]:
res: dict[str, set[str]] = {wire: set() for wire in circuit.keys()}
for wire, val in circuit.items():
if isinstance(val, int):
continue
for dep in (val.lhs, val.rhs):
if dep is None:
continue
if dep.isdigit():
continue
res[wire].add(dep)
return res
def topo_sort(dep_graph: dict[str, set[str]]) -> list[str]:
res: list[str] = []
queue = {n for n, deps in dep_graph.items() if not deps}
seen: set[str] = set()
while queue:
node = queue.pop()
res.append(node)
seen.add(node)
# Iterate over all nodes as we don't have information on children
for child, deps in dep_graph.items():
if child in seen:
continue
if deps - seen:
continue
queue.add(child)
return res
def run(circuit: Circuit) -> dict[str, int]:
res: dict[str, int] = {}
for wire in topo_sort(dependencies(circuit)):
match circuit[wire]:
case int(n):
res[wire] = n
case Instruction(op, lhs, rhs):
resolve = lambda v: int(v) if v.isdigit() else res[v]
lhs_n = resolve(lhs)
rhs_n = None if rhs is None else resolve(rhs)
res[wire] = op.apply(lhs_n, rhs_n)
return res
circuit = parse(input)
first_run = run(circuit)
wires = run(circuit | {"b": first_run["a"]})
return wires["a"]
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

339
2015/d07/ex2/input Normal file
View file

@ -0,0 +1,339 @@
lf AND lq -> ls
iu RSHIFT 1 -> jn
bo OR bu -> bv
gj RSHIFT 1 -> hc
et RSHIFT 2 -> eu
bv AND bx -> by
is OR it -> iu
b OR n -> o
gf OR ge -> gg
NOT kt -> ku
ea AND eb -> ed
kl OR kr -> ks
hi AND hk -> hl
au AND av -> ax
lf RSHIFT 2 -> lg
dd RSHIFT 3 -> df
eu AND fa -> fc
df AND dg -> di
ip LSHIFT 15 -> it
NOT el -> em
et OR fe -> ff
fj LSHIFT 15 -> fn
t OR s -> u
ly OR lz -> ma
ko AND kq -> kr
NOT fx -> fy
et RSHIFT 1 -> fm
eu OR fa -> fb
dd RSHIFT 2 -> de
NOT go -> gp
kb AND kd -> ke
hg OR hh -> hi
jm LSHIFT 1 -> kg
NOT cn -> co
jp RSHIFT 2 -> jq
jp RSHIFT 5 -> js
1 AND io -> ip
eo LSHIFT 15 -> es
1 AND jj -> jk
g AND i -> j
ci RSHIFT 3 -> ck
gn AND gp -> gq
fs AND fu -> fv
lj AND ll -> lm
jk LSHIFT 15 -> jo
iu RSHIFT 3 -> iw
NOT ii -> ij
1 AND cc -> cd
bn RSHIFT 3 -> bp
NOT gw -> gx
NOT ft -> fu
jn OR jo -> jp
iv OR jb -> jc
hv OR hu -> hw
19138 -> b
gj RSHIFT 5 -> gm
hq AND hs -> ht
dy RSHIFT 1 -> er
ao OR an -> ap
ld OR le -> lf
bk LSHIFT 1 -> ce
bz AND cb -> cc
bi LSHIFT 15 -> bm
il AND in -> io
af AND ah -> ai
as RSHIFT 1 -> bl
lf RSHIFT 3 -> lh
er OR es -> et
NOT ax -> ay
ci RSHIFT 1 -> db
et AND fe -> fg
lg OR lm -> ln
k AND m -> n
hz RSHIFT 2 -> ia
kh LSHIFT 1 -> lb
NOT ey -> ez
NOT di -> dj
dz OR ef -> eg
lx -> a
NOT iz -> ja
gz LSHIFT 15 -> hd
ce OR cd -> cf
fq AND fr -> ft
at AND az -> bb
ha OR gz -> hb
fp AND fv -> fx
NOT gb -> gc
ia AND ig -> ii
gl OR gm -> gn
0 -> c
NOT ca -> cb
bn RSHIFT 1 -> cg
c LSHIFT 1 -> t
iw OR ix -> iy
kg OR kf -> kh
dy OR ej -> ek
km AND kn -> kp
NOT fc -> fd
hz RSHIFT 3 -> ib
NOT dq -> dr
NOT fg -> fh
dy RSHIFT 2 -> dz
kk RSHIFT 2 -> kl
1 AND fi -> fj
NOT hr -> hs
jp RSHIFT 1 -> ki
bl OR bm -> bn
1 AND gy -> gz
gr AND gt -> gu
db OR dc -> dd
de OR dk -> dl
as RSHIFT 5 -> av
lf RSHIFT 5 -> li
hm AND ho -> hp
cg OR ch -> ci
gj AND gu -> gw
ge LSHIFT 15 -> gi
e OR f -> g
fp OR fv -> fw
fb AND fd -> fe
cd LSHIFT 15 -> ch
b RSHIFT 1 -> v
at OR az -> ba
bn RSHIFT 2 -> bo
lh AND li -> lk
dl AND dn -> do
eg AND ei -> ej
ex AND ez -> fa
NOT kp -> kq
NOT lk -> ll
x AND ai -> ak
jp OR ka -> kb
NOT jd -> je
iy AND ja -> jb
jp RSHIFT 3 -> jr
fo OR fz -> ga
df OR dg -> dh
gj RSHIFT 2 -> gk
gj OR gu -> gv
NOT jh -> ji
ap LSHIFT 1 -> bj
NOT ls -> lt
ir LSHIFT 1 -> jl
bn AND by -> ca
lv LSHIFT 15 -> lz
ba AND bc -> bd
cy LSHIFT 15 -> dc
ln AND lp -> lq
x RSHIFT 1 -> aq
gk OR gq -> gr
NOT kx -> ky
jg AND ji -> jj
bn OR by -> bz
fl LSHIFT 1 -> gf
bp OR bq -> br
he OR hp -> hq
et RSHIFT 5 -> ew
iu RSHIFT 2 -> iv
gl AND gm -> go
x OR ai -> aj
hc OR hd -> he
lg AND lm -> lo
lh OR li -> lj
da LSHIFT 1 -> du
fo RSHIFT 2 -> fp
gk AND gq -> gs
bj OR bi -> bk
lf OR lq -> lr
cj AND cp -> cr
hu LSHIFT 15 -> hy
1 AND bh -> bi
fo RSHIFT 3 -> fq
NOT lo -> lp
hw LSHIFT 1 -> iq
dd RSHIFT 1 -> dw
dt LSHIFT 15 -> dx
dy AND ej -> el
an LSHIFT 15 -> ar
aq OR ar -> as
1 AND r -> s
fw AND fy -> fz
NOT im -> in
et RSHIFT 3 -> ev
1 AND ds -> dt
ec AND ee -> ef
NOT ak -> al
jl OR jk -> jm
1 AND en -> eo
lb OR la -> lc
iu AND jf -> jh
iu RSHIFT 5 -> ix
bo AND bu -> bw
cz OR cy -> da
iv AND jb -> jd
iw AND ix -> iz
lf RSHIFT 1 -> ly
iu OR jf -> jg
NOT dm -> dn
lw OR lv -> lx
gg LSHIFT 1 -> ha
lr AND lt -> lu
fm OR fn -> fo
he RSHIFT 3 -> hg
aj AND al -> am
1 AND kz -> la
dy RSHIFT 5 -> eb
jc AND je -> jf
cm AND co -> cp
gv AND gx -> gy
ev OR ew -> ex
jp AND ka -> kc
fk OR fj -> fl
dy RSHIFT 3 -> ea
NOT bs -> bt
NOT ag -> ah
dz AND ef -> eh
cf LSHIFT 1 -> cz
NOT cv -> cw
1 AND cx -> cy
de AND dk -> dm
ck AND cl -> cn
x RSHIFT 5 -> aa
dv LSHIFT 1 -> ep
he RSHIFT 2 -> hf
NOT bw -> bx
ck OR cl -> cm
bp AND bq -> bs
as OR bd -> be
he AND hp -> hr
ev AND ew -> ey
1 AND lu -> lv
kk RSHIFT 3 -> km
b AND n -> p
NOT kc -> kd
lc LSHIFT 1 -> lw
km OR kn -> ko
id AND if -> ig
ih AND ij -> ik
jr AND js -> ju
ci RSHIFT 5 -> cl
hz RSHIFT 1 -> is
1 AND ke -> kf
NOT gs -> gt
aw AND ay -> az
x RSHIFT 2 -> y
ab AND ad -> ae
ff AND fh -> fi
ci AND ct -> cv
eq LSHIFT 1 -> fk
gj RSHIFT 3 -> gl
u LSHIFT 1 -> ao
NOT bb -> bc
NOT hj -> hk
kw AND ky -> kz
as AND bd -> bf
dw OR dx -> dy
br AND bt -> bu
kk AND kv -> kx
ep OR eo -> eq
he RSHIFT 1 -> hx
ki OR kj -> kk
NOT ju -> jv
ek AND em -> en
kk RSHIFT 5 -> kn
NOT eh -> ei
hx OR hy -> hz
ea OR eb -> ec
s LSHIFT 15 -> w
fo RSHIFT 1 -> gh
kk OR kv -> kw
bn RSHIFT 5 -> bq
NOT ed -> ee
1 AND ht -> hu
cu AND cw -> cx
b RSHIFT 5 -> f
kl AND kr -> kt
iq OR ip -> ir
ci RSHIFT 2 -> cj
cj OR cp -> cq
o AND q -> r
dd RSHIFT 5 -> dg
b RSHIFT 2 -> d
ks AND ku -> kv
b RSHIFT 3 -> e
d OR j -> k
NOT p -> q
NOT cr -> cs
du OR dt -> dv
kf LSHIFT 15 -> kj
NOT ac -> ad
fo RSHIFT 5 -> fr
hz OR ik -> il
jx AND jz -> ka
gh OR gi -> gj
kk RSHIFT 1 -> ld
hz RSHIFT 5 -> ic
as RSHIFT 2 -> at
NOT jy -> jz
1 AND am -> an
ci OR ct -> cu
hg AND hh -> hj
jq OR jw -> jx
v OR w -> x
la LSHIFT 15 -> le
dh AND dj -> dk
dp AND dr -> ds
jq AND jw -> jy
au OR av -> aw
NOT bf -> bg
z OR aa -> ab
ga AND gc -> gd
hz AND ik -> im
jt AND jv -> jw
z AND aa -> ac
jr OR js -> jt
hb LSHIFT 1 -> hv
hf OR hl -> hm
ib OR ic -> id
fq OR fr -> fs
cq AND cs -> ct
ia OR ig -> ih
dd OR do -> dp
d AND j -> l
ib AND ic -> ie
as RSHIFT 3 -> au
be AND bg -> bh
dd AND do -> dq
NOT l -> m
1 AND gd -> ge
y AND ae -> ag
fo AND fz -> gb
NOT ie -> if
e AND f -> h
x RSHIFT 3 -> z
y OR ae -> af
hf AND hl -> hn
NOT h -> i
NOT hn -> ho
he RSHIFT 5 -> hh

19
2015/d08/ex1/ex1.py Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env python
import ast
import sys
def solve(input: str) -> int:
strings = input.splitlines()
# It's too easy to use the built-in parser not to do it...
return sum(len(raw) - len(ast.literal_eval(raw)) for raw in strings)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

300
2015/d08/ex1/input Normal file
View file

@ -0,0 +1,300 @@
"qxfcsmh"
"ffsfyxbyuhqkpwatkjgudo"
"byc\x9dyxuafof\\\xa6uf\\axfozomj\\olh\x6a"
"jtqvz"
"uzezxa\"jgbmojtwyfbfguz"
"vqsremfk\x8fxiknektafj"
"wzntebpxnnt\"vqndz\"i\x47vvjqo\""
"higvez\"k\"riewqk"
"dlkrbhbrlfrp\\damiauyucwhty"
"d\""
"qlz"
"ku"
"yy\"\"uoao\"uripabop"
"saduyrntuswlnlkuppdro\\sicxosted"
"tj"
"zzphopswlwdhebwkxeurvizdv"
"xfoheirjoakrpofles\"nfu"
"q\xb7oh\"p\xce\"n"
"qeendp\"ercwgywdjeylxcv"
"dcmem"
"\"i\x13r\"l"
"ikso\xdcbvqnbrjduh\"uqudzki\xderwk"
"wfdsn"
"pwynglklryhtsqbno"
"hcoj\x63iccz\"v\"ttr"
"zf\x23\\hlj\\kkce\\d\\asy\"yyfestwcdxyfj"
"xs"
"m\"tvltapxdvtrxiy"
"bmud"
"k\"a"
"b\"oas"
"\"yexnjjupoqsxyqnquy\"uzfdvetqrc"
"vdw\xe3olxfgujaj"
"qomcxdnd\"\\cfoe\""
"fpul"
"m\"avamefphkpv"
"vvdnb\\x\\uhnxfw\"dpubfkxfmeuhnxisd"
"hey\\"
"ldaeigghlfey"
"eure\"hoy\xa5iezjp\\tm"
"yygb\"twbj\\r\"\x10gmxuhmp\""
"weirebp\x39mqonbtmfmd"
"ltuz\\hs\"e"
"ysvmpc"
"g\x8amjtt\"megl\"omsaihifwa"
"yimmm"
"iiyqfalh"
"cwknlaaf"
"q\x37feg\xc6s\"xx"
"uayrgeurgyp\\oi"
"xhug\"pt\"axugllbdiggzhvy"
"kdaarqmsjfx\xc3d"
"\"vkwla"
"d\""
"tmroz\"bvfinxoe\\mum\"wmm"
"\"n\"bbswxne\\p\\yr\"qhwpdd"
"skzlkietklkqovjhvj\xfe"
"pbg\\pab\"bubqaf\"obzcwxwywbs\\dhtq"
"xxjidvqh\"lx\\wu\"ij"
"daef\x5fe\x5b\\kbeeb\x13qnydtboof"
"ogvazaqy\"j\x73"
"y"
"n\"tibetedldy\\gsamm\"nwu"
"wldkvgdtqulwkad"
"dpmxnj"
"twybw\"cdvf\"mjdajurokbce"
"ru\"\\lasij\"i"
"roc\\vra\\lhrm"
"pbkt\x60booz\"fjlkc"
"j\x4dytvjwrzt"
"\\uiwjkniumxcs"
"cbhm\"nexccior\"v\"j\"nazxilmfp\x47"
"qdxngevzrlgoq"
"\"lrzxftytpobsdfyrtdqpjbpuwmm\x9e"
"mdag\x0asnck\xc2ggj\"slb\"fjy"
"wyqkhjuazdtcgkcxvjkpnjdae"
"aixfk\xc0iom\x21vueob"
"dkiiakyjpkffqlluhaetires"
"ysspv\"lysgkvnmwbbsy"
"gy\"ryexcjjxdm\"xswssgtr"
"s"
"ddxv"
"qwt\"\x27puilb\"pslmbrsxhrz"
"qdg\xc9e\\qwtknlvkol\x54oqvmchn\\"
"lvo"
"b"
"fk\"aa\"\"yenwch\\\\on"
"srig\x63hpwaavs\\\x80qzk\"xa\"\xe6u\\wr"
"yxjxuj\"ghyhhxfj\"\xa6qvatre"
"yoktqxjxkzrklkoeroil"
"\"jfmik\""
"smgseztzdwldikbqrh\""
"jftahgctf\"hoqy"
"tcnhicr\"znpgckt\"ble"
"vqktnkodh\"lo\"a\\bkmdjqqnsqr"
"ztnirfzqq"
"s"
"xx"
"iqj\"y\\hqgzflwrdsusasekyrxbp\\ad"
"\\xzjhlaiynkioz\"\"bxepzimvgwt"
"s\x36rbw"
"mniieztwrisvdx"
"atyfxioy\x2b\\"
"irde\x85\x5cvbah\\jekw\"ia"
"bdmftlhkwrprmpat\"prfaocvp"
"w\\k"
"umbpausy"
"zfauhpsangy"
"p\"zqyw"
"wtztypyqvnnxzvlvipnq\"zu"
"deicgwq\\oqvajpbov\\or\"kgplwu"
"mbzlfgpi\\\\zqcidjpzqdzxityxa"
"lfkxvhma"
"\xf2yduqzqr\"\\fak\"p\"n"
"mpajacfuxotonpadvng"
"anb\\telzvcdu\\a\xf2flfq"
"lrs\"ebethwpmuuc\"\x86ygr"
"qmvdbhtumzc\"ci"
"meet"
"yopg\x0fdxdq\"h\\ugsu\xffmolxjv"
"uhy"
"fzgidrtzycsireghazscvmwcfmw\\t"
"cqohkhpgvpru"
"bihyigtnvmevx\"xx"
"xz"
"zofomwotzuxsjk\"q\"mc\"js\"dnmalhxd"
"\\ktnddux\\fqvt\"ibnjntjcbn"
"ia"
"htjadnefwetyp\xd5kbrwfycbyy"
"\"\\hkuxqddnao"
"meqqsz\x83luecpgaem"
"cvks\x87frvxo\"svqivqsdpgwhukmju"
"sgmxiai\\o\"riufxwjfigr\xdf"
"fgywdfecqufccpcdn"
"faghjoq\x28abxnpxj"
"zuppgzcfb\"dctvp\"elup\"zxkopx"
"xqs\x45xxdqcihbwghmzoa"
"anbnlp\\cgcvm\"hc"
"xf\"fgrngwzys"
"nrxsjduedcy\x24"
"\x71sxl\"gj\"sds\"ulcruguz\\t\\ssvjcwhi"
"jhj\"msch"
"qpovolktfwyiuyicbfeeju\x01"
"nkyxmb\"qyqultgt\"nmvzvvnxnb"
"ycsrkbstgzqb\"uv\\cisn"
"s"
"ueptjnn\"\"sh"
"lp\"z\"d\"mxtxiy"
"yzjtvockdnvbubqabjourf\"k\"uoxwle"
"\x82\"wqm\""
"\xb5cwtuks\x5fpgh"
"wd"
"tbvf"
"ttbmzdgn"
"vfpiyfdejyrlbgcdtwzbnm"
"uc"
"otdcmhpjagqix"
"\\\xb1qso\"s"
"scowax"
"behpstjdh\xccqlgnqjyz\"eesn"
"r\xe1cbnjwzveoomkzlo\\kxlfouhm"
"jgrl"
"kzqs\\r"
"ctscb\x7fthwkdyko\"\x62pkf\"d\xe6knmhurg"
"tc\"kw\x3ftt"
"bxb\x5ccl"
"jyrmfbphsldwpq"
"jylpvysl\"\"juducjg"
"en\\m\"kxpq\"wpb\\\""
"madouht\"bmdwvnyqvpnawiphgac\""
"vuxpk\"ltucrw"
"aae\x60arr"
"ttitnne\"kilkrgssnr\xfdurzh"
"oalw"
"pc\"\"gktkdykzbdpkwigucqni\"nxiqx"
"dbrsaj"
"bgzsowyxcbrvhtvekhsh\"qgd"
"kudfemvk\"\"\"hkbrbil\"chkqoa"
"zjzgj\\ekbhyfzufy"
"\\acos\"fqekuxqzxbmkbnn\x1ejzwrm"
"elxahvudn\"txtmomotgw"
"\x2eoxmwdhelpr\"cgi\xf7pzvb"
"eapheklx"
"hfvma\"mietvc\"tszbbm\"czex"
"h\"iiockj\\\xc1et"
"d\"rmjjftm"
"qlvhdcbqtyrhlc\\"
"yy\"rsucjtulm\"coryri\"eqjlbmk"
"tv"
"r\"bfuht\\jjgujp\""
"kukxvuauamtdosngdjlkauylttaokaj"
"srgost\"\"rbkcqtlccu\x65ohjptstrjkzy"
"yxwxl\\yjilwwxffrjjuazmzjs"
"dxlw\\fkstu\"hjrtiafhyuoh\"sewabne"
"\x88sj\"v"
"rfzprz\xec\"oxqclu\"krzefp\\q"
"cfmhdbjuhrcymgxpylllyvpni"
"ucrmjvmimmcq\x88\xd9\"lz"
"lujtt\""
"gvbqoixn\"pmledpjmo\"flydnwkfxllf"
"dvxqlbshhmelsk\x8big\"l"
"mx\x54lma\x8bbguxejg"
"\x66jdati\xeceieo"
"\"iyyupixei\x54ff"
"xohzf\"rbxsoksxamiu"
"vlhthspeshzbppa\x4drhqnohjop\"\"mfjd"
"f\"tvxxla\"vurian\"\"idjq\x3aptm\xc3olep"
"gzqz"
"kbq\\wogye\\altvi\\hbvmodny"
"j\xd8"
"ofjozdhkblvndl"
"hbitoupimbawimxlxqze"
"ypeleimnme"
"xfwdrzsc\\oxqamawyizvi\\y"
"enoikppx\xa1ixe\"yo\"gumye"
"fb"
"vzf"
"zxidr"
"cu\x31beirsywtskq"
"lxpjbvqzztafwezd"
"\\jyxeuo\x18bv"
"b\"vawc\"p\\\\giern\"b"
"odizunx\"\"t\\yicdn\"x\"sdiz"
"\"\"tebrtsi"
"ctyzsxv\xa6pegfkwsi\"tgyltaakytccb"
"htxwbofchvmzbppycccliyik\xe5a"
"ggsslefamsklezqkrd"
"rcep\"fnimwvvdx\"l"
"zyrzlqmd\x12egvqs\\llqyie"
"\x07gsqyrr\\rcyhyspsvn"
"butg\""
"gb"
"gywkoxf\"jsg\\wtopxvumirqxlwz"
"rj\"ir\"wldwveair\x2es\"dhjrdehbqnzl"
"ru\"elktnsbxufk\\ejufjfjlevt\\lrzd"
"\"widsvok"
"oy\"\x81nuesvw"
"ay"
"syticfac\x1cfjsivwlmy\"pumsqlqqzx"
"m"
"rjjkfh\x78cf\x2brgceg\"jmdyas\"\\xlv\xb6p"
"tmuvo\"\x3ffdqdovjmdmkgpstotojkv\"as"
"jd\\ojvynhxllfzzxvbn\"wrpphcvx"
"pz"
"\"twr"
"n\\hdzmxe\"mzjjeadlz"
"fb\"rprxuagvahjnri"
"rfmexmjjgh\\xrnmyvnatrvfruflaqjnd"
"obbbde\"co\"qr\"qpiwjgqahqm\\jjp\""
"vpbq\"\"y\"czk\\b\x52ed\"lnzepobp"
"syzeajzfarplydipny\"y\"\xe8ad"
"mpyodwb"
"\x47rakphlqqptd"
"wa\"oj\"aiy"
"a"
"ropozx"
"q\x51nbtlwa"
"etukvgx\\jqxlkq"
"\"tp\"rah\"pg\"s\"bpdtes\\tkasdhqd"
"dn\"qqpkikadowssb\xcah\"dzpsf\\ect\"jdh"
"pxunovbbrrn\\vullyn\"bno\"\"\"myfxlp\""
"qaixyazuryvkmoulhcqaotegfj\\mpzm"
"bvfrbicutzbjwn\\oml\"cf\"d\"ezcpv\"j"
"rmbrdtneudemigdhelmb"
"aq\\aurmbhy"
"wujqvzw"
"gf\"tssmvm\"gm\"hu\x9a\xb7yjawsa"
"hrhqqxow\xe2gsydtdspcfqy\"zw\\ou"
"ianwwf\\yko\\tdujhhqdi"
"xylz\"zpvpab"
"lwuopbeeegp"
"aoop\x49jhhcexdmdtun"
"\\\\mouqqcsgmz"
"tltuvwhveau\x43b\"ymxjlcgiymcynwt"
"gsugerumpyuhtjljbhrdyoj"
"lnjm\xb8wg\"ajh"
"zmspue\"nfttdon\\b\"eww"
"\"w\x67jwaq\x7ernmyvs\\rmdsuwydsd\"th"
"ogtgvtlmcvgllyv"
"z\"fqi\"rvddoehrciyl"
"yustxxtot\"muec\"xvfdbzunzvveq"
"mqslw"
"txqnyvzmibqgjs\xb6xy\x86nfalfyx"
"kzhehlmkholov"
"plpmywcnirrjutjguosh\\"
"pydbnqofv\"dn\\m"
"aegqof"
"eambmxt\\dxagoogl\\zapfwwlmk"
"afbmqitxxqhddlozuxcpjxgh"
"vgts"
"bfdpqtoxzzhmzcilehnflna"
"s\"idpz"
"\xcfhgly\"nlmztwybx\"ecezmsxaqw"
"aackfgndqcqiy"
"\x22unqdlsrvgzfaohoffgxzfpir\"s"
"abh\"ydv\"kbpdhrerl"
"bdzpg"
"ekwgkywtmzp"
"wtoodejqmrrgslhvnk\"pi\"ldnogpth"
"njro\x68qgbx\xe4af\"\\suan"

23
2015/d08/ex2/ex2.py Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env python
import collections
import sys
def solve(input: str) -> int:
def quote_len(raw: str) -> int:
characters = collections.Counter(raw)
# The `+ 2` is for the surrounding quotes
return characters.total() + characters['"'] + characters["\\"] + 2
strings = input.splitlines()
return sum(quote_len(raw) - len(raw) for raw in strings)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

300
2015/d08/ex2/input Normal file
View file

@ -0,0 +1,300 @@
"qxfcsmh"
"ffsfyxbyuhqkpwatkjgudo"
"byc\x9dyxuafof\\\xa6uf\\axfozomj\\olh\x6a"
"jtqvz"
"uzezxa\"jgbmojtwyfbfguz"
"vqsremfk\x8fxiknektafj"
"wzntebpxnnt\"vqndz\"i\x47vvjqo\""
"higvez\"k\"riewqk"
"dlkrbhbrlfrp\\damiauyucwhty"
"d\""
"qlz"
"ku"
"yy\"\"uoao\"uripabop"
"saduyrntuswlnlkuppdro\\sicxosted"
"tj"
"zzphopswlwdhebwkxeurvizdv"
"xfoheirjoakrpofles\"nfu"
"q\xb7oh\"p\xce\"n"
"qeendp\"ercwgywdjeylxcv"
"dcmem"
"\"i\x13r\"l"
"ikso\xdcbvqnbrjduh\"uqudzki\xderwk"
"wfdsn"
"pwynglklryhtsqbno"
"hcoj\x63iccz\"v\"ttr"
"zf\x23\\hlj\\kkce\\d\\asy\"yyfestwcdxyfj"
"xs"
"m\"tvltapxdvtrxiy"
"bmud"
"k\"a"
"b\"oas"
"\"yexnjjupoqsxyqnquy\"uzfdvetqrc"
"vdw\xe3olxfgujaj"
"qomcxdnd\"\\cfoe\""
"fpul"
"m\"avamefphkpv"
"vvdnb\\x\\uhnxfw\"dpubfkxfmeuhnxisd"
"hey\\"
"ldaeigghlfey"
"eure\"hoy\xa5iezjp\\tm"
"yygb\"twbj\\r\"\x10gmxuhmp\""
"weirebp\x39mqonbtmfmd"
"ltuz\\hs\"e"
"ysvmpc"
"g\x8amjtt\"megl\"omsaihifwa"
"yimmm"
"iiyqfalh"
"cwknlaaf"
"q\x37feg\xc6s\"xx"
"uayrgeurgyp\\oi"
"xhug\"pt\"axugllbdiggzhvy"
"kdaarqmsjfx\xc3d"
"\"vkwla"
"d\""
"tmroz\"bvfinxoe\\mum\"wmm"
"\"n\"bbswxne\\p\\yr\"qhwpdd"
"skzlkietklkqovjhvj\xfe"
"pbg\\pab\"bubqaf\"obzcwxwywbs\\dhtq"
"xxjidvqh\"lx\\wu\"ij"
"daef\x5fe\x5b\\kbeeb\x13qnydtboof"
"ogvazaqy\"j\x73"
"y"
"n\"tibetedldy\\gsamm\"nwu"
"wldkvgdtqulwkad"
"dpmxnj"
"twybw\"cdvf\"mjdajurokbce"
"ru\"\\lasij\"i"
"roc\\vra\\lhrm"
"pbkt\x60booz\"fjlkc"
"j\x4dytvjwrzt"
"\\uiwjkniumxcs"
"cbhm\"nexccior\"v\"j\"nazxilmfp\x47"
"qdxngevzrlgoq"
"\"lrzxftytpobsdfyrtdqpjbpuwmm\x9e"
"mdag\x0asnck\xc2ggj\"slb\"fjy"
"wyqkhjuazdtcgkcxvjkpnjdae"
"aixfk\xc0iom\x21vueob"
"dkiiakyjpkffqlluhaetires"
"ysspv\"lysgkvnmwbbsy"
"gy\"ryexcjjxdm\"xswssgtr"
"s"
"ddxv"
"qwt\"\x27puilb\"pslmbrsxhrz"
"qdg\xc9e\\qwtknlvkol\x54oqvmchn\\"
"lvo"
"b"
"fk\"aa\"\"yenwch\\\\on"
"srig\x63hpwaavs\\\x80qzk\"xa\"\xe6u\\wr"
"yxjxuj\"ghyhhxfj\"\xa6qvatre"
"yoktqxjxkzrklkoeroil"
"\"jfmik\""
"smgseztzdwldikbqrh\""
"jftahgctf\"hoqy"
"tcnhicr\"znpgckt\"ble"
"vqktnkodh\"lo\"a\\bkmdjqqnsqr"
"ztnirfzqq"
"s"
"xx"
"iqj\"y\\hqgzflwrdsusasekyrxbp\\ad"
"\\xzjhlaiynkioz\"\"bxepzimvgwt"
"s\x36rbw"
"mniieztwrisvdx"
"atyfxioy\x2b\\"
"irde\x85\x5cvbah\\jekw\"ia"
"bdmftlhkwrprmpat\"prfaocvp"
"w\\k"
"umbpausy"
"zfauhpsangy"
"p\"zqyw"
"wtztypyqvnnxzvlvipnq\"zu"
"deicgwq\\oqvajpbov\\or\"kgplwu"
"mbzlfgpi\\\\zqcidjpzqdzxityxa"
"lfkxvhma"
"\xf2yduqzqr\"\\fak\"p\"n"
"mpajacfuxotonpadvng"
"anb\\telzvcdu\\a\xf2flfq"
"lrs\"ebethwpmuuc\"\x86ygr"
"qmvdbhtumzc\"ci"
"meet"
"yopg\x0fdxdq\"h\\ugsu\xffmolxjv"
"uhy"
"fzgidrtzycsireghazscvmwcfmw\\t"
"cqohkhpgvpru"
"bihyigtnvmevx\"xx"
"xz"
"zofomwotzuxsjk\"q\"mc\"js\"dnmalhxd"
"\\ktnddux\\fqvt\"ibnjntjcbn"
"ia"
"htjadnefwetyp\xd5kbrwfycbyy"
"\"\\hkuxqddnao"
"meqqsz\x83luecpgaem"
"cvks\x87frvxo\"svqivqsdpgwhukmju"
"sgmxiai\\o\"riufxwjfigr\xdf"
"fgywdfecqufccpcdn"
"faghjoq\x28abxnpxj"
"zuppgzcfb\"dctvp\"elup\"zxkopx"
"xqs\x45xxdqcihbwghmzoa"
"anbnlp\\cgcvm\"hc"
"xf\"fgrngwzys"
"nrxsjduedcy\x24"
"\x71sxl\"gj\"sds\"ulcruguz\\t\\ssvjcwhi"
"jhj\"msch"
"qpovolktfwyiuyicbfeeju\x01"
"nkyxmb\"qyqultgt\"nmvzvvnxnb"
"ycsrkbstgzqb\"uv\\cisn"
"s"
"ueptjnn\"\"sh"
"lp\"z\"d\"mxtxiy"
"yzjtvockdnvbubqabjourf\"k\"uoxwle"
"\x82\"wqm\""
"\xb5cwtuks\x5fpgh"
"wd"
"tbvf"
"ttbmzdgn"
"vfpiyfdejyrlbgcdtwzbnm"
"uc"
"otdcmhpjagqix"
"\\\xb1qso\"s"
"scowax"
"behpstjdh\xccqlgnqjyz\"eesn"
"r\xe1cbnjwzveoomkzlo\\kxlfouhm"
"jgrl"
"kzqs\\r"
"ctscb\x7fthwkdyko\"\x62pkf\"d\xe6knmhurg"
"tc\"kw\x3ftt"
"bxb\x5ccl"
"jyrmfbphsldwpq"
"jylpvysl\"\"juducjg"
"en\\m\"kxpq\"wpb\\\""
"madouht\"bmdwvnyqvpnawiphgac\""
"vuxpk\"ltucrw"
"aae\x60arr"
"ttitnne\"kilkrgssnr\xfdurzh"
"oalw"
"pc\"\"gktkdykzbdpkwigucqni\"nxiqx"
"dbrsaj"
"bgzsowyxcbrvhtvekhsh\"qgd"
"kudfemvk\"\"\"hkbrbil\"chkqoa"
"zjzgj\\ekbhyfzufy"
"\\acos\"fqekuxqzxbmkbnn\x1ejzwrm"
"elxahvudn\"txtmomotgw"
"\x2eoxmwdhelpr\"cgi\xf7pzvb"
"eapheklx"
"hfvma\"mietvc\"tszbbm\"czex"
"h\"iiockj\\\xc1et"
"d\"rmjjftm"
"qlvhdcbqtyrhlc\\"
"yy\"rsucjtulm\"coryri\"eqjlbmk"
"tv"
"r\"bfuht\\jjgujp\""
"kukxvuauamtdosngdjlkauylttaokaj"
"srgost\"\"rbkcqtlccu\x65ohjptstrjkzy"
"yxwxl\\yjilwwxffrjjuazmzjs"
"dxlw\\fkstu\"hjrtiafhyuoh\"sewabne"
"\x88sj\"v"
"rfzprz\xec\"oxqclu\"krzefp\\q"
"cfmhdbjuhrcymgxpylllyvpni"
"ucrmjvmimmcq\x88\xd9\"lz"
"lujtt\""
"gvbqoixn\"pmledpjmo\"flydnwkfxllf"
"dvxqlbshhmelsk\x8big\"l"
"mx\x54lma\x8bbguxejg"
"\x66jdati\xeceieo"
"\"iyyupixei\x54ff"
"xohzf\"rbxsoksxamiu"
"vlhthspeshzbppa\x4drhqnohjop\"\"mfjd"
"f\"tvxxla\"vurian\"\"idjq\x3aptm\xc3olep"
"gzqz"
"kbq\\wogye\\altvi\\hbvmodny"
"j\xd8"
"ofjozdhkblvndl"
"hbitoupimbawimxlxqze"
"ypeleimnme"
"xfwdrzsc\\oxqamawyizvi\\y"
"enoikppx\xa1ixe\"yo\"gumye"
"fb"
"vzf"
"zxidr"
"cu\x31beirsywtskq"
"lxpjbvqzztafwezd"
"\\jyxeuo\x18bv"
"b\"vawc\"p\\\\giern\"b"
"odizunx\"\"t\\yicdn\"x\"sdiz"
"\"\"tebrtsi"
"ctyzsxv\xa6pegfkwsi\"tgyltaakytccb"
"htxwbofchvmzbppycccliyik\xe5a"
"ggsslefamsklezqkrd"
"rcep\"fnimwvvdx\"l"
"zyrzlqmd\x12egvqs\\llqyie"
"\x07gsqyrr\\rcyhyspsvn"
"butg\""
"gb"
"gywkoxf\"jsg\\wtopxvumirqxlwz"
"rj\"ir\"wldwveair\x2es\"dhjrdehbqnzl"
"ru\"elktnsbxufk\\ejufjfjlevt\\lrzd"
"\"widsvok"
"oy\"\x81nuesvw"
"ay"
"syticfac\x1cfjsivwlmy\"pumsqlqqzx"
"m"
"rjjkfh\x78cf\x2brgceg\"jmdyas\"\\xlv\xb6p"
"tmuvo\"\x3ffdqdovjmdmkgpstotojkv\"as"
"jd\\ojvynhxllfzzxvbn\"wrpphcvx"
"pz"
"\"twr"
"n\\hdzmxe\"mzjjeadlz"
"fb\"rprxuagvahjnri"
"rfmexmjjgh\\xrnmyvnatrvfruflaqjnd"
"obbbde\"co\"qr\"qpiwjgqahqm\\jjp\""
"vpbq\"\"y\"czk\\b\x52ed\"lnzepobp"
"syzeajzfarplydipny\"y\"\xe8ad"
"mpyodwb"
"\x47rakphlqqptd"
"wa\"oj\"aiy"
"a"
"ropozx"
"q\x51nbtlwa"
"etukvgx\\jqxlkq"
"\"tp\"rah\"pg\"s\"bpdtes\\tkasdhqd"
"dn\"qqpkikadowssb\xcah\"dzpsf\\ect\"jdh"
"pxunovbbrrn\\vullyn\"bno\"\"\"myfxlp\""
"qaixyazuryvkmoulhcqaotegfj\\mpzm"
"bvfrbicutzbjwn\\oml\"cf\"d\"ezcpv\"j"
"rmbrdtneudemigdhelmb"
"aq\\aurmbhy"
"wujqvzw"
"gf\"tssmvm\"gm\"hu\x9a\xb7yjawsa"
"hrhqqxow\xe2gsydtdspcfqy\"zw\\ou"
"ianwwf\\yko\\tdujhhqdi"
"xylz\"zpvpab"
"lwuopbeeegp"
"aoop\x49jhhcexdmdtun"
"\\\\mouqqcsgmz"
"tltuvwhveau\x43b\"ymxjlcgiymcynwt"
"gsugerumpyuhtjljbhrdyoj"
"lnjm\xb8wg\"ajh"
"zmspue\"nfttdon\\b\"eww"
"\"w\x67jwaq\x7ernmyvs\\rmdsuwydsd\"th"
"ogtgvtlmcvgllyv"
"z\"fqi\"rvddoehrciyl"
"yustxxtot\"muec\"xvfdbzunzvveq"
"mqslw"
"txqnyvzmibqgjs\xb6xy\x86nfalfyx"
"kzhehlmkholov"
"plpmywcnirrjutjguosh\\"
"pydbnqofv\"dn\\m"
"aegqof"
"eambmxt\\dxagoogl\\zapfwwlmk"
"afbmqitxxqhddlozuxcpjxgh"
"vgts"
"bfdpqtoxzzhmzcilehnflna"
"s\"idpz"
"\xcfhgly\"nlmztwybx\"ecezmsxaqw"
"aackfgndqcqiy"
"\x22unqdlsrvgzfaohoffgxzfpir\"s"
"abh\"ydv\"kbpdhrerl"
"bdzpg"
"ekwgkywtmzp"
"wtoodejqmrrgslhvnk\"pi\"ldnogpth"
"njro\x68qgbx\xe4af\"\\suan"

34
2015/d09/ex1/ex1.py Executable file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python
import collections
import itertools
import sys
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, str, int]:
p1, _, p2, _, dist = input.split()
return p1, p2, int(dist)
def parse(input: str) -> dict[str, dict[str, int]]:
res: dict[str, dict[str, int]] = collections.defaultdict(dict)
for p1, p2, dist in map(parse_line, input.splitlines()):
res[p1][p2] = dist
res[p2][p1] = dist
return res
# Boring Traveling Salesman solution
distances = parse(input)
return min(
sum(distances[s][e] for s, e in itertools.pairwise(travel_plan))
for travel_plan in itertools.permutations(distances.keys())
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

28
2015/d09/ex1/input Normal file
View file

@ -0,0 +1,28 @@
Faerun to Norrath = 129
Faerun to Tristram = 58
Faerun to AlphaCentauri = 13
Faerun to Arbre = 24
Faerun to Snowdin = 60
Faerun to Tambi = 71
Faerun to Straylight = 67
Norrath to Tristram = 142
Norrath to AlphaCentauri = 15
Norrath to Arbre = 135
Norrath to Snowdin = 75
Norrath to Tambi = 82
Norrath to Straylight = 54
Tristram to AlphaCentauri = 118
Tristram to Arbre = 122
Tristram to Snowdin = 103
Tristram to Tambi = 49
Tristram to Straylight = 97
AlphaCentauri to Arbre = 116
AlphaCentauri to Snowdin = 12
AlphaCentauri to Tambi = 18
AlphaCentauri to Straylight = 91
Arbre to Snowdin = 129
Arbre to Tambi = 53
Arbre to Straylight = 40
Snowdin to Tambi = 15
Snowdin to Straylight = 99
Tambi to Straylight = 70

34
2015/d09/ex2/ex2.py Executable file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python
import collections
import itertools
import sys
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, str, int]:
p1, _, p2, _, dist = input.split()
return p1, p2, int(dist)
def parse(input: str) -> dict[str, dict[str, int]]:
res: dict[str, dict[str, int]] = collections.defaultdict(dict)
for p1, p2, dist in map(parse_line, input.splitlines()):
res[p1][p2] = dist
res[p2][p1] = dist
return res
# Boring Traveling Salesman solution
distances = parse(input)
return max(
sum(distances[s][e] for s, e in itertools.pairwise(travel_plan))
for travel_plan in itertools.permutations(distances.keys())
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

28
2015/d09/ex2/input Normal file
View file

@ -0,0 +1,28 @@
Faerun to Norrath = 129
Faerun to Tristram = 58
Faerun to AlphaCentauri = 13
Faerun to Arbre = 24
Faerun to Snowdin = 60
Faerun to Tambi = 71
Faerun to Straylight = 67
Norrath to Tristram = 142
Norrath to AlphaCentauri = 15
Norrath to Arbre = 135
Norrath to Snowdin = 75
Norrath to Tambi = 82
Norrath to Straylight = 54
Tristram to AlphaCentauri = 118
Tristram to Arbre = 122
Tristram to Snowdin = 103
Tristram to Tambi = 49
Tristram to Straylight = 97
AlphaCentauri to Arbre = 116
AlphaCentauri to Snowdin = 12
AlphaCentauri to Tambi = 18
AlphaCentauri to Straylight = 91
Arbre to Snowdin = 129
Arbre to Tambi = 53
Arbre to Straylight = 40
Snowdin to Tambi = 15
Snowdin to Straylight = 99
Tambi to Straylight = 70

312
2015/d10/ex1/ex1.py Executable file
View file

@ -0,0 +1,312 @@
#!/usr/bin/env python
import collections
import enum
import sys
# https://en.wikipedia.org/wiki/Look-and-say_sequence#Cosmological_decay
class Atom(enum.StrEnum):
H = "22"
He = "13112221133211322112211213322112"
Li = "312211322212221121123222112"
Be = "111312211312113221133211322112211213322112"
B = "1321132122211322212221121123222112"
C = "3113112211322112211213322112"
N = "111312212221121123222112"
O = "132112211213322112"
F = "31121123222112"
Ne = "111213322112"
Na = "123222112"
Mg = "3113322112"
Al = "1113222112"
Si = "1322112"
P = "311311222112"
S = "1113122112"
Cl = "132112"
Ar = "3112"
K = "1112"
Ca = "12"
Sc = "3113112221133112"
Ti = "11131221131112"
V = "13211312"
Cr = "31132"
Mn = "111311222112"
Fe = "13122112"
Co = "32112"
Ni = "11133112"
Cu = "131112"
Zn = "312"
Ga = "13221133122211332"
Ge = "31131122211311122113222"
As = "11131221131211322113322112"
Se = "13211321222113222112"
Br = "3113112211322112"
Kr = "11131221222112"
Rb = "1321122112"
Sr = "3112112"
Y = "1112133"
Zr = "12322211331222113112211"
Nb = "1113122113322113111221131221"
Mo = "13211322211312113211"
Tc = "311322113212221"
Ru = "132211331222113112211"
Rh = "311311222113111221131221"
Pd = "111312211312113211"
Ag = "132113212221"
Cd = "3113112211"
In = "11131221"
Sn = "13211"
Sb = "3112221"
Te = "1322113312211"
I = "311311222113111221"
Xe = "11131221131211"
Cs = "13211321"
Ba = "311311"
La = "11131"
Ce = "1321133112"
Pr = "31131112"
Nd = "111312"
Pm = "132"
Sm = "311332"
Eu = "1113222"
Gd = "13221133112"
Tb = "3113112221131112"
Dy = "111312211312"
Ho = "1321132"
Er = "311311222"
Tm = "11131221133112"
Yb = "1321131112"
Lu = "311312"
Hf = "11132"
Ta = "13112221133211322112211213322113"
W = "312211322212221121123222113"
Re = "111312211312113221133211322112211213322113"
Os = "1321132122211322212221121123222113"
Ir = "3113112211322112211213322113"
Pt = "111312212221121123222113"
Au = "132112211213322113"
Hg = "31121123222113"
Tl = "111213322113"
Pb = "123222113"
Bi = "3113322113"
Po = "1113222113"
At = "1322113"
Rn = "311311222113"
Fr = "1113122113"
Ra = "132113"
Ac = "3113"
Th = "1113"
Pa = "13"
U = "3"
def decay(self) -> list["Atom"]:
match self:
case Atom.H:
return [Atom.H]
case Atom.He:
return [Atom.Hf, Atom.Pa, Atom.H, Atom.Ca, Atom.Li]
case Atom.Li:
return [Atom.He]
case Atom.Be:
return [Atom.Ge, Atom.Ca, Atom.Li]
case Atom.B:
return [Atom.Be]
case Atom.C:
return [Atom.B]
case Atom.N:
return [Atom.C]
case Atom.O:
return [Atom.N]
case Atom.F:
return [Atom.O]
case Atom.Ne:
return [Atom.F]
case Atom.Na:
return [Atom.Ne]
case Atom.Mg:
return [Atom.Pm, Atom.Na]
case Atom.Al:
return [Atom.Mg]
case Atom.Si:
return [Atom.Al]
case Atom.P:
return [Atom.Ho, Atom.Si]
case Atom.S:
return [Atom.P]
case Atom.Cl:
return [Atom.S]
case Atom.Ar:
return [Atom.Cl]
case Atom.K:
return [Atom.Ar]
case Atom.Ca:
return [Atom.K]
case Atom.Sc:
return [Atom.Ho, Atom.Pa, Atom.H, Atom.Ca, Atom.Co]
case Atom.Ti:
return [Atom.Sc]
case Atom.V:
return [Atom.Ti]
case Atom.Cr:
return [Atom.V]
case Atom.Mn:
return [Atom.Cr, Atom.Si]
case Atom.Fe:
return [Atom.Mn]
case Atom.Co:
return [Atom.Fe]
case Atom.Ni:
return [Atom.Zn, Atom.Co]
case Atom.Cu:
return [Atom.Ni]
case Atom.Zn:
return [Atom.Cu]
case Atom.Ga:
return [Atom.Eu, Atom.Ca, Atom.Ac, Atom.H, Atom.Ca, Atom.Zn]
case Atom.Ge:
return [Atom.Ho, Atom.Ga]
case Atom.As:
return [Atom.Ge, Atom.Na]
case Atom.Se:
return [Atom.As]
case Atom.Br:
return [Atom.Se]
case Atom.Kr:
return [Atom.Br]
case Atom.Rb:
return [Atom.Kr]
case Atom.Sr:
return [Atom.Rb]
case Atom.Y:
return [Atom.Sr, Atom.U]
case Atom.Zr:
return [Atom.Y, Atom.H, Atom.Ca, Atom.Tc]
case Atom.Nb:
return [Atom.Er, Atom.Zr]
case Atom.Mo:
return [Atom.Nb]
case Atom.Tc:
return [Atom.Mo]
case Atom.Ru:
return [Atom.Eu, Atom.Ca, Atom.Tc]
case Atom.Rh:
return [Atom.Ho, Atom.Ru]
case Atom.Pd:
return [Atom.Rh]
case Atom.Ag:
return [Atom.Pd]
case Atom.Cd:
return [Atom.Ag]
case Atom.In:
return [Atom.Cd]
case Atom.Sn:
return [Atom.In]
case Atom.Sb:
return [Atom.Pm, Atom.Sn]
case Atom.Te:
return [Atom.Eu, Atom.Ca, Atom.Sb]
case Atom.I:
return [Atom.Ho, Atom.Te]
case Atom.Xe:
return [Atom.I]
case Atom.Cs:
return [Atom.Xe]
case Atom.Ba:
return [Atom.Cs]
case Atom.La:
return [Atom.Ba]
case Atom.Ce:
return [Atom.La, Atom.H, Atom.Ca, Atom.Co]
case Atom.Pr:
return [Atom.Ce]
case Atom.Nd:
return [Atom.Pr]
case Atom.Pm:
return [Atom.Nd]
case Atom.Sm:
return [Atom.Pm, Atom.Ca, Atom.Zn]
case Atom.Eu:
return [Atom.Sm]
case Atom.Gd:
return [Atom.Eu, Atom.Ca, Atom.Co]
case Atom.Tb:
return [Atom.Ho, Atom.Gd]
case Atom.Dy:
return [Atom.Tb]
case Atom.Ho:
return [Atom.Dy]
case Atom.Er:
return [Atom.Ho, Atom.Pm]
case Atom.Tm:
return [Atom.Er, Atom.Ca, Atom.Co]
case Atom.Yb:
return [Atom.Tm]
case Atom.Lu:
return [Atom.Yb]
case Atom.Hf:
return [Atom.Lu]
case Atom.Ta:
return [Atom.Hf, Atom.Pa, Atom.H, Atom.Ca, Atom.W]
case Atom.W:
return [Atom.Ta]
case Atom.Re:
return [Atom.Ge, Atom.Ca, Atom.W]
case Atom.Os:
return [Atom.Re]
case Atom.Ir:
return [Atom.Os]
case Atom.Pt:
return [Atom.Ir]
case Atom.Au:
return [Atom.Pt]
case Atom.Hg:
return [Atom.Au]
case Atom.Tl:
return [Atom.Hg]
case Atom.Pb:
return [Atom.Tl]
case Atom.Bi:
return [Atom.Pm, Atom.Pb]
case Atom.Po:
return [Atom.Bi]
case Atom.At:
return [Atom.Po]
case Atom.Rn:
return [Atom.Ho, Atom.At]
case Atom.Fr:
return [Atom.Rn]
case Atom.Ra:
return [Atom.Fr]
case Atom.Ac:
return [Atom.Ra]
case Atom.Th:
return [Atom.Ac]
case Atom.Pa:
return [Atom.Th]
case Atom.U:
return [Atom.Pa]
def solve(input: str) -> int:
def look_and_say(atoms: dict[Atom, int]) -> dict[Atom, int]:
res: collections.Counter[Atom] = collections.Counter()
for atom, count in atoms.items():
for split in atom.decay():
res[split] += count
return res
# Happens to work, I assume for all inputs
atoms = {Atom(input.strip()): 1}
for _ in range(40):
atoms = look_and_say(atoms)
return sum(len(atom) * count for atom, count in atoms.items())
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d10/ex1/input Normal file
View file

@ -0,0 +1 @@
3113322113

312
2015/d10/ex2/ex2.py Executable file
View file

@ -0,0 +1,312 @@
#!/usr/bin/env python
import collections
import enum
import sys
# https://en.wikipedia.org/wiki/Look-and-say_sequence#Cosmological_decay
class Atom(enum.StrEnum):
H = "22"
He = "13112221133211322112211213322112"
Li = "312211322212221121123222112"
Be = "111312211312113221133211322112211213322112"
B = "1321132122211322212221121123222112"
C = "3113112211322112211213322112"
N = "111312212221121123222112"
O = "132112211213322112"
F = "31121123222112"
Ne = "111213322112"
Na = "123222112"
Mg = "3113322112"
Al = "1113222112"
Si = "1322112"
P = "311311222112"
S = "1113122112"
Cl = "132112"
Ar = "3112"
K = "1112"
Ca = "12"
Sc = "3113112221133112"
Ti = "11131221131112"
V = "13211312"
Cr = "31132"
Mn = "111311222112"
Fe = "13122112"
Co = "32112"
Ni = "11133112"
Cu = "131112"
Zn = "312"
Ga = "13221133122211332"
Ge = "31131122211311122113222"
As = "11131221131211322113322112"
Se = "13211321222113222112"
Br = "3113112211322112"
Kr = "11131221222112"
Rb = "1321122112"
Sr = "3112112"
Y = "1112133"
Zr = "12322211331222113112211"
Nb = "1113122113322113111221131221"
Mo = "13211322211312113211"
Tc = "311322113212221"
Ru = "132211331222113112211"
Rh = "311311222113111221131221"
Pd = "111312211312113211"
Ag = "132113212221"
Cd = "3113112211"
In = "11131221"
Sn = "13211"
Sb = "3112221"
Te = "1322113312211"
I = "311311222113111221"
Xe = "11131221131211"
Cs = "13211321"
Ba = "311311"
La = "11131"
Ce = "1321133112"
Pr = "31131112"
Nd = "111312"
Pm = "132"
Sm = "311332"
Eu = "1113222"
Gd = "13221133112"
Tb = "3113112221131112"
Dy = "111312211312"
Ho = "1321132"
Er = "311311222"
Tm = "11131221133112"
Yb = "1321131112"
Lu = "311312"
Hf = "11132"
Ta = "13112221133211322112211213322113"
W = "312211322212221121123222113"
Re = "111312211312113221133211322112211213322113"
Os = "1321132122211322212221121123222113"
Ir = "3113112211322112211213322113"
Pt = "111312212221121123222113"
Au = "132112211213322113"
Hg = "31121123222113"
Tl = "111213322113"
Pb = "123222113"
Bi = "3113322113"
Po = "1113222113"
At = "1322113"
Rn = "311311222113"
Fr = "1113122113"
Ra = "132113"
Ac = "3113"
Th = "1113"
Pa = "13"
U = "3"
def decay(self) -> list["Atom"]:
match self:
case Atom.H:
return [Atom.H]
case Atom.He:
return [Atom.Hf, Atom.Pa, Atom.H, Atom.Ca, Atom.Li]
case Atom.Li:
return [Atom.He]
case Atom.Be:
return [Atom.Ge, Atom.Ca, Atom.Li]
case Atom.B:
return [Atom.Be]
case Atom.C:
return [Atom.B]
case Atom.N:
return [Atom.C]
case Atom.O:
return [Atom.N]
case Atom.F:
return [Atom.O]
case Atom.Ne:
return [Atom.F]
case Atom.Na:
return [Atom.Ne]
case Atom.Mg:
return [Atom.Pm, Atom.Na]
case Atom.Al:
return [Atom.Mg]
case Atom.Si:
return [Atom.Al]
case Atom.P:
return [Atom.Ho, Atom.Si]
case Atom.S:
return [Atom.P]
case Atom.Cl:
return [Atom.S]
case Atom.Ar:
return [Atom.Cl]
case Atom.K:
return [Atom.Ar]
case Atom.Ca:
return [Atom.K]
case Atom.Sc:
return [Atom.Ho, Atom.Pa, Atom.H, Atom.Ca, Atom.Co]
case Atom.Ti:
return [Atom.Sc]
case Atom.V:
return [Atom.Ti]
case Atom.Cr:
return [Atom.V]
case Atom.Mn:
return [Atom.Cr, Atom.Si]
case Atom.Fe:
return [Atom.Mn]
case Atom.Co:
return [Atom.Fe]
case Atom.Ni:
return [Atom.Zn, Atom.Co]
case Atom.Cu:
return [Atom.Ni]
case Atom.Zn:
return [Atom.Cu]
case Atom.Ga:
return [Atom.Eu, Atom.Ca, Atom.Ac, Atom.H, Atom.Ca, Atom.Zn]
case Atom.Ge:
return [Atom.Ho, Atom.Ga]
case Atom.As:
return [Atom.Ge, Atom.Na]
case Atom.Se:
return [Atom.As]
case Atom.Br:
return [Atom.Se]
case Atom.Kr:
return [Atom.Br]
case Atom.Rb:
return [Atom.Kr]
case Atom.Sr:
return [Atom.Rb]
case Atom.Y:
return [Atom.Sr, Atom.U]
case Atom.Zr:
return [Atom.Y, Atom.H, Atom.Ca, Atom.Tc]
case Atom.Nb:
return [Atom.Er, Atom.Zr]
case Atom.Mo:
return [Atom.Nb]
case Atom.Tc:
return [Atom.Mo]
case Atom.Ru:
return [Atom.Eu, Atom.Ca, Atom.Tc]
case Atom.Rh:
return [Atom.Ho, Atom.Ru]
case Atom.Pd:
return [Atom.Rh]
case Atom.Ag:
return [Atom.Pd]
case Atom.Cd:
return [Atom.Ag]
case Atom.In:
return [Atom.Cd]
case Atom.Sn:
return [Atom.In]
case Atom.Sb:
return [Atom.Pm, Atom.Sn]
case Atom.Te:
return [Atom.Eu, Atom.Ca, Atom.Sb]
case Atom.I:
return [Atom.Ho, Atom.Te]
case Atom.Xe:
return [Atom.I]
case Atom.Cs:
return [Atom.Xe]
case Atom.Ba:
return [Atom.Cs]
case Atom.La:
return [Atom.Ba]
case Atom.Ce:
return [Atom.La, Atom.H, Atom.Ca, Atom.Co]
case Atom.Pr:
return [Atom.Ce]
case Atom.Nd:
return [Atom.Pr]
case Atom.Pm:
return [Atom.Nd]
case Atom.Sm:
return [Atom.Pm, Atom.Ca, Atom.Zn]
case Atom.Eu:
return [Atom.Sm]
case Atom.Gd:
return [Atom.Eu, Atom.Ca, Atom.Co]
case Atom.Tb:
return [Atom.Ho, Atom.Gd]
case Atom.Dy:
return [Atom.Tb]
case Atom.Ho:
return [Atom.Dy]
case Atom.Er:
return [Atom.Ho, Atom.Pm]
case Atom.Tm:
return [Atom.Er, Atom.Ca, Atom.Co]
case Atom.Yb:
return [Atom.Tm]
case Atom.Lu:
return [Atom.Yb]
case Atom.Hf:
return [Atom.Lu]
case Atom.Ta:
return [Atom.Hf, Atom.Pa, Atom.H, Atom.Ca, Atom.W]
case Atom.W:
return [Atom.Ta]
case Atom.Re:
return [Atom.Ge, Atom.Ca, Atom.W]
case Atom.Os:
return [Atom.Re]
case Atom.Ir:
return [Atom.Os]
case Atom.Pt:
return [Atom.Ir]
case Atom.Au:
return [Atom.Pt]
case Atom.Hg:
return [Atom.Au]
case Atom.Tl:
return [Atom.Hg]
case Atom.Pb:
return [Atom.Tl]
case Atom.Bi:
return [Atom.Pm, Atom.Pb]
case Atom.Po:
return [Atom.Bi]
case Atom.At:
return [Atom.Po]
case Atom.Rn:
return [Atom.Ho, Atom.At]
case Atom.Fr:
return [Atom.Rn]
case Atom.Ra:
return [Atom.Fr]
case Atom.Ac:
return [Atom.Ra]
case Atom.Th:
return [Atom.Ac]
case Atom.Pa:
return [Atom.Th]
case Atom.U:
return [Atom.Pa]
def solve(input: str) -> int:
def look_and_say(atoms: dict[Atom, int]) -> dict[Atom, int]:
res: collections.Counter[Atom] = collections.Counter()
for atom, count in atoms.items():
for split in atom.decay():
res[split] += count
return res
# Happens to work, I assume for all inputs
atoms = {Atom(input.strip()): 1}
for _ in range(50):
atoms = look_and_say(atoms)
return sum(len(atom) * count for atom, count in atoms.items())
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d10/ex2/input Normal file
View file

@ -0,0 +1 @@
3113322113

70
2015/d11/ex1/ex1.py Executable file
View file

@ -0,0 +1,70 @@
#!/usr/bin/env python
import collections
import itertools
import sys
from collections.abc import Iterable, Iterator
from typing import TypeVar
T = TypeVar("T")
def sliding_window(iterable: Iterable[T], n: int) -> Iterator[tuple[T, ...]]:
iterator = iter(iterable)
window = collections.deque(itertools.islice(iterator, n - 1), maxlen=n)
for x in iterator:
window.append(x)
yield tuple(window)
def solve(input: str) -> str:
def parse(input: str) -> int:
res = 0
for c in input.strip():
res = res * 26 + ord(c) - ord("a")
return res
def unparse(n: int) -> str:
# Passwords *must* have 8 characters
assert 0 <= n < 26**8 # Sanity check
return "".join(chr(ord("a") + (n // 26**i) % 26) for i in range(8))[::-1]
def has_straight(password: str) -> bool:
for a, b, c in sliding_window(password, 3):
if ord(a) + 1 == ord(b) and ord(b) + 1 == ord(c):
return True
return False
def no_iol(password: str) -> bool:
return not any(c in password for c in "iol")
def has_couples(password: str) -> bool:
for i, (a, b) in enumerate(itertools.pairwise(password)):
if a != b:
continue
for c, d in itertools.pairwise(password[i + 2 :]):
if c == d:
return True
return False
return False
n = parse(input)
while True:
n = (n + 1) % 26**8 # Restrict password to 8 characters
password = unparse(n)
if not has_straight(password):
continue
if not no_iol(password):
continue
if not has_couples(password):
continue
return password
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d11/ex1/input Normal file
View file

@ -0,0 +1 @@
vzbxkghb

73
2015/d11/ex2/ex2.py Executable file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env python
import collections
import itertools
import sys
from collections.abc import Iterable, Iterator
from typing import TypeVar
T = TypeVar("T")
def sliding_window(iterable: Iterable[T], n: int) -> Iterator[tuple[T, ...]]:
iterator = iter(iterable)
window = collections.deque(itertools.islice(iterator, n - 1), maxlen=n)
for x in iterator:
window.append(x)
yield tuple(window)
def solve(input: str) -> str:
def parse(input: str) -> int:
res = 0
for c in input.strip():
res = res * 26 + ord(c) - ord("a")
return res
def unparse(n: int) -> str:
# Passwords *must* have 8 characters
assert 0 <= n < 26**8 # Sanity check
return "".join(chr(ord("a") + (n // 26**i) % 26) for i in range(8))[::-1]
def has_straight(password: str) -> bool:
for a, b, c in sliding_window(password, 3):
if ord(a) + 1 == ord(b) and ord(b) + 1 == ord(c):
return True
return False
def no_iol(password: str) -> bool:
return not any(c in password for c in "iol")
def has_couples(password: str) -> bool:
for i, (a, b) in enumerate(itertools.pairwise(password)):
if a != b:
continue
for c, d in itertools.pairwise(password[i + 2 :]):
if c == d:
return True
return False
return False
def next_password(password: str) -> str:
n = parse(password)
while True:
n = (n + 1) % 26**8 # Restrict password to 8 characters
password = unparse(n)
if not has_straight(password):
continue
if not no_iol(password):
continue
if not has_couples(password):
continue
return password
return next_password(next_password(input))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d11/ex2/input Normal file
View file

@ -0,0 +1 @@
vzbxkghb

34
2015/d12/ex1/ex1.py Executable file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python
import json
import sys
from collections.abc import Iterator
JSONValue = int | str | list["JSONValue"] | dict[str, "JSONValue"]
def solve(input: str) -> int:
def parse(input: str) -> JSONValue:
return json.loads(input)
def all_numbers(doc: JSONValue) -> Iterator[int]:
if isinstance(doc, int):
yield doc
elif isinstance(doc, list):
for it in doc:
yield from all_numbers(it)
elif isinstance(doc, dict):
for it in doc.values():
yield from all_numbers(it)
doc = parse(input)
return sum(all_numbers(doc))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d12/ex1/input Normal file

File diff suppressed because one or more lines are too long

36
2015/d12/ex2/ex2.py Executable file
View file

@ -0,0 +1,36 @@
#!/usr/bin/env python
import json
import sys
from collections.abc import Iterator
JSONValue = int | str | list["JSONValue"] | dict[str, "JSONValue"]
def solve(input: str) -> int:
def parse(input: str) -> JSONValue:
return json.loads(input)
def all_numbers(doc: JSONValue) -> Iterator[int]:
if isinstance(doc, int):
yield doc
elif isinstance(doc, list):
for it in doc:
yield from all_numbers(it)
elif isinstance(doc, dict):
if "red" in doc.values():
return
for it in doc.values():
yield from all_numbers(it)
doc = parse(input)
return sum(all_numbers(doc))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d12/ex2/input Normal file

File diff suppressed because one or more lines are too long

40
2015/d13/ex1/ex1.py Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
import collections
import itertools
import sys
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, str, int]:
split_input = input.removesuffix(".").split()
p, other = split_input[0], split_input[-1]
delta = int(split_input[3]) * (1 if split_input[2] == "gain" else -1)
return p, other, delta
def parse(input: str) -> dict[str, dict[str, int]]:
res: dict[str, dict[str, int]] = collections.defaultdict(dict)
for p, neighbour, delta in map(parse_line, input.splitlines()):
res[p][neighbour] = delta
return res
def score_seating(deltas: dict[str, dict[str, int]], seating: list[str]) -> int:
table = itertools.chain(seating, [seating[0]])
return sum(
deltas[p1][p2] + deltas[p2][p1] for p1, p2 in itertools.pairwise(table)
)
deltas = parse(input)
return max(
score_seating(deltas, list(perm))
for perm in itertools.permutations(deltas.keys())
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

56
2015/d13/ex1/input Normal file
View file

@ -0,0 +1,56 @@
Alice would gain 2 happiness units by sitting next to Bob.
Alice would gain 26 happiness units by sitting next to Carol.
Alice would lose 82 happiness units by sitting next to David.
Alice would lose 75 happiness units by sitting next to Eric.
Alice would gain 42 happiness units by sitting next to Frank.
Alice would gain 38 happiness units by sitting next to George.
Alice would gain 39 happiness units by sitting next to Mallory.
Bob would gain 40 happiness units by sitting next to Alice.
Bob would lose 61 happiness units by sitting next to Carol.
Bob would lose 15 happiness units by sitting next to David.
Bob would gain 63 happiness units by sitting next to Eric.
Bob would gain 41 happiness units by sitting next to Frank.
Bob would gain 30 happiness units by sitting next to George.
Bob would gain 87 happiness units by sitting next to Mallory.
Carol would lose 35 happiness units by sitting next to Alice.
Carol would lose 99 happiness units by sitting next to Bob.
Carol would lose 51 happiness units by sitting next to David.
Carol would gain 95 happiness units by sitting next to Eric.
Carol would gain 90 happiness units by sitting next to Frank.
Carol would lose 16 happiness units by sitting next to George.
Carol would gain 94 happiness units by sitting next to Mallory.
David would gain 36 happiness units by sitting next to Alice.
David would lose 18 happiness units by sitting next to Bob.
David would lose 65 happiness units by sitting next to Carol.
David would lose 18 happiness units by sitting next to Eric.
David would lose 22 happiness units by sitting next to Frank.
David would gain 2 happiness units by sitting next to George.
David would gain 42 happiness units by sitting next to Mallory.
Eric would lose 65 happiness units by sitting next to Alice.
Eric would gain 24 happiness units by sitting next to Bob.
Eric would gain 100 happiness units by sitting next to Carol.
Eric would gain 51 happiness units by sitting next to David.
Eric would gain 21 happiness units by sitting next to Frank.
Eric would gain 55 happiness units by sitting next to George.
Eric would lose 44 happiness units by sitting next to Mallory.
Frank would lose 48 happiness units by sitting next to Alice.
Frank would gain 91 happiness units by sitting next to Bob.
Frank would gain 8 happiness units by sitting next to Carol.
Frank would lose 66 happiness units by sitting next to David.
Frank would gain 97 happiness units by sitting next to Eric.
Frank would lose 9 happiness units by sitting next to George.
Frank would lose 92 happiness units by sitting next to Mallory.
George would lose 44 happiness units by sitting next to Alice.
George would lose 25 happiness units by sitting next to Bob.
George would gain 17 happiness units by sitting next to Carol.
George would gain 92 happiness units by sitting next to David.
George would lose 92 happiness units by sitting next to Eric.
George would gain 18 happiness units by sitting next to Frank.
George would gain 97 happiness units by sitting next to Mallory.
Mallory would gain 92 happiness units by sitting next to Alice.
Mallory would lose 96 happiness units by sitting next to Bob.
Mallory would lose 51 happiness units by sitting next to Carol.
Mallory would lose 81 happiness units by sitting next to David.
Mallory would gain 31 happiness units by sitting next to Eric.
Mallory would lose 73 happiness units by sitting next to Frank.
Mallory would lose 89 happiness units by sitting next to George.

47
2015/d13/ex2/ex2.py Executable file
View file

@ -0,0 +1,47 @@
#!/usr/bin/env python
import collections
import itertools
import sys
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, str, int]:
split_input = input.removesuffix(".").split()
p, other = split_input[0], split_input[-1]
delta = int(split_input[3]) * (1 if split_input[2] == "gain" else -1)
return p, other, delta
def parse(input: str) -> dict[str, dict[str, int]]:
res: dict[str, dict[str, int]] = collections.defaultdict(dict)
for p, neighbour, delta in map(parse_line, input.splitlines()):
res[p][neighbour] = delta
return res
def score_seating(deltas: dict[str, dict[str, int]], seating: list[str]) -> int:
table = itertools.chain(seating, [seating[0]])
return sum(
deltas[p1][p2] + deltas[p2][p1] for p1, p2 in itertools.pairwise(table)
)
def add_me(deltas: dict[str, dict[str, int]]) -> None:
deltas["me"] = {}
for other in deltas.keys():
deltas["me"][other] = 0
deltas[other]["me"] = 0
deltas = parse(input)
add_me(deltas)
return max(
score_seating(deltas, list(perm))
for perm in itertools.permutations(deltas.keys())
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

56
2015/d13/ex2/input Normal file
View file

@ -0,0 +1,56 @@
Alice would gain 2 happiness units by sitting next to Bob.
Alice would gain 26 happiness units by sitting next to Carol.
Alice would lose 82 happiness units by sitting next to David.
Alice would lose 75 happiness units by sitting next to Eric.
Alice would gain 42 happiness units by sitting next to Frank.
Alice would gain 38 happiness units by sitting next to George.
Alice would gain 39 happiness units by sitting next to Mallory.
Bob would gain 40 happiness units by sitting next to Alice.
Bob would lose 61 happiness units by sitting next to Carol.
Bob would lose 15 happiness units by sitting next to David.
Bob would gain 63 happiness units by sitting next to Eric.
Bob would gain 41 happiness units by sitting next to Frank.
Bob would gain 30 happiness units by sitting next to George.
Bob would gain 87 happiness units by sitting next to Mallory.
Carol would lose 35 happiness units by sitting next to Alice.
Carol would lose 99 happiness units by sitting next to Bob.
Carol would lose 51 happiness units by sitting next to David.
Carol would gain 95 happiness units by sitting next to Eric.
Carol would gain 90 happiness units by sitting next to Frank.
Carol would lose 16 happiness units by sitting next to George.
Carol would gain 94 happiness units by sitting next to Mallory.
David would gain 36 happiness units by sitting next to Alice.
David would lose 18 happiness units by sitting next to Bob.
David would lose 65 happiness units by sitting next to Carol.
David would lose 18 happiness units by sitting next to Eric.
David would lose 22 happiness units by sitting next to Frank.
David would gain 2 happiness units by sitting next to George.
David would gain 42 happiness units by sitting next to Mallory.
Eric would lose 65 happiness units by sitting next to Alice.
Eric would gain 24 happiness units by sitting next to Bob.
Eric would gain 100 happiness units by sitting next to Carol.
Eric would gain 51 happiness units by sitting next to David.
Eric would gain 21 happiness units by sitting next to Frank.
Eric would gain 55 happiness units by sitting next to George.
Eric would lose 44 happiness units by sitting next to Mallory.
Frank would lose 48 happiness units by sitting next to Alice.
Frank would gain 91 happiness units by sitting next to Bob.
Frank would gain 8 happiness units by sitting next to Carol.
Frank would lose 66 happiness units by sitting next to David.
Frank would gain 97 happiness units by sitting next to Eric.
Frank would lose 9 happiness units by sitting next to George.
Frank would lose 92 happiness units by sitting next to Mallory.
George would lose 44 happiness units by sitting next to Alice.
George would lose 25 happiness units by sitting next to Bob.
George would gain 17 happiness units by sitting next to Carol.
George would gain 92 happiness units by sitting next to David.
George would lose 92 happiness units by sitting next to Eric.
George would gain 18 happiness units by sitting next to Frank.
George would gain 97 happiness units by sitting next to Mallory.
Mallory would gain 92 happiness units by sitting next to Alice.
Mallory would lose 96 happiness units by sitting next to Bob.
Mallory would lose 51 happiness units by sitting next to Carol.
Mallory would lose 81 happiness units by sitting next to David.
Mallory would gain 31 happiness units by sitting next to Eric.
Mallory would lose 73 happiness units by sitting next to Frank.
Mallory would lose 89 happiness units by sitting next to George.

39
2015/d14/ex1/ex1.py Executable file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env python
import sys
from typing import NamedTuple
class RunPerformance(NamedTuple):
speed: int
time: int
rest: int
def run(self, t: int) -> int:
cycle_length = self.time + self.rest
cycles = t // cycle_length
left_over = t % cycle_length
run_time = cycles * self.time + min(self.time, left_over)
return self.speed * run_time
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, RunPerformance]:
split_input = input.split()
speed, time, rest = map(int, (split_input[3], split_input[6], split_input[-2]))
return split_input[0], RunPerformance(speed, time, rest)
def parse(input: str) -> dict[str, RunPerformance]:
return {name: perf for name, perf in map(parse_line, input.splitlines())}
reindeers = parse(input)
return max(perf.run(2503) for perf in reindeers.values())
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

9
2015/d14/ex1/input Normal file
View file

@ -0,0 +1,9 @@
Dancer can fly 27 km/s for 5 seconds, but then must rest for 132 seconds.
Cupid can fly 22 km/s for 2 seconds, but then must rest for 41 seconds.
Rudolph can fly 11 km/s for 5 seconds, but then must rest for 48 seconds.
Donner can fly 28 km/s for 5 seconds, but then must rest for 134 seconds.
Dasher can fly 4 km/s for 16 seconds, but then must rest for 55 seconds.
Blitzen can fly 14 km/s for 3 seconds, but then must rest for 38 seconds.
Prancer can fly 3 km/s for 21 seconds, but then must rest for 40 seconds.
Comet can fly 18 km/s for 6 seconds, but then must rest for 103 seconds.
Vixen can fly 18 km/s for 5 seconds, but then must rest for 84 seconds.

50
2015/d14/ex2/ex2.py Executable file
View file

@ -0,0 +1,50 @@
#!/usr/bin/env python
import sys
from typing import NamedTuple
class RunPerformance(NamedTuple):
speed: int
time: int
rest: int
def run(self, t: int) -> int:
cycle_length = self.time + self.rest
cycles = t // cycle_length
left_over = t % cycle_length
run_time = cycles * self.time + min(self.time, left_over)
return self.speed * run_time
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, RunPerformance]:
split_input = input.split()
speed, time, rest = map(int, (split_input[3], split_input[6], split_input[-2]))
return split_input[0], RunPerformance(speed, time, rest)
def parse(input: str) -> dict[str, RunPerformance]:
return {name: perf for name, perf in map(parse_line, input.splitlines())}
def race(reindeers: dict[str, RunPerformance], t: int) -> dict[str, int]:
points = {name: 0 for name in reindeers.keys()}
for i in range(1, t + 1):
# Just re-compute the run every time, it's fast enough
distances = {name: perf.run(i) for name, perf in reindeers.items()}
max_dist = max(distances.values())
for name, distance in distances.items():
points[name] += distance == max_dist
return points
reindeers = parse(input)
scores = race(reindeers, 2503)
return max(scores.values())
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

9
2015/d14/ex2/input Normal file
View file

@ -0,0 +1,9 @@
Dancer can fly 27 km/s for 5 seconds, but then must rest for 132 seconds.
Cupid can fly 22 km/s for 2 seconds, but then must rest for 41 seconds.
Rudolph can fly 11 km/s for 5 seconds, but then must rest for 48 seconds.
Donner can fly 28 km/s for 5 seconds, but then must rest for 134 seconds.
Dasher can fly 4 km/s for 16 seconds, but then must rest for 55 seconds.
Blitzen can fly 14 km/s for 3 seconds, but then must rest for 38 seconds.
Prancer can fly 3 km/s for 21 seconds, but then must rest for 40 seconds.
Comet can fly 18 km/s for 6 seconds, but then must rest for 103 seconds.
Vixen can fly 18 km/s for 5 seconds, but then must rest for 84 seconds.

73
2015/d15/ex1/ex1.py Executable file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env python
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Properties(NamedTuple):
capacity: int
durability: int
flavor: int
texture: int
calories: int
@classmethod
def from_str(cls, input: str) -> "Properties":
properties = map(str.split, input.split(", "))
return cls(*(int(prop[-1]) for prop in properties))
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, Properties]:
ingredient, properties = input.split(": ")
return ingredient, Properties.from_str(properties)
def parse(input: str) -> dict[str, Properties]:
return {name: prop for name, prop in map(parse_line, input.splitlines())}
def score(ingredients: dict[str, Properties], amounts: dict[str, int]) -> int:
assert ingredients.keys() == amounts.keys() # Sanity check
assert sum(amounts.values()) == 100 # Sanity check
res = 1
for prop in ("capacity", "durability", "flavor", "texture"):
res *= max(
0,
sum(
getattr(ingredients[name], prop) * amounts[name]
for name in ingredients.keys()
),
)
return res
def permute_amounts(ingredients: dict[str, Properties]) -> Iterator[dict[str, int]]:
def helper(amounts: dict[str, int]) -> Iterator[dict[str, int]]:
remaining = 100 - sum(amounts.values())
assert remaining >= 0 # Sanity check
assert ingredients # Sanity check
current = next(iter(n for n in ingredients.keys() if n not in amounts))
if (len(amounts) + 1) == len(ingredients):
yield amounts | {current: remaining}
else:
for i in range(remaining):
yield from helper(amounts | {current: i})
yield from helper({})
def maximize_score(ingredient: dict[str, Properties]) -> int:
return max(
score(ingredient, amounts) for amounts in permute_amounts(ingredients)
)
ingredients = parse(input)
return maximize_score(ingredients)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

4
2015/d15/ex1/input Normal file
View file

@ -0,0 +1,4 @@
Sprinkles: capacity 5, durability -1, flavor 0, texture 0, calories 5
PeanutButter: capacity -1, durability 3, flavor 0, texture 0, calories 1
Frosting: capacity 0, durability -1, flavor 4, texture 0, calories 6
Sugar: capacity -1, durability 0, flavor 0, texture 2, calories 8

85
2015/d15/ex2/ex2.py Executable file
View file

@ -0,0 +1,85 @@
#!/usr/bin/env python
import sys
from collections.abc import Iterator
from typing import Literal, NamedTuple, cast
class Properties(NamedTuple):
capacity: int
durability: int
flavor: int
texture: int
calories: int
@classmethod
def from_str(cls, input: str) -> "Properties":
properties = map(str.split, input.split(", "))
return cls(*(int(prop[-1]) for prop in properties))
PropertyName = Literal["capacity", "durability", "flavor", "texture", "calories"]
def solve(input: str) -> int:
def parse_line(input: str) -> tuple[str, Properties]:
ingredient, properties = input.split(": ")
return ingredient, Properties.from_str(properties)
def parse(input: str) -> dict[str, Properties]:
return {name: prop for name, prop in map(parse_line, input.splitlines())}
def sum_properties(
ingredients: dict[str, Properties],
amounts: dict[str, int],
prop: PropertyName,
) -> int:
return sum(
getattr(ingredients[name], prop) * amounts[name]
for name in ingredients.keys()
)
def score(ingredients: dict[str, Properties], amounts: dict[str, int]) -> int:
assert ingredients.keys() == amounts.keys() # Sanity check
assert sum(amounts.values()) == 100 # Sanity check
res = 1
for prop in ("capacity", "durability", "flavor", "texture"):
res *= max(
0,
sum_properties(ingredients, amounts, cast(PropertyName, prop)),
)
return res
def permute_amounts(ingredients: dict[str, Properties]) -> Iterator[dict[str, int]]:
def helper(amounts: dict[str, int]) -> Iterator[dict[str, int]]:
remaining = 100 - sum(amounts.values())
assert remaining >= 0 # Sanity check
assert ingredients # Sanity check
current = next(iter(n for n in ingredients.keys() if n not in amounts))
if (len(amounts) + 1) == len(ingredients):
yield amounts | {current: remaining}
else:
for i in range(remaining):
yield from helper(amounts | {current: i})
yield from helper({})
def maximize_score(ingredient: dict[str, Properties]) -> int:
return max(
score(ingredient, amounts)
for amounts in permute_amounts(ingredients)
if sum_properties(ingredient, amounts, "calories") == 500
)
ingredients = parse(input)
return maximize_score(ingredients)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

4
2015/d15/ex2/input Normal file
View file

@ -0,0 +1,4 @@
Sprinkles: capacity 5, durability -1, flavor 0, texture 0, calories 5
PeanutButter: capacity -1, durability 3, flavor 0, texture 0, calories 1
Frosting: capacity 0, durability -1, flavor 4, texture 0, calories 6
Sugar: capacity -1, durability 0, flavor 0, texture 2, calories 8

62
2015/d16/ex1/ex1.py Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python
import sys
from typing import NamedTuple
class Sue(NamedTuple):
children: int | None = None
cats: int | None = None
samoyeds: int | None = None
pomeranians: int | None = None
akitas: int | None = None
vizslas: int | None = None
goldfish: int | None = None
trees: int | None = None
cars: int | None = None
perfumes: int | None = None
def matches(self, reading: "Sue") -> bool:
for it, reading_it in zip(self, reading):
if it is None or reading_it is None:
continue
if it != reading_it:
return False
return True
def solve(input: str) -> int:
def parse_line(input: str) -> Sue:
_, other = input.split(": ", 1)
raw_items = other.split(", ")
items = {
name: int(val) for name, val in (item.split(": ") for item in raw_items)
}
return Sue(**items)
def parse(input: str) -> list[Sue]:
return [parse_line(line) for line in input.splitlines()]
aunts = parse(input)
reading = Sue(
children=3,
cats=7,
samoyeds=2,
pomeranians=3,
akitas=0,
vizslas=0,
goldfish=5,
trees=3,
cars=2,
perfumes=1,
)
return next(i for i, sue in enumerate(aunts, 1) if sue.matches(reading))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

500
2015/d16/ex1/input Normal file
View file

@ -0,0 +1,500 @@
Sue 1: goldfish: 6, trees: 9, akitas: 0
Sue 2: goldfish: 7, trees: 1, akitas: 0
Sue 3: cars: 10, akitas: 6, perfumes: 7
Sue 4: perfumes: 2, vizslas: 0, cars: 6
Sue 5: goldfish: 1, trees: 3, perfumes: 10
Sue 6: children: 9, vizslas: 7, cars: 9
Sue 7: cars: 6, vizslas: 5, cats: 3
Sue 8: akitas: 10, vizslas: 9, children: 3
Sue 9: vizslas: 8, cats: 2, trees: 1
Sue 10: perfumes: 10, trees: 6, cars: 4
Sue 11: cars: 9, children: 1, cats: 1
Sue 12: pomeranians: 4, akitas: 6, goldfish: 8
Sue 13: cats: 10, children: 5, trees: 9
Sue 14: perfumes: 8, vizslas: 3, samoyeds: 1
Sue 15: vizslas: 2, perfumes: 8, trees: 3
Sue 16: pomeranians: 10, trees: 9, samoyeds: 4
Sue 17: akitas: 7, vizslas: 0, goldfish: 6
Sue 18: trees: 5, vizslas: 9, cars: 0
Sue 19: akitas: 3, goldfish: 9, trees: 10
Sue 20: perfumes: 7, samoyeds: 3, vizslas: 10
Sue 21: perfumes: 7, pomeranians: 10, akitas: 8
Sue 22: vizslas: 6, trees: 8, akitas: 10
Sue 23: goldfish: 0, trees: 4, children: 9
Sue 24: goldfish: 7, pomeranians: 9, akitas: 4
Sue 25: cars: 7, trees: 4, pomeranians: 4
Sue 26: trees: 9, akitas: 9, pomeranians: 7
Sue 27: samoyeds: 0, perfumes: 9, goldfish: 10
Sue 28: cars: 5, trees: 7, vizslas: 1
Sue 29: perfumes: 9, trees: 1, children: 6
Sue 30: goldfish: 10, trees: 0, cars: 4
Sue 31: akitas: 2, perfumes: 5, goldfish: 5
Sue 32: goldfish: 0, akitas: 5, trees: 0
Sue 33: vizslas: 2, akitas: 2, samoyeds: 3
Sue 34: goldfish: 8, perfumes: 5, cars: 3
Sue 35: akitas: 1, cats: 4, trees: 9
Sue 36: cars: 4, vizslas: 4, goldfish: 7
Sue 37: akitas: 5, perfumes: 7, trees: 3
Sue 38: goldfish: 10, trees: 2, vizslas: 9
Sue 39: goldfish: 4, pomeranians: 5, vizslas: 5
Sue 40: perfumes: 5, samoyeds: 4, akitas: 6
Sue 41: goldfish: 9, cars: 4, perfumes: 5
Sue 42: trees: 6, pomeranians: 9, goldfish: 8
Sue 43: perfumes: 7, pomeranians: 1, akitas: 2
Sue 44: vizslas: 9, cars: 5, cats: 0
Sue 45: akitas: 1, goldfish: 6, trees: 0
Sue 46: akitas: 5, vizslas: 8, trees: 2
Sue 47: trees: 9, akitas: 2, vizslas: 9
Sue 48: goldfish: 10, trees: 5, akitas: 2
Sue 49: cars: 7, vizslas: 2, perfumes: 6
Sue 50: akitas: 5, goldfish: 6, perfumes: 0
Sue 51: cars: 9, cats: 7, trees: 5
Sue 52: akitas: 7, goldfish: 10, cars: 0
Sue 53: cars: 10, cats: 4, perfumes: 2
Sue 54: goldfish: 2, pomeranians: 5, perfumes: 10
Sue 55: vizslas: 5, akitas: 4, cars: 8
Sue 56: goldfish: 9, vizslas: 4, akitas: 5
Sue 57: perfumes: 8, samoyeds: 7, cars: 9
Sue 58: cars: 5, akitas: 7, perfumes: 8
Sue 59: samoyeds: 8, cars: 10, vizslas: 10
Sue 60: akitas: 6, samoyeds: 0, goldfish: 3
Sue 61: trees: 8, pomeranians: 0, akitas: 2
Sue 62: trees: 1, perfumes: 3, vizslas: 4
Sue 63: vizslas: 6, samoyeds: 9, goldfish: 8
Sue 64: goldfish: 7, trees: 6, vizslas: 3
Sue 65: cars: 1, vizslas: 0, akitas: 6
Sue 66: cats: 6, pomeranians: 4, cars: 9
Sue 67: trees: 10, pomeranians: 7, samoyeds: 3
Sue 68: pomeranians: 5, goldfish: 9, akitas: 1
Sue 69: akitas: 1, vizslas: 0, trees: 9
Sue 70: cats: 4, goldfish: 4, vizslas: 10
Sue 71: vizslas: 7, perfumes: 7, trees: 8
Sue 72: children: 2, vizslas: 9, cats: 3
Sue 73: cars: 8, pomeranians: 0, perfumes: 6
Sue 74: akitas: 1, pomeranians: 8, vizslas: 10
Sue 75: vizslas: 5, perfumes: 5, cars: 7
Sue 76: cars: 3, vizslas: 3, goldfish: 0
Sue 77: akitas: 9, samoyeds: 1, pomeranians: 3
Sue 78: trees: 0, vizslas: 0, akitas: 6
Sue 79: pomeranians: 9, cars: 1, perfumes: 0
Sue 80: perfumes: 10, trees: 1, cats: 0
Sue 81: goldfish: 5, akitas: 9, trees: 0
Sue 82: vizslas: 1, akitas: 6, children: 4
Sue 83: samoyeds: 7, perfumes: 8, pomeranians: 4
Sue 84: perfumes: 3, children: 3, cats: 7
Sue 85: goldfish: 9, trees: 3, cars: 9
Sue 86: cars: 0, perfumes: 9, vizslas: 0
Sue 87: children: 3, trees: 4, akitas: 3
Sue 88: trees: 1, samoyeds: 1, goldfish: 0
Sue 89: akitas: 8, cars: 3, vizslas: 9
Sue 90: pomeranians: 9, trees: 9, goldfish: 8
Sue 91: goldfish: 7, trees: 10, children: 0
Sue 92: cats: 9, cars: 7, perfumes: 7
Sue 93: vizslas: 2, goldfish: 7, cats: 9
Sue 94: akitas: 5, cars: 8, vizslas: 4
Sue 95: goldfish: 7, vizslas: 1, perfumes: 2
Sue 96: goldfish: 5, trees: 6, perfumes: 10
Sue 97: trees: 0, perfumes: 7, cars: 0
Sue 98: cars: 2, perfumes: 6, trees: 8
Sue 99: trees: 10, children: 7, cats: 9
Sue 100: samoyeds: 5, goldfish: 6, vizslas: 6
Sue 101: cars: 10, perfumes: 9, vizslas: 3
Sue 102: pomeranians: 6, trees: 1, samoyeds: 4
Sue 103: cars: 2, perfumes: 1, goldfish: 5
Sue 104: goldfish: 2, cars: 8, pomeranians: 2
Sue 105: goldfish: 6, vizslas: 0, trees: 10
Sue 106: trees: 10, akitas: 10, pomeranians: 0
Sue 107: vizslas: 2, pomeranians: 10, trees: 3
Sue 108: children: 3, vizslas: 8, akitas: 7
Sue 109: perfumes: 2, akitas: 2, samoyeds: 3
Sue 110: goldfish: 7, trees: 1, perfumes: 1
Sue 111: akitas: 2, cars: 9, perfumes: 2
Sue 112: children: 10, cars: 0, akitas: 3
Sue 113: akitas: 9, vizslas: 4, children: 3
Sue 114: pomeranians: 3, trees: 2, goldfish: 5
Sue 115: perfumes: 8, cars: 6, trees: 0
Sue 116: samoyeds: 6, children: 3, pomeranians: 1
Sue 117: goldfish: 1, trees: 2, akitas: 1
Sue 118: goldfish: 10, akitas: 10, samoyeds: 0
Sue 119: vizslas: 10, perfumes: 6, cars: 0
Sue 120: cars: 2, perfumes: 9, goldfish: 5
Sue 121: vizslas: 2, trees: 2, cars: 6
Sue 122: vizslas: 3, trees: 0, akitas: 2
Sue 123: akitas: 5, samoyeds: 7, goldfish: 1
Sue 124: goldfish: 8, samoyeds: 7, trees: 8
Sue 125: trees: 3, goldfish: 8, perfumes: 5
Sue 126: cats: 3, vizslas: 9, goldfish: 0
Sue 127: pomeranians: 9, goldfish: 3, perfumes: 6
Sue 128: vizslas: 4, cars: 8, goldfish: 5
Sue 129: vizslas: 8, children: 5, perfumes: 8
Sue 130: cars: 7, children: 7, cats: 3
Sue 131: perfumes: 1, akitas: 8, vizslas: 9
Sue 132: perfumes: 7, samoyeds: 10, pomeranians: 6
Sue 133: cars: 5, perfumes: 3, goldfish: 7
Sue 134: perfumes: 9, akitas: 2, cats: 3
Sue 135: perfumes: 1, trees: 9, vizslas: 9
Sue 136: akitas: 7, cars: 3, perfumes: 7
Sue 137: vizslas: 9, goldfish: 8, cars: 5
Sue 138: trees: 0, samoyeds: 1, cars: 3
Sue 139: cars: 0, perfumes: 6, trees: 0
Sue 140: pomeranians: 4, cars: 1, perfumes: 7
Sue 141: vizslas: 10, akitas: 8, cats: 3
Sue 142: trees: 1, cats: 6, vizslas: 5
Sue 143: pomeranians: 9, cars: 7, perfumes: 9
Sue 144: cars: 0, perfumes: 2, pomeranians: 1
Sue 145: trees: 1, goldfish: 9, perfumes: 8
Sue 146: cars: 8, children: 5, vizslas: 2
Sue 147: perfumes: 2, goldfish: 5, cars: 0
Sue 148: akitas: 2, perfumes: 7, pomeranians: 6
Sue 149: goldfish: 8, cars: 0, trees: 1
Sue 150: akitas: 6, perfumes: 5, trees: 0
Sue 151: vizslas: 6, samoyeds: 8, akitas: 10
Sue 152: trees: 7, akitas: 7, perfumes: 6
Sue 153: goldfish: 9, cats: 9, cars: 3
Sue 154: vizslas: 10, trees: 0, cars: 9
Sue 155: perfumes: 3, children: 2, goldfish: 1
Sue 156: goldfish: 7, perfumes: 5, akitas: 6
Sue 157: cats: 10, trees: 1, goldfish: 0
Sue 158: cats: 7, children: 7, vizslas: 6
Sue 159: perfumes: 9, akitas: 0, cars: 0
Sue 160: akitas: 3, goldfish: 10, pomeranians: 2
Sue 161: goldfish: 10, cars: 6, perfumes: 3
Sue 162: trees: 0, cars: 9, goldfish: 1
Sue 163: cars: 8, perfumes: 9, vizslas: 5
Sue 164: goldfish: 1, trees: 10, children: 6
Sue 165: goldfish: 0, vizslas: 6, cars: 0
Sue 166: akitas: 5, vizslas: 1, cars: 5
Sue 167: vizslas: 1, samoyeds: 1, children: 4
Sue 168: samoyeds: 7, vizslas: 7, akitas: 3
Sue 169: goldfish: 3, cats: 9, trees: 2
Sue 170: cars: 5, perfumes: 9, vizslas: 5
Sue 171: goldfish: 7, cars: 6, perfumes: 10
Sue 172: cats: 6, akitas: 1, children: 6
Sue 173: cats: 4, goldfish: 1, children: 3
Sue 174: cars: 2, pomeranians: 2, vizslas: 7
Sue 175: trees: 0, children: 4, goldfish: 7
Sue 176: children: 8, cars: 5, cats: 9
Sue 177: pomeranians: 4, vizslas: 7, trees: 3
Sue 178: vizslas: 6, perfumes: 10, akitas: 6
Sue 179: cars: 4, akitas: 4, trees: 4
Sue 180: akitas: 8, goldfish: 6, trees: 9
Sue 181: perfumes: 3, vizslas: 10, cars: 3
Sue 182: vizslas: 3, samoyeds: 3, goldfish: 7
Sue 183: goldfish: 10, perfumes: 2, cats: 1
Sue 184: goldfish: 5, trees: 1, perfumes: 1
Sue 185: vizslas: 10, trees: 9, perfumes: 2
Sue 186: goldfish: 6, perfumes: 9, trees: 1
Sue 187: cars: 0, trees: 9, goldfish: 6
Sue 188: cars: 0, trees: 1, vizslas: 9
Sue 189: akitas: 7, vizslas: 2, trees: 0
Sue 190: pomeranians: 5, perfumes: 8, akitas: 10
Sue 191: vizslas: 5, akitas: 3, cats: 0
Sue 192: children: 1, trees: 1, cars: 2
Sue 193: cars: 3, goldfish: 9, trees: 2
Sue 194: samoyeds: 3, akitas: 4, perfumes: 8
Sue 195: trees: 1, vizslas: 8, akitas: 10
Sue 196: akitas: 6, cars: 5, pomeranians: 0
Sue 197: akitas: 5, vizslas: 5, cats: 1
Sue 198: trees: 4, cars: 6, goldfish: 6
Sue 199: cats: 7, cars: 5, goldfish: 6
Sue 200: vizslas: 4, cats: 0, akitas: 9
Sue 201: pomeranians: 1, perfumes: 4, children: 2
Sue 202: cats: 1, perfumes: 4, vizslas: 3
Sue 203: vizslas: 1, akitas: 9, children: 5
Sue 204: perfumes: 8, cars: 7, trees: 4
Sue 205: perfumes: 7, pomeranians: 5, cats: 9
Sue 206: vizslas: 8, trees: 2, akitas: 2
Sue 207: akitas: 6, vizslas: 2, perfumes: 10
Sue 208: vizslas: 1, children: 7, akitas: 4
Sue 209: perfumes: 4, trees: 2, children: 1
Sue 210: goldfish: 0, vizslas: 2, samoyeds: 10
Sue 211: cars: 8, perfumes: 3, trees: 1
Sue 212: cars: 8, samoyeds: 5, pomeranians: 8
Sue 213: akitas: 2, goldfish: 8, pomeranians: 2
Sue 214: akitas: 6, pomeranians: 2, cars: 0
Sue 215: trees: 10, pomeranians: 4, vizslas: 0
Sue 216: perfumes: 0, cars: 8, trees: 0
Sue 217: samoyeds: 8, akitas: 7, children: 10
Sue 218: perfumes: 1, vizslas: 6, children: 0
Sue 219: children: 1, goldfish: 4, trees: 1
Sue 220: akitas: 10, goldfish: 10, trees: 5
Sue 221: cars: 7, pomeranians: 6, perfumes: 3
Sue 222: vizslas: 6, children: 0, akitas: 5
Sue 223: perfumes: 9, cars: 1, trees: 6
Sue 224: pomeranians: 1, trees: 0, vizslas: 0
Sue 225: goldfish: 8, akitas: 4, perfumes: 10
Sue 226: pomeranians: 7, cats: 7, children: 4
Sue 227: trees: 0, akitas: 2, perfumes: 1
Sue 228: vizslas: 6, cars: 10, perfumes: 9
Sue 229: cars: 0, perfumes: 6, trees: 4
Sue 230: pomeranians: 7, perfumes: 5, trees: 2
Sue 231: goldfish: 9, cars: 6, trees: 7
Sue 232: akitas: 1, vizslas: 5, cars: 3
Sue 233: akitas: 7, samoyeds: 2, vizslas: 5
Sue 234: akitas: 6, cats: 8, pomeranians: 0
Sue 235: pomeranians: 5, akitas: 5, vizslas: 3
Sue 236: goldfish: 5, trees: 6, akitas: 5
Sue 237: goldfish: 9, perfumes: 5, cats: 5
Sue 238: cats: 8, goldfish: 4, perfumes: 0
Sue 239: samoyeds: 8, children: 6, pomeranians: 6
Sue 240: akitas: 4, samoyeds: 10, trees: 8
Sue 241: trees: 2, goldfish: 8, cars: 1
Sue 242: perfumes: 2, cars: 0, akitas: 10
Sue 243: pomeranians: 1, cars: 7, trees: 2
Sue 244: trees: 9, vizslas: 2, akitas: 10
Sue 245: cars: 9, pomeranians: 4, trees: 0
Sue 246: cars: 9, pomeranians: 7, perfumes: 1
Sue 247: trees: 0, goldfish: 1, akitas: 8
Sue 248: vizslas: 1, cats: 4, akitas: 4
Sue 249: cats: 6, children: 4, goldfish: 9
Sue 250: vizslas: 1, cars: 10, samoyeds: 5
Sue 251: cars: 0, goldfish: 1, vizslas: 7
Sue 252: cars: 7, akitas: 9, vizslas: 10
Sue 253: akitas: 7, vizslas: 2, perfumes: 5
Sue 254: vizslas: 10, akitas: 5, samoyeds: 0
Sue 255: pomeranians: 8, goldfish: 0, cats: 6
Sue 256: cars: 10, goldfish: 8, vizslas: 9
Sue 257: goldfish: 3, perfumes: 9, cats: 3
Sue 258: trees: 6, goldfish: 6, cars: 6
Sue 259: trees: 0, goldfish: 2, perfumes: 8
Sue 260: trees: 5, akitas: 0, cars: 0
Sue 261: pomeranians: 9, goldfish: 7, perfumes: 8
Sue 262: perfumes: 8, vizslas: 6, goldfish: 2
Sue 263: vizslas: 6, trees: 5, goldfish: 9
Sue 264: vizslas: 4, perfumes: 7, cars: 9
Sue 265: goldfish: 10, trees: 3, perfumes: 1
Sue 266: trees: 10, akitas: 8, goldfish: 8
Sue 267: goldfish: 4, trees: 0, samoyeds: 9
Sue 268: vizslas: 1, trees: 0, goldfish: 8
Sue 269: cars: 2, perfumes: 10, goldfish: 5
Sue 270: perfumes: 7, cars: 2, vizslas: 1
Sue 271: cars: 6, perfumes: 10, goldfish: 6
Sue 272: samoyeds: 4, goldfish: 2, vizslas: 9
Sue 273: perfumes: 4, goldfish: 4, vizslas: 1
Sue 274: children: 4, cars: 4, perfumes: 3
Sue 275: children: 8, vizslas: 3, trees: 2
Sue 276: vizslas: 5, children: 7, perfumes: 3
Sue 277: perfumes: 3, cats: 4, vizslas: 5
Sue 278: cars: 1, samoyeds: 10, akitas: 2
Sue 279: trees: 9, perfumes: 9, cars: 10
Sue 280: vizslas: 5, trees: 0, perfumes: 6
Sue 281: vizslas: 3, akitas: 10, pomeranians: 7
Sue 282: trees: 1, children: 2, akitas: 8
Sue 283: akitas: 9, goldfish: 6, cats: 5
Sue 284: cars: 9, children: 10, pomeranians: 2
Sue 285: pomeranians: 0, perfumes: 4, cars: 7
Sue 286: perfumes: 0, vizslas: 10, akitas: 10
Sue 287: cats: 2, perfumes: 3, trees: 5
Sue 288: akitas: 9, vizslas: 8, samoyeds: 9
Sue 289: perfumes: 6, children: 2, cars: 7
Sue 290: akitas: 0, children: 5, cars: 5
Sue 291: cars: 4, perfumes: 0, trees: 1
Sue 292: cats: 0, cars: 8, perfumes: 6
Sue 293: akitas: 9, cats: 5, children: 5
Sue 294: akitas: 4, cars: 9, goldfish: 3
Sue 295: cars: 2, akitas: 3, perfumes: 7
Sue 296: perfumes: 4, cars: 7, goldfish: 10
Sue 297: trees: 5, akitas: 8, vizslas: 1
Sue 298: perfumes: 0, goldfish: 6, trees: 9
Sue 299: perfumes: 6, samoyeds: 8, cars: 1
Sue 300: goldfish: 10, perfumes: 4, akitas: 2
Sue 301: cars: 3, trees: 0, goldfish: 8
Sue 302: perfumes: 7, samoyeds: 2, vizslas: 7
Sue 303: children: 10, goldfish: 7, perfumes: 2
Sue 304: samoyeds: 8, vizslas: 2, cars: 1
Sue 305: trees: 1, cats: 0, goldfish: 10
Sue 306: trees: 4, perfumes: 2, cars: 7
Sue 307: cars: 6, vizslas: 2, children: 6
Sue 308: vizslas: 2, cars: 0, akitas: 7
Sue 309: cars: 3, vizslas: 8, perfumes: 6
Sue 310: goldfish: 7, perfumes: 7, vizslas: 3
Sue 311: pomeranians: 10, trees: 2, cars: 0
Sue 312: samoyeds: 2, vizslas: 9, akitas: 1
Sue 313: cars: 4, pomeranians: 7, goldfish: 7
Sue 314: akitas: 2, pomeranians: 9, samoyeds: 10
Sue 315: akitas: 3, vizslas: 2, trees: 0
Sue 316: cars: 0, perfumes: 4, pomeranians: 6
Sue 317: akitas: 10, goldfish: 3, pomeranians: 7
Sue 318: cars: 9, trees: 0, pomeranians: 9
Sue 319: akitas: 3, vizslas: 7, children: 10
Sue 320: vizslas: 0, akitas: 8, pomeranians: 4
Sue 321: cars: 10, akitas: 9, vizslas: 3
Sue 322: perfumes: 0, akitas: 8, vizslas: 6
Sue 323: vizslas: 10, perfumes: 5, cars: 3
Sue 324: akitas: 0, goldfish: 6, vizslas: 7
Sue 325: perfumes: 9, vizslas: 5, pomeranians: 2
Sue 326: vizslas: 6, goldfish: 10, pomeranians: 8
Sue 327: vizslas: 10, cars: 1, akitas: 7
Sue 328: trees: 1, perfumes: 10, cars: 10
Sue 329: pomeranians: 5, samoyeds: 3, cars: 10
Sue 330: akitas: 6, cars: 1, pomeranians: 4
Sue 331: cars: 5, children: 2, trees: 0
Sue 332: vizslas: 6, pomeranians: 1, perfumes: 0
Sue 333: akitas: 7, trees: 1, cats: 9
Sue 334: vizslas: 6, goldfish: 9, akitas: 7
Sue 335: akitas: 3, samoyeds: 3, cars: 3
Sue 336: samoyeds: 10, perfumes: 9, trees: 6
Sue 337: vizslas: 2, cars: 9, akitas: 0
Sue 338: akitas: 6, perfumes: 9, vizslas: 3
Sue 339: cars: 3, samoyeds: 8, trees: 2
Sue 340: cats: 7, perfumes: 8, cars: 9
Sue 341: goldfish: 9, perfumes: 5, cars: 10
Sue 342: trees: 0, akitas: 3, perfumes: 5
Sue 343: perfumes: 2, children: 0, cars: 6
Sue 344: goldfish: 8, trees: 8, perfumes: 0
Sue 345: perfumes: 6, cars: 6, goldfish: 5
Sue 346: vizslas: 8, trees: 1, cars: 6
Sue 347: cars: 0, cats: 3, perfumes: 7
Sue 348: children: 7, perfumes: 10, cars: 7
Sue 349: pomeranians: 8, akitas: 5, children: 2
Sue 350: perfumes: 9, pomeranians: 4, goldfish: 3
Sue 351: perfumes: 8, pomeranians: 7, trees: 4
Sue 352: samoyeds: 1, goldfish: 9, akitas: 8
Sue 353: akitas: 6, goldfish: 10, vizslas: 8
Sue 354: akitas: 7, cars: 2, goldfish: 6
Sue 355: cars: 3, goldfish: 6, akitas: 5
Sue 356: akitas: 2, goldfish: 9, pomeranians: 1
Sue 357: goldfish: 10, cars: 6, pomeranians: 9
Sue 358: trees: 0, children: 2, goldfish: 6
Sue 359: samoyeds: 3, cars: 2, akitas: 4
Sue 360: trees: 1, goldfish: 8, cars: 5
Sue 361: akitas: 5, vizslas: 7, perfumes: 1
Sue 362: cats: 5, vizslas: 9, children: 4
Sue 363: goldfish: 9, perfumes: 3, vizslas: 9
Sue 364: children: 7, samoyeds: 2, pomeranians: 10
Sue 365: perfumes: 9, akitas: 10, pomeranians: 4
Sue 366: cars: 10, trees: 3, cats: 4
Sue 367: vizslas: 6, akitas: 10, perfumes: 5
Sue 368: akitas: 9, vizslas: 9, children: 4
Sue 369: goldfish: 8, trees: 2, perfumes: 5
Sue 370: trees: 0, children: 4, cars: 8
Sue 371: cats: 6, perfumes: 0, vizslas: 2
Sue 372: akitas: 7, cars: 5, perfumes: 3
Sue 373: cars: 0, perfumes: 4, pomeranians: 10
Sue 374: akitas: 5, perfumes: 5, vizslas: 2
Sue 375: goldfish: 7, trees: 10, pomeranians: 7
Sue 376: cars: 8, trees: 1, pomeranians: 8
Sue 377: cars: 0, akitas: 9, vizslas: 1
Sue 378: akitas: 5, perfumes: 3, vizslas: 7
Sue 379: trees: 2, goldfish: 8, pomeranians: 8
Sue 380: akitas: 5, cars: 9, perfumes: 9
Sue 381: cars: 2, perfumes: 6, trees: 3
Sue 382: perfumes: 6, vizslas: 2, goldfish: 9
Sue 383: akitas: 8, vizslas: 7, cats: 1
Sue 384: akitas: 9, trees: 10, vizslas: 7
Sue 385: cars: 0, perfumes: 7, vizslas: 2
Sue 386: vizslas: 10, akitas: 4, perfumes: 9
Sue 387: perfumes: 6, pomeranians: 5, samoyeds: 8
Sue 388: vizslas: 10, trees: 9, goldfish: 9
Sue 389: goldfish: 8, akitas: 4, perfumes: 10
Sue 390: goldfish: 6, trees: 8, akitas: 1
Sue 391: vizslas: 4, akitas: 10, goldfish: 7
Sue 392: akitas: 1, vizslas: 6, samoyeds: 5
Sue 393: trees: 6, cars: 3, akitas: 5
Sue 394: goldfish: 9, trees: 3, cars: 5
Sue 395: akitas: 6, samoyeds: 4, goldfish: 4
Sue 396: akitas: 2, trees: 1, cats: 5
Sue 397: cars: 0, children: 9, trees: 10
Sue 398: pomeranians: 3, samoyeds: 9, goldfish: 10
Sue 399: cars: 7, akitas: 4, goldfish: 8
Sue 400: cars: 4, akitas: 5, vizslas: 4
Sue 401: pomeranians: 5, akitas: 8, vizslas: 5
Sue 402: cats: 7, cars: 6, goldfish: 6
Sue 403: samoyeds: 8, perfumes: 4, cars: 5
Sue 404: akitas: 10, goldfish: 4, trees: 2
Sue 405: trees: 8, perfumes: 1, cars: 2
Sue 406: trees: 0, perfumes: 9, pomeranians: 10
Sue 407: perfumes: 4, trees: 7, goldfish: 3
Sue 408: akitas: 1, perfumes: 3, cars: 5
Sue 409: trees: 6, samoyeds: 3, cars: 9
Sue 410: vizslas: 3, goldfish: 5, akitas: 7
Sue 411: goldfish: 10, trees: 1, vizslas: 9
Sue 412: cars: 0, akitas: 6, trees: 6
Sue 413: goldfish: 7, trees: 0, cars: 3
Sue 414: pomeranians: 10, samoyeds: 3, cars: 10
Sue 415: perfumes: 6, trees: 9, cars: 4
Sue 416: trees: 2, cars: 4, goldfish: 8
Sue 417: goldfish: 2, cars: 9, cats: 5
Sue 418: vizslas: 1, cars: 9, akitas: 0
Sue 419: perfumes: 6, cats: 3, children: 9
Sue 420: cats: 5, goldfish: 7, akitas: 9
Sue 421: trees: 1, samoyeds: 6, pomeranians: 1
Sue 422: trees: 10, goldfish: 6, children: 7
Sue 423: cars: 8, goldfish: 7, vizslas: 3
Sue 424: samoyeds: 9, akitas: 7, trees: 5
Sue 425: akitas: 5, children: 4, perfumes: 9
Sue 426: goldfish: 1, children: 9, cats: 2
Sue 427: vizslas: 9, akitas: 7, goldfish: 9
Sue 428: pomeranians: 7, akitas: 5, vizslas: 1
Sue 429: vizslas: 7, goldfish: 7, cars: 9
Sue 430: trees: 7, perfumes: 0, pomeranians: 5
Sue 431: children: 9, perfumes: 5, vizslas: 7
Sue 432: trees: 6, samoyeds: 7, cats: 1
Sue 433: goldfish: 5, trees: 5, children: 6
Sue 434: goldfish: 9, akitas: 7, cars: 3
Sue 435: samoyeds: 10, perfumes: 2, cars: 0
Sue 436: akitas: 5, pomeranians: 4, perfumes: 7
Sue 437: vizslas: 5, cats: 6, perfumes: 5
Sue 438: trees: 2, goldfish: 6, vizslas: 7
Sue 439: samoyeds: 8, pomeranians: 10, goldfish: 1
Sue 440: akitas: 6, children: 9, perfumes: 4
Sue 441: cars: 2, goldfish: 9, children: 0
Sue 442: goldfish: 7, cars: 2, vizslas: 8
Sue 443: goldfish: 6, samoyeds: 3, perfumes: 2
Sue 444: trees: 2, goldfish: 7, cars: 8
Sue 445: trees: 2, pomeranians: 0, children: 0
Sue 446: perfumes: 4, akitas: 4, goldfish: 6
Sue 447: vizslas: 7, akitas: 9, cars: 3
Sue 448: goldfish: 6, trees: 9, cars: 0
Sue 449: samoyeds: 7, perfumes: 4, vizslas: 10
Sue 450: akitas: 7, cars: 10, goldfish: 7
Sue 451: goldfish: 4, children: 7, pomeranians: 4
Sue 452: cats: 4, vizslas: 6, trees: 7
Sue 453: cars: 1, trees: 10, goldfish: 9
Sue 454: trees: 2, goldfish: 3, vizslas: 10
Sue 455: pomeranians: 9, vizslas: 3, akitas: 2
Sue 456: vizslas: 10, akitas: 2, goldfish: 1
Sue 457: trees: 5, cats: 5, children: 8
Sue 458: cars: 6, goldfish: 3, akitas: 9
Sue 459: goldfish: 7, akitas: 2, cats: 7
Sue 460: akitas: 1, cars: 5, children: 8
Sue 461: cars: 8, perfumes: 0, goldfish: 6
Sue 462: pomeranians: 6, cats: 2, perfumes: 6
Sue 463: vizslas: 7, perfumes: 3, goldfish: 3
Sue 464: akitas: 10, goldfish: 10, trees: 1
Sue 465: vizslas: 0, akitas: 2, trees: 2
Sue 466: perfumes: 6, akitas: 8, cars: 2
Sue 467: goldfish: 1, cars: 10, perfumes: 3
Sue 468: goldfish: 4, trees: 2, cars: 9
Sue 469: perfumes: 6, pomeranians: 0, vizslas: 10
Sue 470: samoyeds: 8, children: 0, akitas: 7
Sue 471: children: 3, goldfish: 9, cats: 9
Sue 472: samoyeds: 0, goldfish: 0, trees: 0
Sue 473: trees: 3, goldfish: 4, vizslas: 1
Sue 474: perfumes: 10, cars: 3, trees: 7
Sue 475: akitas: 5, vizslas: 4, goldfish: 5
Sue 476: children: 2, akitas: 7, vizslas: 3
Sue 477: vizslas: 6, pomeranians: 9, trees: 6
Sue 478: vizslas: 7, pomeranians: 6, akitas: 7
Sue 479: trees: 2, perfumes: 2, children: 2
Sue 480: cars: 8, cats: 5, vizslas: 0
Sue 481: trees: 5, goldfish: 0, akitas: 3
Sue 482: cars: 8, perfumes: 6, goldfish: 10
Sue 483: goldfish: 0, cars: 3, perfumes: 10
Sue 484: pomeranians: 1, samoyeds: 1, perfumes: 3
Sue 485: trees: 0, akitas: 2, vizslas: 4
Sue 486: cars: 3, vizslas: 8, goldfish: 1
Sue 487: pomeranians: 9, vizslas: 2, children: 10
Sue 488: akitas: 6, vizslas: 10, perfumes: 9
Sue 489: goldfish: 6, vizslas: 4, cars: 2
Sue 490: vizslas: 10, cats: 8, samoyeds: 1
Sue 491: cats: 9, cars: 1, perfumes: 10
Sue 492: goldfish: 6, cars: 9, pomeranians: 9
Sue 493: children: 10, goldfish: 10, vizslas: 0
Sue 494: pomeranians: 5, cars: 0, vizslas: 0
Sue 495: vizslas: 7, perfumes: 6, samoyeds: 3
Sue 496: trees: 1, cats: 4, cars: 10
Sue 497: cats: 1, perfumes: 0, cars: 7
Sue 498: perfumes: 7, vizslas: 6, cats: 9
Sue 499: vizslas: 8, perfumes: 1, akitas: 3
Sue 500: perfumes: 4, cars: 9, trees: 4

69
2015/d16/ex2/ex2.py Executable file
View file

@ -0,0 +1,69 @@
#!/usr/bin/env python
import sys
from typing import NamedTuple
class Sue(NamedTuple):
children: int | None = None
cats: int | None = None
samoyeds: int | None = None
pomeranians: int | None = None
akitas: int | None = None
vizslas: int | None = None
goldfish: int | None = None
trees: int | None = None
cars: int | None = None
perfumes: int | None = None
def matches(self, reading: dict[str, int | None]) -> bool:
for name, expected in reading.items():
assert expected is not None # Sanity check
val = getattr(self, name)
if name in ("cats", "trees"):
if val is not None and val <= expected:
return False
elif name in ("pomeranians", "goldfish"):
if val is not None and val >= expected:
return False
else:
if val is not None and val != expected:
return False
return True
def solve(input: str) -> int:
def parse_line(input: str) -> Sue:
_, other = input.split(": ", 1)
raw_items = other.split(", ")
items = {
name: int(val) for name, val in (item.split(": ") for item in raw_items)
}
return Sue(**items)
def parse(input: str) -> list[Sue]:
return [parse_line(line) for line in input.splitlines()]
aunts = parse(input)
reading = Sue(
children=3,
cats=7,
samoyeds=2,
pomeranians=3,
akitas=0,
vizslas=0,
goldfish=5,
trees=3,
cars=2,
perfumes=1,
)
return next(i for i, sue in enumerate(aunts, 1) if sue.matches(reading._asdict()))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

500
2015/d16/ex2/input Normal file
View file

@ -0,0 +1,500 @@
Sue 1: goldfish: 6, trees: 9, akitas: 0
Sue 2: goldfish: 7, trees: 1, akitas: 0
Sue 3: cars: 10, akitas: 6, perfumes: 7
Sue 4: perfumes: 2, vizslas: 0, cars: 6
Sue 5: goldfish: 1, trees: 3, perfumes: 10
Sue 6: children: 9, vizslas: 7, cars: 9
Sue 7: cars: 6, vizslas: 5, cats: 3
Sue 8: akitas: 10, vizslas: 9, children: 3
Sue 9: vizslas: 8, cats: 2, trees: 1
Sue 10: perfumes: 10, trees: 6, cars: 4
Sue 11: cars: 9, children: 1, cats: 1
Sue 12: pomeranians: 4, akitas: 6, goldfish: 8
Sue 13: cats: 10, children: 5, trees: 9
Sue 14: perfumes: 8, vizslas: 3, samoyeds: 1
Sue 15: vizslas: 2, perfumes: 8, trees: 3
Sue 16: pomeranians: 10, trees: 9, samoyeds: 4
Sue 17: akitas: 7, vizslas: 0, goldfish: 6
Sue 18: trees: 5, vizslas: 9, cars: 0
Sue 19: akitas: 3, goldfish: 9, trees: 10
Sue 20: perfumes: 7, samoyeds: 3, vizslas: 10
Sue 21: perfumes: 7, pomeranians: 10, akitas: 8
Sue 22: vizslas: 6, trees: 8, akitas: 10
Sue 23: goldfish: 0, trees: 4, children: 9
Sue 24: goldfish: 7, pomeranians: 9, akitas: 4
Sue 25: cars: 7, trees: 4, pomeranians: 4
Sue 26: trees: 9, akitas: 9, pomeranians: 7
Sue 27: samoyeds: 0, perfumes: 9, goldfish: 10
Sue 28: cars: 5, trees: 7, vizslas: 1
Sue 29: perfumes: 9, trees: 1, children: 6
Sue 30: goldfish: 10, trees: 0, cars: 4
Sue 31: akitas: 2, perfumes: 5, goldfish: 5
Sue 32: goldfish: 0, akitas: 5, trees: 0
Sue 33: vizslas: 2, akitas: 2, samoyeds: 3
Sue 34: goldfish: 8, perfumes: 5, cars: 3
Sue 35: akitas: 1, cats: 4, trees: 9
Sue 36: cars: 4, vizslas: 4, goldfish: 7
Sue 37: akitas: 5, perfumes: 7, trees: 3
Sue 38: goldfish: 10, trees: 2, vizslas: 9
Sue 39: goldfish: 4, pomeranians: 5, vizslas: 5
Sue 40: perfumes: 5, samoyeds: 4, akitas: 6
Sue 41: goldfish: 9, cars: 4, perfumes: 5
Sue 42: trees: 6, pomeranians: 9, goldfish: 8
Sue 43: perfumes: 7, pomeranians: 1, akitas: 2
Sue 44: vizslas: 9, cars: 5, cats: 0
Sue 45: akitas: 1, goldfish: 6, trees: 0
Sue 46: akitas: 5, vizslas: 8, trees: 2
Sue 47: trees: 9, akitas: 2, vizslas: 9
Sue 48: goldfish: 10, trees: 5, akitas: 2
Sue 49: cars: 7, vizslas: 2, perfumes: 6
Sue 50: akitas: 5, goldfish: 6, perfumes: 0
Sue 51: cars: 9, cats: 7, trees: 5
Sue 52: akitas: 7, goldfish: 10, cars: 0
Sue 53: cars: 10, cats: 4, perfumes: 2
Sue 54: goldfish: 2, pomeranians: 5, perfumes: 10
Sue 55: vizslas: 5, akitas: 4, cars: 8
Sue 56: goldfish: 9, vizslas: 4, akitas: 5
Sue 57: perfumes: 8, samoyeds: 7, cars: 9
Sue 58: cars: 5, akitas: 7, perfumes: 8
Sue 59: samoyeds: 8, cars: 10, vizslas: 10
Sue 60: akitas: 6, samoyeds: 0, goldfish: 3
Sue 61: trees: 8, pomeranians: 0, akitas: 2
Sue 62: trees: 1, perfumes: 3, vizslas: 4
Sue 63: vizslas: 6, samoyeds: 9, goldfish: 8
Sue 64: goldfish: 7, trees: 6, vizslas: 3
Sue 65: cars: 1, vizslas: 0, akitas: 6
Sue 66: cats: 6, pomeranians: 4, cars: 9
Sue 67: trees: 10, pomeranians: 7, samoyeds: 3
Sue 68: pomeranians: 5, goldfish: 9, akitas: 1
Sue 69: akitas: 1, vizslas: 0, trees: 9
Sue 70: cats: 4, goldfish: 4, vizslas: 10
Sue 71: vizslas: 7, perfumes: 7, trees: 8
Sue 72: children: 2, vizslas: 9, cats: 3
Sue 73: cars: 8, pomeranians: 0, perfumes: 6
Sue 74: akitas: 1, pomeranians: 8, vizslas: 10
Sue 75: vizslas: 5, perfumes: 5, cars: 7
Sue 76: cars: 3, vizslas: 3, goldfish: 0
Sue 77: akitas: 9, samoyeds: 1, pomeranians: 3
Sue 78: trees: 0, vizslas: 0, akitas: 6
Sue 79: pomeranians: 9, cars: 1, perfumes: 0
Sue 80: perfumes: 10, trees: 1, cats: 0
Sue 81: goldfish: 5, akitas: 9, trees: 0
Sue 82: vizslas: 1, akitas: 6, children: 4
Sue 83: samoyeds: 7, perfumes: 8, pomeranians: 4
Sue 84: perfumes: 3, children: 3, cats: 7
Sue 85: goldfish: 9, trees: 3, cars: 9
Sue 86: cars: 0, perfumes: 9, vizslas: 0
Sue 87: children: 3, trees: 4, akitas: 3
Sue 88: trees: 1, samoyeds: 1, goldfish: 0
Sue 89: akitas: 8, cars: 3, vizslas: 9
Sue 90: pomeranians: 9, trees: 9, goldfish: 8
Sue 91: goldfish: 7, trees: 10, children: 0
Sue 92: cats: 9, cars: 7, perfumes: 7
Sue 93: vizslas: 2, goldfish: 7, cats: 9
Sue 94: akitas: 5, cars: 8, vizslas: 4
Sue 95: goldfish: 7, vizslas: 1, perfumes: 2
Sue 96: goldfish: 5, trees: 6, perfumes: 10
Sue 97: trees: 0, perfumes: 7, cars: 0
Sue 98: cars: 2, perfumes: 6, trees: 8
Sue 99: trees: 10, children: 7, cats: 9
Sue 100: samoyeds: 5, goldfish: 6, vizslas: 6
Sue 101: cars: 10, perfumes: 9, vizslas: 3
Sue 102: pomeranians: 6, trees: 1, samoyeds: 4
Sue 103: cars: 2, perfumes: 1, goldfish: 5
Sue 104: goldfish: 2, cars: 8, pomeranians: 2
Sue 105: goldfish: 6, vizslas: 0, trees: 10
Sue 106: trees: 10, akitas: 10, pomeranians: 0
Sue 107: vizslas: 2, pomeranians: 10, trees: 3
Sue 108: children: 3, vizslas: 8, akitas: 7
Sue 109: perfumes: 2, akitas: 2, samoyeds: 3
Sue 110: goldfish: 7, trees: 1, perfumes: 1
Sue 111: akitas: 2, cars: 9, perfumes: 2
Sue 112: children: 10, cars: 0, akitas: 3
Sue 113: akitas: 9, vizslas: 4, children: 3
Sue 114: pomeranians: 3, trees: 2, goldfish: 5
Sue 115: perfumes: 8, cars: 6, trees: 0
Sue 116: samoyeds: 6, children: 3, pomeranians: 1
Sue 117: goldfish: 1, trees: 2, akitas: 1
Sue 118: goldfish: 10, akitas: 10, samoyeds: 0
Sue 119: vizslas: 10, perfumes: 6, cars: 0
Sue 120: cars: 2, perfumes: 9, goldfish: 5
Sue 121: vizslas: 2, trees: 2, cars: 6
Sue 122: vizslas: 3, trees: 0, akitas: 2
Sue 123: akitas: 5, samoyeds: 7, goldfish: 1
Sue 124: goldfish: 8, samoyeds: 7, trees: 8
Sue 125: trees: 3, goldfish: 8, perfumes: 5
Sue 126: cats: 3, vizslas: 9, goldfish: 0
Sue 127: pomeranians: 9, goldfish: 3, perfumes: 6
Sue 128: vizslas: 4, cars: 8, goldfish: 5
Sue 129: vizslas: 8, children: 5, perfumes: 8
Sue 130: cars: 7, children: 7, cats: 3
Sue 131: perfumes: 1, akitas: 8, vizslas: 9
Sue 132: perfumes: 7, samoyeds: 10, pomeranians: 6
Sue 133: cars: 5, perfumes: 3, goldfish: 7
Sue 134: perfumes: 9, akitas: 2, cats: 3
Sue 135: perfumes: 1, trees: 9, vizslas: 9
Sue 136: akitas: 7, cars: 3, perfumes: 7
Sue 137: vizslas: 9, goldfish: 8, cars: 5
Sue 138: trees: 0, samoyeds: 1, cars: 3
Sue 139: cars: 0, perfumes: 6, trees: 0
Sue 140: pomeranians: 4, cars: 1, perfumes: 7
Sue 141: vizslas: 10, akitas: 8, cats: 3
Sue 142: trees: 1, cats: 6, vizslas: 5
Sue 143: pomeranians: 9, cars: 7, perfumes: 9
Sue 144: cars: 0, perfumes: 2, pomeranians: 1
Sue 145: trees: 1, goldfish: 9, perfumes: 8
Sue 146: cars: 8, children: 5, vizslas: 2
Sue 147: perfumes: 2, goldfish: 5, cars: 0
Sue 148: akitas: 2, perfumes: 7, pomeranians: 6
Sue 149: goldfish: 8, cars: 0, trees: 1
Sue 150: akitas: 6, perfumes: 5, trees: 0
Sue 151: vizslas: 6, samoyeds: 8, akitas: 10
Sue 152: trees: 7, akitas: 7, perfumes: 6
Sue 153: goldfish: 9, cats: 9, cars: 3
Sue 154: vizslas: 10, trees: 0, cars: 9
Sue 155: perfumes: 3, children: 2, goldfish: 1
Sue 156: goldfish: 7, perfumes: 5, akitas: 6
Sue 157: cats: 10, trees: 1, goldfish: 0
Sue 158: cats: 7, children: 7, vizslas: 6
Sue 159: perfumes: 9, akitas: 0, cars: 0
Sue 160: akitas: 3, goldfish: 10, pomeranians: 2
Sue 161: goldfish: 10, cars: 6, perfumes: 3
Sue 162: trees: 0, cars: 9, goldfish: 1
Sue 163: cars: 8, perfumes: 9, vizslas: 5
Sue 164: goldfish: 1, trees: 10, children: 6
Sue 165: goldfish: 0, vizslas: 6, cars: 0
Sue 166: akitas: 5, vizslas: 1, cars: 5
Sue 167: vizslas: 1, samoyeds: 1, children: 4
Sue 168: samoyeds: 7, vizslas: 7, akitas: 3
Sue 169: goldfish: 3, cats: 9, trees: 2
Sue 170: cars: 5, perfumes: 9, vizslas: 5
Sue 171: goldfish: 7, cars: 6, perfumes: 10
Sue 172: cats: 6, akitas: 1, children: 6
Sue 173: cats: 4, goldfish: 1, children: 3
Sue 174: cars: 2, pomeranians: 2, vizslas: 7
Sue 175: trees: 0, children: 4, goldfish: 7
Sue 176: children: 8, cars: 5, cats: 9
Sue 177: pomeranians: 4, vizslas: 7, trees: 3
Sue 178: vizslas: 6, perfumes: 10, akitas: 6
Sue 179: cars: 4, akitas: 4, trees: 4
Sue 180: akitas: 8, goldfish: 6, trees: 9
Sue 181: perfumes: 3, vizslas: 10, cars: 3
Sue 182: vizslas: 3, samoyeds: 3, goldfish: 7
Sue 183: goldfish: 10, perfumes: 2, cats: 1
Sue 184: goldfish: 5, trees: 1, perfumes: 1
Sue 185: vizslas: 10, trees: 9, perfumes: 2
Sue 186: goldfish: 6, perfumes: 9, trees: 1
Sue 187: cars: 0, trees: 9, goldfish: 6
Sue 188: cars: 0, trees: 1, vizslas: 9
Sue 189: akitas: 7, vizslas: 2, trees: 0
Sue 190: pomeranians: 5, perfumes: 8, akitas: 10
Sue 191: vizslas: 5, akitas: 3, cats: 0
Sue 192: children: 1, trees: 1, cars: 2
Sue 193: cars: 3, goldfish: 9, trees: 2
Sue 194: samoyeds: 3, akitas: 4, perfumes: 8
Sue 195: trees: 1, vizslas: 8, akitas: 10
Sue 196: akitas: 6, cars: 5, pomeranians: 0
Sue 197: akitas: 5, vizslas: 5, cats: 1
Sue 198: trees: 4, cars: 6, goldfish: 6
Sue 199: cats: 7, cars: 5, goldfish: 6
Sue 200: vizslas: 4, cats: 0, akitas: 9
Sue 201: pomeranians: 1, perfumes: 4, children: 2
Sue 202: cats: 1, perfumes: 4, vizslas: 3
Sue 203: vizslas: 1, akitas: 9, children: 5
Sue 204: perfumes: 8, cars: 7, trees: 4
Sue 205: perfumes: 7, pomeranians: 5, cats: 9
Sue 206: vizslas: 8, trees: 2, akitas: 2
Sue 207: akitas: 6, vizslas: 2, perfumes: 10
Sue 208: vizslas: 1, children: 7, akitas: 4
Sue 209: perfumes: 4, trees: 2, children: 1
Sue 210: goldfish: 0, vizslas: 2, samoyeds: 10
Sue 211: cars: 8, perfumes: 3, trees: 1
Sue 212: cars: 8, samoyeds: 5, pomeranians: 8
Sue 213: akitas: 2, goldfish: 8, pomeranians: 2
Sue 214: akitas: 6, pomeranians: 2, cars: 0
Sue 215: trees: 10, pomeranians: 4, vizslas: 0
Sue 216: perfumes: 0, cars: 8, trees: 0
Sue 217: samoyeds: 8, akitas: 7, children: 10
Sue 218: perfumes: 1, vizslas: 6, children: 0
Sue 219: children: 1, goldfish: 4, trees: 1
Sue 220: akitas: 10, goldfish: 10, trees: 5
Sue 221: cars: 7, pomeranians: 6, perfumes: 3
Sue 222: vizslas: 6, children: 0, akitas: 5
Sue 223: perfumes: 9, cars: 1, trees: 6
Sue 224: pomeranians: 1, trees: 0, vizslas: 0
Sue 225: goldfish: 8, akitas: 4, perfumes: 10
Sue 226: pomeranians: 7, cats: 7, children: 4
Sue 227: trees: 0, akitas: 2, perfumes: 1
Sue 228: vizslas: 6, cars: 10, perfumes: 9
Sue 229: cars: 0, perfumes: 6, trees: 4
Sue 230: pomeranians: 7, perfumes: 5, trees: 2
Sue 231: goldfish: 9, cars: 6, trees: 7
Sue 232: akitas: 1, vizslas: 5, cars: 3
Sue 233: akitas: 7, samoyeds: 2, vizslas: 5
Sue 234: akitas: 6, cats: 8, pomeranians: 0
Sue 235: pomeranians: 5, akitas: 5, vizslas: 3
Sue 236: goldfish: 5, trees: 6, akitas: 5
Sue 237: goldfish: 9, perfumes: 5, cats: 5
Sue 238: cats: 8, goldfish: 4, perfumes: 0
Sue 239: samoyeds: 8, children: 6, pomeranians: 6
Sue 240: akitas: 4, samoyeds: 10, trees: 8
Sue 241: trees: 2, goldfish: 8, cars: 1
Sue 242: perfumes: 2, cars: 0, akitas: 10
Sue 243: pomeranians: 1, cars: 7, trees: 2
Sue 244: trees: 9, vizslas: 2, akitas: 10
Sue 245: cars: 9, pomeranians: 4, trees: 0
Sue 246: cars: 9, pomeranians: 7, perfumes: 1
Sue 247: trees: 0, goldfish: 1, akitas: 8
Sue 248: vizslas: 1, cats: 4, akitas: 4
Sue 249: cats: 6, children: 4, goldfish: 9
Sue 250: vizslas: 1, cars: 10, samoyeds: 5
Sue 251: cars: 0, goldfish: 1, vizslas: 7
Sue 252: cars: 7, akitas: 9, vizslas: 10
Sue 253: akitas: 7, vizslas: 2, perfumes: 5
Sue 254: vizslas: 10, akitas: 5, samoyeds: 0
Sue 255: pomeranians: 8, goldfish: 0, cats: 6
Sue 256: cars: 10, goldfish: 8, vizslas: 9
Sue 257: goldfish: 3, perfumes: 9, cats: 3
Sue 258: trees: 6, goldfish: 6, cars: 6
Sue 259: trees: 0, goldfish: 2, perfumes: 8
Sue 260: trees: 5, akitas: 0, cars: 0
Sue 261: pomeranians: 9, goldfish: 7, perfumes: 8
Sue 262: perfumes: 8, vizslas: 6, goldfish: 2
Sue 263: vizslas: 6, trees: 5, goldfish: 9
Sue 264: vizslas: 4, perfumes: 7, cars: 9
Sue 265: goldfish: 10, trees: 3, perfumes: 1
Sue 266: trees: 10, akitas: 8, goldfish: 8
Sue 267: goldfish: 4, trees: 0, samoyeds: 9
Sue 268: vizslas: 1, trees: 0, goldfish: 8
Sue 269: cars: 2, perfumes: 10, goldfish: 5
Sue 270: perfumes: 7, cars: 2, vizslas: 1
Sue 271: cars: 6, perfumes: 10, goldfish: 6
Sue 272: samoyeds: 4, goldfish: 2, vizslas: 9
Sue 273: perfumes: 4, goldfish: 4, vizslas: 1
Sue 274: children: 4, cars: 4, perfumes: 3
Sue 275: children: 8, vizslas: 3, trees: 2
Sue 276: vizslas: 5, children: 7, perfumes: 3
Sue 277: perfumes: 3, cats: 4, vizslas: 5
Sue 278: cars: 1, samoyeds: 10, akitas: 2
Sue 279: trees: 9, perfumes: 9, cars: 10
Sue 280: vizslas: 5, trees: 0, perfumes: 6
Sue 281: vizslas: 3, akitas: 10, pomeranians: 7
Sue 282: trees: 1, children: 2, akitas: 8
Sue 283: akitas: 9, goldfish: 6, cats: 5
Sue 284: cars: 9, children: 10, pomeranians: 2
Sue 285: pomeranians: 0, perfumes: 4, cars: 7
Sue 286: perfumes: 0, vizslas: 10, akitas: 10
Sue 287: cats: 2, perfumes: 3, trees: 5
Sue 288: akitas: 9, vizslas: 8, samoyeds: 9
Sue 289: perfumes: 6, children: 2, cars: 7
Sue 290: akitas: 0, children: 5, cars: 5
Sue 291: cars: 4, perfumes: 0, trees: 1
Sue 292: cats: 0, cars: 8, perfumes: 6
Sue 293: akitas: 9, cats: 5, children: 5
Sue 294: akitas: 4, cars: 9, goldfish: 3
Sue 295: cars: 2, akitas: 3, perfumes: 7
Sue 296: perfumes: 4, cars: 7, goldfish: 10
Sue 297: trees: 5, akitas: 8, vizslas: 1
Sue 298: perfumes: 0, goldfish: 6, trees: 9
Sue 299: perfumes: 6, samoyeds: 8, cars: 1
Sue 300: goldfish: 10, perfumes: 4, akitas: 2
Sue 301: cars: 3, trees: 0, goldfish: 8
Sue 302: perfumes: 7, samoyeds: 2, vizslas: 7
Sue 303: children: 10, goldfish: 7, perfumes: 2
Sue 304: samoyeds: 8, vizslas: 2, cars: 1
Sue 305: trees: 1, cats: 0, goldfish: 10
Sue 306: trees: 4, perfumes: 2, cars: 7
Sue 307: cars: 6, vizslas: 2, children: 6
Sue 308: vizslas: 2, cars: 0, akitas: 7
Sue 309: cars: 3, vizslas: 8, perfumes: 6
Sue 310: goldfish: 7, perfumes: 7, vizslas: 3
Sue 311: pomeranians: 10, trees: 2, cars: 0
Sue 312: samoyeds: 2, vizslas: 9, akitas: 1
Sue 313: cars: 4, pomeranians: 7, goldfish: 7
Sue 314: akitas: 2, pomeranians: 9, samoyeds: 10
Sue 315: akitas: 3, vizslas: 2, trees: 0
Sue 316: cars: 0, perfumes: 4, pomeranians: 6
Sue 317: akitas: 10, goldfish: 3, pomeranians: 7
Sue 318: cars: 9, trees: 0, pomeranians: 9
Sue 319: akitas: 3, vizslas: 7, children: 10
Sue 320: vizslas: 0, akitas: 8, pomeranians: 4
Sue 321: cars: 10, akitas: 9, vizslas: 3
Sue 322: perfumes: 0, akitas: 8, vizslas: 6
Sue 323: vizslas: 10, perfumes: 5, cars: 3
Sue 324: akitas: 0, goldfish: 6, vizslas: 7
Sue 325: perfumes: 9, vizslas: 5, pomeranians: 2
Sue 326: vizslas: 6, goldfish: 10, pomeranians: 8
Sue 327: vizslas: 10, cars: 1, akitas: 7
Sue 328: trees: 1, perfumes: 10, cars: 10
Sue 329: pomeranians: 5, samoyeds: 3, cars: 10
Sue 330: akitas: 6, cars: 1, pomeranians: 4
Sue 331: cars: 5, children: 2, trees: 0
Sue 332: vizslas: 6, pomeranians: 1, perfumes: 0
Sue 333: akitas: 7, trees: 1, cats: 9
Sue 334: vizslas: 6, goldfish: 9, akitas: 7
Sue 335: akitas: 3, samoyeds: 3, cars: 3
Sue 336: samoyeds: 10, perfumes: 9, trees: 6
Sue 337: vizslas: 2, cars: 9, akitas: 0
Sue 338: akitas: 6, perfumes: 9, vizslas: 3
Sue 339: cars: 3, samoyeds: 8, trees: 2
Sue 340: cats: 7, perfumes: 8, cars: 9
Sue 341: goldfish: 9, perfumes: 5, cars: 10
Sue 342: trees: 0, akitas: 3, perfumes: 5
Sue 343: perfumes: 2, children: 0, cars: 6
Sue 344: goldfish: 8, trees: 8, perfumes: 0
Sue 345: perfumes: 6, cars: 6, goldfish: 5
Sue 346: vizslas: 8, trees: 1, cars: 6
Sue 347: cars: 0, cats: 3, perfumes: 7
Sue 348: children: 7, perfumes: 10, cars: 7
Sue 349: pomeranians: 8, akitas: 5, children: 2
Sue 350: perfumes: 9, pomeranians: 4, goldfish: 3
Sue 351: perfumes: 8, pomeranians: 7, trees: 4
Sue 352: samoyeds: 1, goldfish: 9, akitas: 8
Sue 353: akitas: 6, goldfish: 10, vizslas: 8
Sue 354: akitas: 7, cars: 2, goldfish: 6
Sue 355: cars: 3, goldfish: 6, akitas: 5
Sue 356: akitas: 2, goldfish: 9, pomeranians: 1
Sue 357: goldfish: 10, cars: 6, pomeranians: 9
Sue 358: trees: 0, children: 2, goldfish: 6
Sue 359: samoyeds: 3, cars: 2, akitas: 4
Sue 360: trees: 1, goldfish: 8, cars: 5
Sue 361: akitas: 5, vizslas: 7, perfumes: 1
Sue 362: cats: 5, vizslas: 9, children: 4
Sue 363: goldfish: 9, perfumes: 3, vizslas: 9
Sue 364: children: 7, samoyeds: 2, pomeranians: 10
Sue 365: perfumes: 9, akitas: 10, pomeranians: 4
Sue 366: cars: 10, trees: 3, cats: 4
Sue 367: vizslas: 6, akitas: 10, perfumes: 5
Sue 368: akitas: 9, vizslas: 9, children: 4
Sue 369: goldfish: 8, trees: 2, perfumes: 5
Sue 370: trees: 0, children: 4, cars: 8
Sue 371: cats: 6, perfumes: 0, vizslas: 2
Sue 372: akitas: 7, cars: 5, perfumes: 3
Sue 373: cars: 0, perfumes: 4, pomeranians: 10
Sue 374: akitas: 5, perfumes: 5, vizslas: 2
Sue 375: goldfish: 7, trees: 10, pomeranians: 7
Sue 376: cars: 8, trees: 1, pomeranians: 8
Sue 377: cars: 0, akitas: 9, vizslas: 1
Sue 378: akitas: 5, perfumes: 3, vizslas: 7
Sue 379: trees: 2, goldfish: 8, pomeranians: 8
Sue 380: akitas: 5, cars: 9, perfumes: 9
Sue 381: cars: 2, perfumes: 6, trees: 3
Sue 382: perfumes: 6, vizslas: 2, goldfish: 9
Sue 383: akitas: 8, vizslas: 7, cats: 1
Sue 384: akitas: 9, trees: 10, vizslas: 7
Sue 385: cars: 0, perfumes: 7, vizslas: 2
Sue 386: vizslas: 10, akitas: 4, perfumes: 9
Sue 387: perfumes: 6, pomeranians: 5, samoyeds: 8
Sue 388: vizslas: 10, trees: 9, goldfish: 9
Sue 389: goldfish: 8, akitas: 4, perfumes: 10
Sue 390: goldfish: 6, trees: 8, akitas: 1
Sue 391: vizslas: 4, akitas: 10, goldfish: 7
Sue 392: akitas: 1, vizslas: 6, samoyeds: 5
Sue 393: trees: 6, cars: 3, akitas: 5
Sue 394: goldfish: 9, trees: 3, cars: 5
Sue 395: akitas: 6, samoyeds: 4, goldfish: 4
Sue 396: akitas: 2, trees: 1, cats: 5
Sue 397: cars: 0, children: 9, trees: 10
Sue 398: pomeranians: 3, samoyeds: 9, goldfish: 10
Sue 399: cars: 7, akitas: 4, goldfish: 8
Sue 400: cars: 4, akitas: 5, vizslas: 4
Sue 401: pomeranians: 5, akitas: 8, vizslas: 5
Sue 402: cats: 7, cars: 6, goldfish: 6
Sue 403: samoyeds: 8, perfumes: 4, cars: 5
Sue 404: akitas: 10, goldfish: 4, trees: 2
Sue 405: trees: 8, perfumes: 1, cars: 2
Sue 406: trees: 0, perfumes: 9, pomeranians: 10
Sue 407: perfumes: 4, trees: 7, goldfish: 3
Sue 408: akitas: 1, perfumes: 3, cars: 5
Sue 409: trees: 6, samoyeds: 3, cars: 9
Sue 410: vizslas: 3, goldfish: 5, akitas: 7
Sue 411: goldfish: 10, trees: 1, vizslas: 9
Sue 412: cars: 0, akitas: 6, trees: 6
Sue 413: goldfish: 7, trees: 0, cars: 3
Sue 414: pomeranians: 10, samoyeds: 3, cars: 10
Sue 415: perfumes: 6, trees: 9, cars: 4
Sue 416: trees: 2, cars: 4, goldfish: 8
Sue 417: goldfish: 2, cars: 9, cats: 5
Sue 418: vizslas: 1, cars: 9, akitas: 0
Sue 419: perfumes: 6, cats: 3, children: 9
Sue 420: cats: 5, goldfish: 7, akitas: 9
Sue 421: trees: 1, samoyeds: 6, pomeranians: 1
Sue 422: trees: 10, goldfish: 6, children: 7
Sue 423: cars: 8, goldfish: 7, vizslas: 3
Sue 424: samoyeds: 9, akitas: 7, trees: 5
Sue 425: akitas: 5, children: 4, perfumes: 9
Sue 426: goldfish: 1, children: 9, cats: 2
Sue 427: vizslas: 9, akitas: 7, goldfish: 9
Sue 428: pomeranians: 7, akitas: 5, vizslas: 1
Sue 429: vizslas: 7, goldfish: 7, cars: 9
Sue 430: trees: 7, perfumes: 0, pomeranians: 5
Sue 431: children: 9, perfumes: 5, vizslas: 7
Sue 432: trees: 6, samoyeds: 7, cats: 1
Sue 433: goldfish: 5, trees: 5, children: 6
Sue 434: goldfish: 9, akitas: 7, cars: 3
Sue 435: samoyeds: 10, perfumes: 2, cars: 0
Sue 436: akitas: 5, pomeranians: 4, perfumes: 7
Sue 437: vizslas: 5, cats: 6, perfumes: 5
Sue 438: trees: 2, goldfish: 6, vizslas: 7
Sue 439: samoyeds: 8, pomeranians: 10, goldfish: 1
Sue 440: akitas: 6, children: 9, perfumes: 4
Sue 441: cars: 2, goldfish: 9, children: 0
Sue 442: goldfish: 7, cars: 2, vizslas: 8
Sue 443: goldfish: 6, samoyeds: 3, perfumes: 2
Sue 444: trees: 2, goldfish: 7, cars: 8
Sue 445: trees: 2, pomeranians: 0, children: 0
Sue 446: perfumes: 4, akitas: 4, goldfish: 6
Sue 447: vizslas: 7, akitas: 9, cars: 3
Sue 448: goldfish: 6, trees: 9, cars: 0
Sue 449: samoyeds: 7, perfumes: 4, vizslas: 10
Sue 450: akitas: 7, cars: 10, goldfish: 7
Sue 451: goldfish: 4, children: 7, pomeranians: 4
Sue 452: cats: 4, vizslas: 6, trees: 7
Sue 453: cars: 1, trees: 10, goldfish: 9
Sue 454: trees: 2, goldfish: 3, vizslas: 10
Sue 455: pomeranians: 9, vizslas: 3, akitas: 2
Sue 456: vizslas: 10, akitas: 2, goldfish: 1
Sue 457: trees: 5, cats: 5, children: 8
Sue 458: cars: 6, goldfish: 3, akitas: 9
Sue 459: goldfish: 7, akitas: 2, cats: 7
Sue 460: akitas: 1, cars: 5, children: 8
Sue 461: cars: 8, perfumes: 0, goldfish: 6
Sue 462: pomeranians: 6, cats: 2, perfumes: 6
Sue 463: vizslas: 7, perfumes: 3, goldfish: 3
Sue 464: akitas: 10, goldfish: 10, trees: 1
Sue 465: vizslas: 0, akitas: 2, trees: 2
Sue 466: perfumes: 6, akitas: 8, cars: 2
Sue 467: goldfish: 1, cars: 10, perfumes: 3
Sue 468: goldfish: 4, trees: 2, cars: 9
Sue 469: perfumes: 6, pomeranians: 0, vizslas: 10
Sue 470: samoyeds: 8, children: 0, akitas: 7
Sue 471: children: 3, goldfish: 9, cats: 9
Sue 472: samoyeds: 0, goldfish: 0, trees: 0
Sue 473: trees: 3, goldfish: 4, vizslas: 1
Sue 474: perfumes: 10, cars: 3, trees: 7
Sue 475: akitas: 5, vizslas: 4, goldfish: 5
Sue 476: children: 2, akitas: 7, vizslas: 3
Sue 477: vizslas: 6, pomeranians: 9, trees: 6
Sue 478: vizslas: 7, pomeranians: 6, akitas: 7
Sue 479: trees: 2, perfumes: 2, children: 2
Sue 480: cars: 8, cats: 5, vizslas: 0
Sue 481: trees: 5, goldfish: 0, akitas: 3
Sue 482: cars: 8, perfumes: 6, goldfish: 10
Sue 483: goldfish: 0, cars: 3, perfumes: 10
Sue 484: pomeranians: 1, samoyeds: 1, perfumes: 3
Sue 485: trees: 0, akitas: 2, vizslas: 4
Sue 486: cars: 3, vizslas: 8, goldfish: 1
Sue 487: pomeranians: 9, vizslas: 2, children: 10
Sue 488: akitas: 6, vizslas: 10, perfumes: 9
Sue 489: goldfish: 6, vizslas: 4, cars: 2
Sue 490: vizslas: 10, cats: 8, samoyeds: 1
Sue 491: cats: 9, cars: 1, perfumes: 10
Sue 492: goldfish: 6, cars: 9, pomeranians: 9
Sue 493: children: 10, goldfish: 10, vizslas: 0
Sue 494: pomeranians: 5, cars: 0, vizslas: 0
Sue 495: vizslas: 7, perfumes: 6, samoyeds: 3
Sue 496: trees: 1, cats: 4, cars: 10
Sue 497: cats: 1, perfumes: 0, cars: 7
Sue 498: perfumes: 7, vizslas: 6, cats: 9
Sue 499: vizslas: 8, perfumes: 1, akitas: 3
Sue 500: perfumes: 4, cars: 9, trees: 4

28
2015/d17/ex1/ex1.py Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python
import itertools
import sys
TOTAL_EGGNOG = 150
def solve(input: str) -> int:
def parse(input: str) -> list[int]:
return [int(line) for line in input.splitlines()]
containers = parse(input)
return sum(
sum(combination) == TOTAL_EGGNOG
for combination in itertools.chain.from_iterable(
itertools.combinations(containers, i) for i in range(1, len(containers) + 1)
)
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

20
2015/d17/ex1/input Normal file
View file

@ -0,0 +1,20 @@
43
3
4
10
21
44
4
6
47
41
34
17
17
44
36
31
46
9
27
38

34
2015/d17/ex2/ex2.py Executable file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python
import itertools
import sys
TOTAL_EGGNOG = 150
def solve(input: str) -> int:
def parse(input: str) -> list[int]:
return [int(line) for line in input.splitlines()]
containers = parse(input)
min_containers = min(
i
for i in range(1, len(containers) + 1)
if any(
sum(combination) == TOTAL_EGGNOG
for combination in itertools.combinations(containers, i)
)
)
return sum(
sum(combination) == TOTAL_EGGNOG
for combination in itertools.combinations(containers, min_containers)
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

20
2015/d17/ex2/input Normal file
View file

@ -0,0 +1,20 @@
43
3
4
10
21
44
4
6
47
41
34
17
17
44
36
31
46
9
27
38

57
2015/d18/ex1/ex1.py Executable file
View file

@ -0,0 +1,57 @@
#!/usr/bin/env python
import itertools
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
def solve(input: str) -> int:
def parse(input: str) -> set[Point]:
return {
Point(x, y)
for x, line in enumerate(input.splitlines())
for y, c in enumerate(line)
if c == "#"
}
def neighbours(p: Point) -> Iterator[Point]:
for dx, dy in itertools.product((-1, 0, 1), repeat=2):
if dx == 0 and dy == 0:
continue
yield Point(p.x + dx, p.y + dy)
def step(lights: set[Point], dimensions: Point) -> set[Point]:
res: set[Point] = set()
for p in map(
Point._make,
itertools.product(range(dimensions.x), range(dimensions.y)),
):
num_alive = sum(n in lights for n in neighbours(p))
if p in lights and num_alive not in (2, 3):
continue
if p not in lights and num_alive != 3:
continue
res.add(p)
return res
lights = parse(input)
dimensions = Point(100, 100)
for _ in range(100):
lights = step(lights, dimensions)
return len(lights)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

100
2015/d18/ex1/input Normal file
View file

@ -0,0 +1,100 @@
###.##..##.#..#.##...#..#.####..#.##.##.##..###...#....#...###..#..###..###.#.#.#..#.##..#...##.#..#
.#...##.#####..##.......#..####.###.##.#..###.###.....#.#.####.##.###..##...###....#.##.....#.#.#.##
.....#.#.....#..###..####..#.....##.#..###.####.#.######..##......#####.#.##.#########.###..#.##.#.#
...###......#.#..###..#.#.....#.##..#.##..###...#.##.#..#..#.##.#..##......##.##.##.######...#....##
.###.....#...#.#...####.#.###..#..####.#..#.##..####...##.#...#..###...###...####..##....####.##..#.
..#....#...#.......#..###.###....#.##..#.....###.#.##.#....#.#....##.##..#.##.#..###.###.##.##..##.#
##..#####.#.#....#.#...#.#.####..#....#..#....#.#..#.#####...#..##.#.....#.##..##.####......#.#.##..
.#..##..#.#.###..##..##...#....##...#..#.#..##.##..###.####.....#.####.#.....##.#.##...#..####..#...
#.#####.......#####...#...####.#.#.#....#.###.#.##.#####..#.###.#..##.##.#.##....#.##..#....####.#.#
#.##...#####....##.#.#.....##......##.##...#.##.##...##...###.###.##.#.####.####.##..#.##.#.#.####..
#.##.##....###.###.#..#..##.##.#..#.#..##..#.#...#.##........###..#...##.#.#.##.......##.....#...###
###..#.#..##.##.#.#.#...#..#...##.##.#.########.......#.#...#....########..#.#.###..#.#..#.##..#####
####.#.#...#.##.##..#.#...#....#..###..#.#.#.####.#.##.##.#..##..##..#..#####.####.##..########..##.
.#.#...#..##.#..#..###.#..####.......##.#.#.#.##.#####..#..##...#.##...#..#....#..#..###..####.#....
..#.#...#....##...#####..#..#...###.###.....#.###.#....#.#..##...#.##.##.####.#.#.#..#.##.#....#.#..
#....###.####.##..#.#.###..###.##.##..#.#...###..#.##.#####.##.#######..#.#...##.#..........####.###
#.#####.#......#.#......#.....##...##.#.#########.#......##..##..##.#..##.##..#....##...###...#.#...
#..#..##..###.#.#.#.#.....###.#.####.##.##....#.#..##....#.#..#.####..###.##...#######.#####.##.#.#.
..###.#........##.#...###..#.##..#.#....##.#......#..#.##..#.#..#.#..#.####.#####..###.##..#.##.#...
##.###....#..##...#..#.#......##..#...#..#.####..#.##...##.####.#...#..###...#.#.#....###.##..#.#...
..##.##.#.##..##.#..#.###...##..##..#....##..##...####.#..####.###...#.....#..#.##..##..###..#.#...#
#.#....#.....#...##.#...####..#..##..##.####..##..##...####...#....##.#.#######..##.#......######.#.
#.#...###.######.######..##..##....#.#......#......#.#.##.#.##.#.#.#...#...#....#.#.#.#..#.##..#...#
####.###.#.#.##..#.##.#...#.##...#.##.##...#.....#.#..#.####.##..######.#..#.#..##....#.#.#..#.#.#.#
..##......#.#...#.##.##..##..##..#..##..#########.#..###..###.##...#..##.#..#.#.#.######..#....#.#..
..##.##.#...###.#...##..######.##.#..####..#..#.#.##.####.##.##.#...##....#...###.##.####..#....#.#.
####...###..#.#.##.#.#....###..##.#.#..########..#...#.#...#.##....##.##...#.....#.#.....#.....#....
.#.###############....#.##..###..#.####.#.##.##..#..#.#...###...##..##.##.#.....##...###.###.....#..
.###..#..##.##..####.#.###.##.##..#..##....#.#......#......##.#...#.#...#..##.#.#...#...#.##..#.##..
###.#.#.########.#.#..####.#..##.#.##.##.###.##..######...#..##.##.#..#.#...#.##..#####.....#.#.#..#
.##.##..#.#...#####.#.#.###...##...####...#......#...#..####..#.##..........#..#.#..###....######.##
..#####...#.#.#.#..#.##..#...#.#..#.##...##..##.##.#.##.#..#.#...#.......##.#...###.....#...#.#.#.##
##.##.#..######.##...#.....#.###.#..##.#.#.#..####.#....##.#....####...##....#.#.##.#..###.##.##..##
.###.##.#..#.###.####..#.##..####.#.#.##..###.#######.###.###...####........##....###.#...#.#.####.#
........#..#.#..##..########..........#.##.#..##.#...#.....####....##..#..#.#####.###...#...#.##.###
.....#..##.####...##.#####..######.##.#.###.####.##.##.#..##.##.######.##......#..#.####..##....#.##
##...####....#.##.##.###....#.#...#.####..##.#.##.#.#...####.#.#.#.#...##.###...##...###...######.##
.#....#.#.####...#.##.....##...###.#.#.##...##.#####....#.######.#.#....##..##...##....##.#.##.#.#.#
.###..###.#.......#.#######..#.#.#.######....#.#####.#.....#.#########...#....##...##.####.#..#.....
##.#..##..##.....#..##...#..##.##.#..#.#####.##.##.#.##.##...##.######.####..#.##..#####.##...##..#.
#.###...##.#.#.#.##....#.#.##.##..#....#...#.#.........#..#..####..####.####..#.##.##.#....####..##.
.#..######..#####.####.##.#.....#.#.#####..##..###.#.#.#..#.#...#.#######..##....##.##...#######..#.
#...#....#.#.##..#####..#########..#.....#...##.#.#.###...#####..##...##...####.......#######.#..###
.#......#...##.###..#....#...#.#.....#.#...##.#.#..#..###.##.###.#.##..##...#.##......#.###..#.#..##
.#....####...###..#.....##..#...#.#.###.#.#.##...#.##.##.#.#.#..####..###.#.#.#.##.#.#...#..#...####
......##.##.#...#####.##..#.###..#.#####..##.#..##.###......#...#...#..#......###.######...#.#.##..#
###..#...#.##..###.#....##...#..#####.#.#..#.###...#####.#....##..####.#.##...#.#...##..#.#.#.#..#.#
...##.#.##.##..#.#.#.###.#.#...#.....###.###.##...#.###.##...##..#..###.#..##.##..###.#....###..##..
.##.#..###..###.##.##...#..#####...#.....#####.##..####...#.##.#.#..##.#.#.#....###.....#....##.....
######.#..#.#..#....#.###...####.####.#.........#..##.#..##..##.....#..#.##.##...#...#####.#.##..#.#
.##.###...####....#.####...#####..#..#...#..#.....###.#..#.###..#.###.#.......##.####..#.##.#...##..
........#.#.##.#.....#####.###......##..#.##.#..#...####.#...#..###.#.#...##..#.#...#.####...#.#.###
.#..#.##..##...######.###.##.#.#...#.#.#.#.##..##..##.#.##..#....#.##...#.##.##...##....##.###.##.#.
##...#...#...###.#.#...#...#..###......##.#.#....##..##.#..##.#.######...#..##.#.##.#.#....#.##.##..
...#..###.#....#...#.##..##.#.##.#..###.##..#.##..####.#########....#.....##.#.##.##..##.##.######.#
#.##.#..##.......###...#.###....###.#..####..##.#####.##.###....##....#.###...####..#.#.#.##.....###
.......#...#...##.#...##.#.#..#.##..##.#....###...##.#####...#.........#.......###.##.#.#.###....##.
###.#.##.##.....#.#..#.#..####.####..#..###..........####.#.##...#######.###..#####..#.....#..###..#
#...##.##..####.##.###.#.#######..###.#..#######..#.##.####...#..#.##.####..####.#.#.......####.#...
...#.##..#..#..##........#.#..#..#.#....#.###.#.###..#.......###..#.....#....#..##.#...#.###...##.#.
###.##..#.##.#.#####..#.##.####....#####..###.#.#..#...#...###.#.##..#.#.#.....#.####.#.#.#.#.#.#...
..##..##..#..##.##.#...#..#....####....#...#..####..#.....######.###.####.#....##....##.#.#.###....#
.#.#.#.##..####..#.....#.####.#....#.....#....#.##..#.#..#.#...#.#.#.#..#..#..##.#....####.......#..
..##.##..###......#...#..##...#.###.####.#...#.####..#.#.#.....#.#...####...#.########.##.#.#.#..###
#....#.##.....##.###.##.###..#.####.....####.##...#..##.###...###..###.#....####.#..#..#..#.#..##.#.
.#.#.##....#.##......#.#..###.#....###....#......#.#.##.##.#########..##..#...#.####..#...####..#..#
.#.#.......##.#.##.#...#...#.##.#..#.#.#.##....#..###.###.##.#.#...##.#..#..##....#..###.#...#.#.##.
#.##.#....####...#..##..#.#.#.#.##.#...#####.#...#..#..#.####.####.#.#....#......##..##..###...#..##
..##.###..##.####..#..#..##...###.#.#.#######.####...####......##.##..#...#.##...##....#..#..#.....#
....#..#..#.#.####.#...##..#....####.#..####...#.#...###...#..#..##...#....##...#.....#.#..#.#.#...#
...#.#.#.##..##.###..#.######....####.###...##...###.#...##.####..#.#..#.#..#.##.....#.#.#..##......
.#.##.##.....##.#..###.###.##....#...###.#......#...##.###.#.##.##...###...###...#.######..#......#.
###..#...#......#..##...#....##.#..###.##.####..##..##....####.#...#.#....##..#.#######..#.#.#####..
##...#####..####..##....#.#.###.##.#..#.#..#.....###...###.#####.....#..##.#......#...#.###.##.##...
...#.#.#..#.###..#.#.#....##.#.#..####.##.#.####.#.#.#...#....##....#.##.####..###.#.#...##.#..#..##
#.#.#..#.##..##.##.#...##.#....#...###..##..#.#######.#.###..##......##.#..###.########.#.##..#.#.##
######.###....##..#..#...####....#.#.#..#...#..######.#.#.##..##....##....##.##.##...#..#.####.#.#..
#####.###..#..###......##...##.####.#.#.#.###.......##..##.####..##.####.#..#..####..#.####.#####...
##.#.#.###..##.#.##.#.#.#.##.#...##........###.#.##..####....###.#.####.####.#.......##.##.##...##..
#.#..###...#..##.....##.#..#.#..##..######.#####...###.#.......###...#..##..#..#..##.#.#....#..#..#.
#.#..####.###..#...#...#...#.###..#.#.#.#.#.#.#..#....#.##.##.##..###..####.#..##..##.###.###....##.
#..#.##.#####........#..#.##.#..##.#...#....#..#.##..###..##..##.##..#..##.#.#...#.#.##.#.##....#.#.
.......##..#.....#..#.#.....#.##...####.###..####..#.#.#.#..#.....#....##...#..#.##..###.#.#....#...
#...###########.##.....##...###.#.##.##..####.##...#.####.#####.#####.####...###.##...##..#.#.###..#
....#.#.###.####.###...#...#.#..###.#.#.##...#..#.#.#..#.####..#..###.######.#.####.###...###.#.##.#
.....#..#..########...#.#.#.#.#.#.#.#..###.##..####...##.#.#.#...##..#####.##.#...#.####.#######.##.
.......#...#.#..#..#...#..#..##.....#.##....##.##...##..##.##...##...#.#..#.##.#.###.#.####.#.#..##.
.####...#...#.#.#....##..........##.##.###.##.#.#..#.#.#......########.#...#.####.##.###..##...####.
#.#.#...##.###..##..#..#.....####.#.....##.##.#..#.#.###.#..#######...##..#.#..#.#..############.###
.##..####.#..#.....###..#..#.#.....#.#.#...##.##.#....#..#..###.#...#....#.#...####..#.....###.####.
..#...#.###.###....##.#..#.##..####.##.#.##.##.##...###.####..#.#.#.##.#.#.#..###..##.##.##.##.#..##
#...............##.....######.#.#####.##.#....#.#..#.##...#.##....#........##.##...#.##.##.#..#.##.#
#..##..#.#.#.##.#..#.#.##.##...#...#..#.#.##..#.#...###...##...###..#####.#.#..#..#.#..#.#.##...##.#
.#######.#.....##...#.#.####.######.#..#......#....##.#.#..#..###.#...###...#....#.#..#.##.#...#.#..
#.###......##.#.##..#.###.###..####..##....#..###......##..##..#####.####....#...###.....###.#..#...
###...#....###.#..#.###.##...###.##.......##.##.#.#.#....####....###..##.###...#..##....#.#.##..##..
.##.......##.######.#.#..#..##....#####.###.#.##.....####....#......####....#.##.#.##..#.##...##.#.#
.#.###...#.#.#.##.###..###...##..#.##.##..##..#.....###.#..#.##.##.####........##.#####.#.#....#...#
##...##..#.##.#######.###.#.##.#####....##.....##.#.....#.#.##.#....#.##.#....##.#..#.###..#..#.#...
.#..#.#.#.#...#.##...###.##.#.#...###.##...#.#..###....###.#.###...##..###..#..##.##....###...###.##

70
2015/d18/ex2/ex2.py Executable file
View file

@ -0,0 +1,70 @@
#!/usr/bin/env python
import itertools
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
def solve(input: str) -> int:
def parse(input: str) -> set[Point]:
return {
Point(x, y)
for x, line in enumerate(input.splitlines())
for y, c in enumerate(line)
if c == "#"
}
def neighbours(p: Point) -> Iterator[Point]:
for dx, dy in itertools.product((-1, 0, 1), repeat=2):
if dx == 0 and dy == 0:
continue
yield Point(p.x + dx, p.y + dy)
def step(lights: set[Point], dimensions: Point) -> set[Point]:
res = {
# Four corners are stuck on
Point(0, 0),
Point(0, dimensions.y - 1),
Point(dimensions.x - 1, 0),
Point(dimensions.x - 1, dimensions.y - 1),
}
for p in map(
Point._make,
itertools.product(range(dimensions.x), range(dimensions.y)),
):
num_alive = sum(n in lights for n in neighbours(p))
if p in lights and num_alive not in (2, 3):
continue
if p not in lights and num_alive != 3:
continue
res.add(p)
return res
lights = parse(input)
dimensions = Point(100, 100)
lights |= {
# Four corners are stuck on
Point(0, 0),
Point(0, dimensions.y - 1),
Point(dimensions.x - 1, 0),
Point(dimensions.x - 1, dimensions.y - 1),
}
for _ in range(100):
lights = step(lights, dimensions)
return len(lights)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

100
2015/d18/ex2/input Normal file
View file

@ -0,0 +1,100 @@
###.##..##.#..#.##...#..#.####..#.##.##.##..###...#....#...###..#..###..###.#.#.#..#.##..#...##.#..#
.#...##.#####..##.......#..####.###.##.#..###.###.....#.#.####.##.###..##...###....#.##.....#.#.#.##
.....#.#.....#..###..####..#.....##.#..###.####.#.######..##......#####.#.##.#########.###..#.##.#.#
...###......#.#..###..#.#.....#.##..#.##..###...#.##.#..#..#.##.#..##......##.##.##.######...#....##
.###.....#...#.#...####.#.###..#..####.#..#.##..####...##.#...#..###...###...####..##....####.##..#.
..#....#...#.......#..###.###....#.##..#.....###.#.##.#....#.#....##.##..#.##.#..###.###.##.##..##.#
##..#####.#.#....#.#...#.#.####..#....#..#....#.#..#.#####...#..##.#.....#.##..##.####......#.#.##..
.#..##..#.#.###..##..##...#....##...#..#.#..##.##..###.####.....#.####.#.....##.#.##...#..####..#...
#.#####.......#####...#...####.#.#.#....#.###.#.##.#####..#.###.#..##.##.#.##....#.##..#....####.#.#
#.##...#####....##.#.#.....##......##.##...#.##.##...##...###.###.##.#.####.####.##..#.##.#.#.####..
#.##.##....###.###.#..#..##.##.#..#.#..##..#.#...#.##........###..#...##.#.#.##.......##.....#...###
###..#.#..##.##.#.#.#...#..#...##.##.#.########.......#.#...#....########..#.#.###..#.#..#.##..#####
####.#.#...#.##.##..#.#...#....#..###..#.#.#.####.#.##.##.#..##..##..#..#####.####.##..########..##.
.#.#...#..##.#..#..###.#..####.......##.#.#.#.##.#####..#..##...#.##...#..#....#..#..###..####.#....
..#.#...#....##...#####..#..#...###.###.....#.###.#....#.#..##...#.##.##.####.#.#.#..#.##.#....#.#..
#....###.####.##..#.#.###..###.##.##..#.#...###..#.##.#####.##.#######..#.#...##.#..........####.###
#.#####.#......#.#......#.....##...##.#.#########.#......##..##..##.#..##.##..#....##...###...#.#...
#..#..##..###.#.#.#.#.....###.#.####.##.##....#.#..##....#.#..#.####..###.##...#######.#####.##.#.#.
..###.#........##.#...###..#.##..#.#....##.#......#..#.##..#.#..#.#..#.####.#####..###.##..#.##.#...
##.###....#..##...#..#.#......##..#...#..#.####..#.##...##.####.#...#..###...#.#.#....###.##..#.#...
..##.##.#.##..##.#..#.###...##..##..#....##..##...####.#..####.###...#.....#..#.##..##..###..#.#...#
#.#....#.....#...##.#...####..#..##..##.####..##..##...####...#....##.#.#######..##.#......######.#.
#.#...###.######.######..##..##....#.#......#......#.#.##.#.##.#.#.#...#...#....#.#.#.#..#.##..#...#
####.###.#.#.##..#.##.#...#.##...#.##.##...#.....#.#..#.####.##..######.#..#.#..##....#.#.#..#.#.#.#
..##......#.#...#.##.##..##..##..#..##..#########.#..###..###.##...#..##.#..#.#.#.######..#....#.#..
..##.##.#...###.#...##..######.##.#..####..#..#.#.##.####.##.##.#...##....#...###.##.####..#....#.#.
####...###..#.#.##.#.#....###..##.#.#..########..#...#.#...#.##....##.##...#.....#.#.....#.....#....
.#.###############....#.##..###..#.####.#.##.##..#..#.#...###...##..##.##.#.....##...###.###.....#..
.###..#..##.##..####.#.###.##.##..#..##....#.#......#......##.#...#.#...#..##.#.#...#...#.##..#.##..
###.#.#.########.#.#..####.#..##.#.##.##.###.##..######...#..##.##.#..#.#...#.##..#####.....#.#.#..#
.##.##..#.#...#####.#.#.###...##...####...#......#...#..####..#.##..........#..#.#..###....######.##
..#####...#.#.#.#..#.##..#...#.#..#.##...##..##.##.#.##.#..#.#...#.......##.#...###.....#...#.#.#.##
##.##.#..######.##...#.....#.###.#..##.#.#.#..####.#....##.#....####...##....#.#.##.#..###.##.##..##
.###.##.#..#.###.####..#.##..####.#.#.##..###.#######.###.###...####........##....###.#...#.#.####.#
........#..#.#..##..########..........#.##.#..##.#...#.....####....##..#..#.#####.###...#...#.##.###
.....#..##.####...##.#####..######.##.#.###.####.##.##.#..##.##.######.##......#..#.####..##....#.##
##...####....#.##.##.###....#.#...#.####..##.#.##.#.#...####.#.#.#.#...##.###...##...###...######.##
.#....#.#.####...#.##.....##...###.#.#.##...##.#####....#.######.#.#....##..##...##....##.#.##.#.#.#
.###..###.#.......#.#######..#.#.#.######....#.#####.#.....#.#########...#....##...##.####.#..#.....
##.#..##..##.....#..##...#..##.##.#..#.#####.##.##.#.##.##...##.######.####..#.##..#####.##...##..#.
#.###...##.#.#.#.##....#.#.##.##..#....#...#.#.........#..#..####..####.####..#.##.##.#....####..##.
.#..######..#####.####.##.#.....#.#.#####..##..###.#.#.#..#.#...#.#######..##....##.##...#######..#.
#...#....#.#.##..#####..#########..#.....#...##.#.#.###...#####..##...##...####.......#######.#..###
.#......#...##.###..#....#...#.#.....#.#...##.#.#..#..###.##.###.#.##..##...#.##......#.###..#.#..##
.#....####...###..#.....##..#...#.#.###.#.#.##...#.##.##.#.#.#..####..###.#.#.#.##.#.#...#..#...####
......##.##.#...#####.##..#.###..#.#####..##.#..##.###......#...#...#..#......###.######...#.#.##..#
###..#...#.##..###.#....##...#..#####.#.#..#.###...#####.#....##..####.#.##...#.#...##..#.#.#.#..#.#
...##.#.##.##..#.#.#.###.#.#...#.....###.###.##...#.###.##...##..#..###.#..##.##..###.#....###..##..
.##.#..###..###.##.##...#..#####...#.....#####.##..####...#.##.#.#..##.#.#.#....###.....#....##.....
######.#..#.#..#....#.###...####.####.#.........#..##.#..##..##.....#..#.##.##...#...#####.#.##..#.#
.##.###...####....#.####...#####..#..#...#..#.....###.#..#.###..#.###.#.......##.####..#.##.#...##..
........#.#.##.#.....#####.###......##..#.##.#..#...####.#...#..###.#.#...##..#.#...#.####...#.#.###
.#..#.##..##...######.###.##.#.#...#.#.#.#.##..##..##.#.##..#....#.##...#.##.##...##....##.###.##.#.
##...#...#...###.#.#...#...#..###......##.#.#....##..##.#..##.#.######...#..##.#.##.#.#....#.##.##..
...#..###.#....#...#.##..##.#.##.#..###.##..#.##..####.#########....#.....##.#.##.##..##.##.######.#
#.##.#..##.......###...#.###....###.#..####..##.#####.##.###....##....#.###...####..#.#.#.##.....###
.......#...#...##.#...##.#.#..#.##..##.#....###...##.#####...#.........#.......###.##.#.#.###....##.
###.#.##.##.....#.#..#.#..####.####..#..###..........####.#.##...#######.###..#####..#.....#..###..#
#...##.##..####.##.###.#.#######..###.#..#######..#.##.####...#..#.##.####..####.#.#.......####.#...
...#.##..#..#..##........#.#..#..#.#....#.###.#.###..#.......###..#.....#....#..##.#...#.###...##.#.
###.##..#.##.#.#####..#.##.####....#####..###.#.#..#...#...###.#.##..#.#.#.....#.####.#.#.#.#.#.#...
..##..##..#..##.##.#...#..#....####....#...#..####..#.....######.###.####.#....##....##.#.#.###....#
.#.#.#.##..####..#.....#.####.#....#.....#....#.##..#.#..#.#...#.#.#.#..#..#..##.#....####.......#..
..##.##..###......#...#..##...#.###.####.#...#.####..#.#.#.....#.#...####...#.########.##.#.#.#..###
#....#.##.....##.###.##.###..#.####.....####.##...#..##.###...###..###.#....####.#..#..#..#.#..##.#.
.#.#.##....#.##......#.#..###.#....###....#......#.#.##.##.#########..##..#...#.####..#...####..#..#
.#.#.......##.#.##.#...#...#.##.#..#.#.#.##....#..###.###.##.#.#...##.#..#..##....#..###.#...#.#.##.
#.##.#....####...#..##..#.#.#.#.##.#...#####.#...#..#..#.####.####.#.#....#......##..##..###...#..##
..##.###..##.####..#..#..##...###.#.#.#######.####...####......##.##..#...#.##...##....#..#..#.....#
....#..#..#.#.####.#...##..#....####.#..####...#.#...###...#..#..##...#....##...#.....#.#..#.#.#...#
...#.#.#.##..##.###..#.######....####.###...##...###.#...##.####..#.#..#.#..#.##.....#.#.#..##......
.#.##.##.....##.#..###.###.##....#...###.#......#...##.###.#.##.##...###...###...#.######..#......#.
###..#...#......#..##...#....##.#..###.##.####..##..##....####.#...#.#....##..#.#######..#.#.#####..
##...#####..####..##....#.#.###.##.#..#.#..#.....###...###.#####.....#..##.#......#...#.###.##.##...
...#.#.#..#.###..#.#.#....##.#.#..####.##.#.####.#.#.#...#....##....#.##.####..###.#.#...##.#..#..##
#.#.#..#.##..##.##.#...##.#....#...###..##..#.#######.#.###..##......##.#..###.########.#.##..#.#.##
######.###....##..#..#...####....#.#.#..#...#..######.#.#.##..##....##....##.##.##...#..#.####.#.#..
#####.###..#..###......##...##.####.#.#.#.###.......##..##.####..##.####.#..#..####..#.####.#####...
##.#.#.###..##.#.##.#.#.#.##.#...##........###.#.##..####....###.#.####.####.#.......##.##.##...##..
#.#..###...#..##.....##.#..#.#..##..######.#####...###.#.......###...#..##..#..#..##.#.#....#..#..#.
#.#..####.###..#...#...#...#.###..#.#.#.#.#.#.#..#....#.##.##.##..###..####.#..##..##.###.###....##.
#..#.##.#####........#..#.##.#..##.#...#....#..#.##..###..##..##.##..#..##.#.#...#.#.##.#.##....#.#.
.......##..#.....#..#.#.....#.##...####.###..####..#.#.#.#..#.....#....##...#..#.##..###.#.#....#...
#...###########.##.....##...###.#.##.##..####.##...#.####.#####.#####.####...###.##...##..#.#.###..#
....#.#.###.####.###...#...#.#..###.#.#.##...#..#.#.#..#.####..#..###.######.#.####.###...###.#.##.#
.....#..#..########...#.#.#.#.#.#.#.#..###.##..####...##.#.#.#...##..#####.##.#...#.####.#######.##.
.......#...#.#..#..#...#..#..##.....#.##....##.##...##..##.##...##...#.#..#.##.#.###.#.####.#.#..##.
.####...#...#.#.#....##..........##.##.###.##.#.#..#.#.#......########.#...#.####.##.###..##...####.
#.#.#...##.###..##..#..#.....####.#.....##.##.#..#.#.###.#..#######...##..#.#..#.#..############.###
.##..####.#..#.....###..#..#.#.....#.#.#...##.##.#....#..#..###.#...#....#.#...####..#.....###.####.
..#...#.###.###....##.#..#.##..####.##.#.##.##.##...###.####..#.#.#.##.#.#.#..###..##.##.##.##.#..##
#...............##.....######.#.#####.##.#....#.#..#.##...#.##....#........##.##...#.##.##.#..#.##.#
#..##..#.#.#.##.#..#.#.##.##...#...#..#.#.##..#.#...###...##...###..#####.#.#..#..#.#..#.#.##...##.#
.#######.#.....##...#.#.####.######.#..#......#....##.#.#..#..###.#...###...#....#.#..#.##.#...#.#..
#.###......##.#.##..#.###.###..####..##....#..###......##..##..#####.####....#...###.....###.#..#...
###...#....###.#..#.###.##...###.##.......##.##.#.#.#....####....###..##.###...#..##....#.#.##..##..
.##.......##.######.#.#..#..##....#####.###.#.##.....####....#......####....#.##.#.##..#.##...##.#.#
.#.###...#.#.#.##.###..###...##..#.##.##..##..#.....###.#..#.##.##.####........##.#####.#.#....#...#
##...##..#.##.#######.###.#.##.#####....##.....##.#.....#.#.##.#....#.##.#....##.#..#.###..#..#.#...
.#..#.#.#.#...#.##...###.##.#.#...###.##...#.#..###....###.#.###...##..###..#..##.##....###...###.##

45
2015/d19/ex1/ex1.py Executable file
View file

@ -0,0 +1,45 @@
#!/usr/bin/env python
import collections
import sys
from collections.abc import Iterator
def solve(input: str) -> int:
def parse(input: str) -> tuple[dict[str, list[str]], str]:
raw_replacements, molecule = input.strip().split("\n\n")
res: dict[str, list[str]] = collections.defaultdict(list)
for start, end in (
line.split(" => ") for line in raw_replacements.splitlines()
):
res[start].append(end)
return res, molecule
def replace_needle(input: str, needle: str, to: str) -> Iterator[str]:
assert needle in input # Sanity check
i = input.find(needle)
while i != -1:
yield input[:i] + to + input[i + len(needle) :]
i = input.find(needle, i + 1)
def do_replacements(
replacements: dict[str, list[str]], molecule: str
) -> Iterator[str]:
for needle, vals in replacements.items():
if needle not in molecule:
continue
for to in vals:
yield from replace_needle(molecule, needle, to)
replacements, molecule = parse(input)
new_molecules = set(do_replacements(replacements, molecule))
return len(new_molecules)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

45
2015/d19/ex1/input Normal file
View file

@ -0,0 +1,45 @@
Al => ThF
Al => ThRnFAr
B => BCa
B => TiB
B => TiRnFAr
Ca => CaCa
Ca => PB
Ca => PRnFAr
Ca => SiRnFYFAr
Ca => SiRnMgAr
Ca => SiTh
F => CaF
F => PMg
F => SiAl
H => CRnAlAr
H => CRnFYFYFAr
H => CRnFYMgAr
H => CRnMgYFAr
H => HCa
H => NRnFYFAr
H => NRnMgAr
H => NTh
H => OB
H => ORnFAr
Mg => BF
Mg => TiMg
N => CRnFAr
N => HSi
O => CRnFYFAr
O => CRnMgAr
O => HP
O => NRnFAr
O => OTi
P => CaP
P => PTi
P => SiRnFAr
Si => CaSi
Th => ThCa
Ti => BP
Ti => TiTi
e => HF
e => NAl
e => OMg
CRnCaSiRnBSiRnFArTiBPTiTiBFArPBCaSiThSiRnTiBPBPMgArCaSiRnTiMgArCaSiThCaSiRnFArRnSiRnFArTiTiBFArCaCaSiRnSiThCaCaSiRnMgArFYSiRnFYCaFArSiThCaSiThPBPTiMgArCaPRnSiAlArPBCaCaSiRnFYSiThCaRnFArArCaCaSiRnPBSiRnFArMgYCaCaCaCaSiThCaCaSiAlArCaCaSiRnPBSiAlArBCaCaCaCaSiThCaPBSiThPBPBCaSiRnFYFArSiThCaSiRnFArBCaCaSiRnFYFArSiThCaPBSiThCaSiRnPMgArRnFArPTiBCaPRnFArCaCaCaCaSiRnCaCaSiRnFYFArFArBCaSiThFArThSiThSiRnTiRnPMgArFArCaSiThCaPBCaSiRnBFArCaCaPRnCaCaPMgArSiRnFYFArCaSiThRnPBPMgAr

49
2015/d19/ex2/ex2.py Executable file
View file

@ -0,0 +1,49 @@
#!/usr/bin/env python
import collections
import sys
def solve(input: str) -> int:
def parse(input: str) -> tuple[dict[str, list[str]], str]:
raw_replacements, molecule = input.strip().split("\n\n")
res: dict[str, list[str]] = collections.defaultdict(list)
for start, end in (
line.split(" => ") for line in raw_replacements.splitlines()
):
res[start].append(end)
return res, molecule
def inverse(input: dict[str, list[str]]) -> dict[str, str]:
res: dict[str, str] = {}
for key, vals in input.items():
for val in vals:
res[val] = key
assert len(res) == sum(map(len, input.values())) # Sanity check
return res
def build(replacements: dict[str, list[str]], molecule: str) -> int:
# We will be "building down" to the electron, so inverse the replacement mapping
inversed_replacements = inverse(replacements)
# Order the replacement needles to try the longest ones first
needles = sorted(inversed_replacements.keys(), key=len, reverse=True)
res = 0
while molecule != "e":
for needle in needles:
if needle not in molecule:
continue
res += 1
molecule = molecule.replace(needle, inversed_replacements[needle], 1)
return res
replacements, molecule = parse(input)
return build(replacements, molecule)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

45
2015/d19/ex2/input Normal file
View file

@ -0,0 +1,45 @@
Al => ThF
Al => ThRnFAr
B => BCa
B => TiB
B => TiRnFAr
Ca => CaCa
Ca => PB
Ca => PRnFAr
Ca => SiRnFYFAr
Ca => SiRnMgAr
Ca => SiTh
F => CaF
F => PMg
F => SiAl
H => CRnAlAr
H => CRnFYFYFAr
H => CRnFYMgAr
H => CRnMgYFAr
H => HCa
H => NRnFYFAr
H => NRnMgAr
H => NTh
H => OB
H => ORnFAr
Mg => BF
Mg => TiMg
N => CRnFAr
N => HSi
O => CRnFYFAr
O => CRnMgAr
O => HP
O => NRnFAr
O => OTi
P => CaP
P => PTi
P => SiRnFAr
Si => CaSi
Th => ThCa
Ti => BP
Ti => TiTi
e => HF
e => NAl
e => OMg
CRnCaSiRnBSiRnFArTiBPTiTiBFArPBCaSiThSiRnTiBPBPMgArCaSiRnTiMgArCaSiThCaSiRnFArRnSiRnFArTiTiBFArCaCaSiRnSiThCaCaSiRnMgArFYSiRnFYCaFArSiThCaSiThPBPTiMgArCaPRnSiAlArPBCaCaSiRnFYSiThCaRnFArArCaCaSiRnPBSiRnFArMgYCaCaCaCaSiThCaCaSiAlArCaCaSiRnPBSiAlArBCaCaCaCaSiThCaPBSiThPBPBCaSiRnFYFArSiThCaSiRnFArBCaCaSiRnFYFArSiThCaPBSiThCaSiRnPMgArRnFArPTiBCaPRnFArCaCaCaCaSiRnCaCaSiRnFYFArFArBCaSiThFArThSiThSiRnTiRnPMgArFArCaSiThCaPBCaSiRnBFArCaCaPRnCaCaPMgArSiRnFYFArCaSiThRnPBPMgAr

24
2015/d20/ex1/ex1.py Executable file
View file

@ -0,0 +1,24 @@
#!/usr/bin/env python
import sys
def solve(input: str) -> int:
needed = int(input.strip())
presents = [0] * (needed // 10) # Surely this should be enough houses
for i in range(1, len(presents)):
for j in range(i, len(presents), i):
presents[j] += 10 * i
for i, total in enumerate(presents):
if total >= needed:
return i
assert False # Sanity check
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d20/ex1/input Normal file
View file

@ -0,0 +1 @@
36000000

26
2015/d20/ex2/ex2.py Executable file
View file

@ -0,0 +1,26 @@
#!/usr/bin/env python
import sys
def solve(input: str) -> int:
needed = int(input.strip())
presents = [0] * (needed // 10) # Surely this should be enough houses
for i in range(1, len(presents)):
for j in range(1, 50 + 1):
if (i * j) >= len(presents):
continue
presents[i * j] += 11 * i
for i, total in enumerate(presents):
if total >= needed:
return i
assert False # Sanity check
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d20/ex2/input Normal file
View file

@ -0,0 +1 @@
36000000

104
2015/d21/ex1/ex1.py Executable file
View file

@ -0,0 +1,104 @@
#!/usr/bin/env python
import itertools
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Ennemy(NamedTuple):
hp: int
damage: int
armor: int
def attack(self, other: "Ennemy") -> "Ennemy":
return Ennemy(
other.hp - max(1, self.damage - other.armor),
other.damage,
other.armor,
)
class Item(NamedTuple):
cost: int
damage: int
armor: int
WEAPONS = {
"Dagger": Item(8, 4, 0),
"Shortsword": Item(10, 5, 0),
"Warhammer": Item(25, 6, 0),
"Longsword": Item(40, 7, 0),
"Greataxe": Item(74, 8, 0),
}
ARMORS = {
"Leather": Item(13, 0, 1),
"Chainmail": Item(31, 0, 2),
"Splintmail": Item(53, 0, 3),
"Bandedmail": Item(75, 0, 4),
"Platemail": Item(102, 0, 5),
}
RINGS = {
"Damage +1": Item(25, 1, 0),
"Damage +2": Item(50, 2, 0),
"Damage +3": Item(100, 3, 0),
"Defense +1": Item(20, 0, 1),
"Defense +2": Item(40, 0, 2),
"Defense +3": Item(80, 0, 3),
}
def solve(input: str) -> int:
def parse(input: str) -> Ennemy:
return Ennemy(*map(int, (line.split(": ")[1] for line in input.splitlines())))
def choose_items() -> Iterator[list[Item]]:
allowed_weapons = [1]
allowed_armors = [0, 1]
allowed_rings = [0, 1, 2]
for weapons, armors, rings in itertools.product(
itertools.chain.from_iterable(
itertools.combinations(WEAPONS.values(), i) for i in allowed_weapons
),
itertools.chain.from_iterable(
itertools.combinations(ARMORS.values(), i) for i in allowed_armors
),
itertools.chain.from_iterable(
itertools.combinations(RINGS.values(), i) for i in allowed_rings
),
):
yield list(itertools.chain(weapons, armors, rings))
def assemble_inventory(items: list[Item]) -> Ennemy:
return Ennemy(
hp=100,
damage=sum(item.damage for item in items),
armor=sum(item.armor for item in items),
)
def battle(us: Ennemy, ennemy: Ennemy) -> bool:
while True:
ennemy = us.attack(ennemy)
if ennemy.hp <= 0:
return True
us = ennemy.attack(us)
if us.hp <= 0:
return False
ennemy = parse(input)
return min(
sum(item.cost for item in items)
for items in choose_items()
if battle(assemble_inventory(items), ennemy)
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

3
2015/d21/ex1/input Normal file
View file

@ -0,0 +1,3 @@
Hit Points: 109
Damage: 8
Armor: 2

104
2015/d21/ex2/ex2.py Executable file
View file

@ -0,0 +1,104 @@
#!/usr/bin/env python
import itertools
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Ennemy(NamedTuple):
hp: int
damage: int
armor: int
def attack(self, other: "Ennemy") -> "Ennemy":
return Ennemy(
other.hp - max(1, self.damage - other.armor),
other.damage,
other.armor,
)
class Item(NamedTuple):
cost: int
damage: int
armor: int
WEAPONS = {
"Dagger": Item(8, 4, 0),
"Shortsword": Item(10, 5, 0),
"Warhammer": Item(25, 6, 0),
"Longsword": Item(40, 7, 0),
"Greataxe": Item(74, 8, 0),
}
ARMORS = {
"Leather": Item(13, 0, 1),
"Chainmail": Item(31, 0, 2),
"Splintmail": Item(53, 0, 3),
"Bandedmail": Item(75, 0, 4),
"Platemail": Item(102, 0, 5),
}
RINGS = {
"Damage +1": Item(25, 1, 0),
"Damage +2": Item(50, 2, 0),
"Damage +3": Item(100, 3, 0),
"Defense +1": Item(20, 0, 1),
"Defense +2": Item(40, 0, 2),
"Defense +3": Item(80, 0, 3),
}
def solve(input: str) -> int:
def parse(input: str) -> Ennemy:
return Ennemy(*map(int, (line.split(": ")[1] for line in input.splitlines())))
def choose_items() -> Iterator[list[Item]]:
allowed_weapons = [1]
allowed_armors = [0, 1]
allowed_rings = [0, 1, 2]
for weapons, armors, rings in itertools.product(
itertools.chain.from_iterable(
itertools.combinations(WEAPONS.values(), i) for i in allowed_weapons
),
itertools.chain.from_iterable(
itertools.combinations(ARMORS.values(), i) for i in allowed_armors
),
itertools.chain.from_iterable(
itertools.combinations(RINGS.values(), i) for i in allowed_rings
),
):
yield list(itertools.chain(weapons, armors, rings))
def assemble_inventory(items: list[Item]) -> Ennemy:
return Ennemy(
hp=100,
damage=sum(item.damage for item in items),
armor=sum(item.armor for item in items),
)
def battle(us: Ennemy, ennemy: Ennemy) -> bool:
while True:
ennemy = us.attack(ennemy)
if ennemy.hp <= 0:
return True
us = ennemy.attack(us)
if us.hp <= 0:
return False
ennemy = parse(input)
return max(
sum(item.cost for item in items)
for items in choose_items()
if not battle(assemble_inventory(items), ennemy)
)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

3
2015/d21/ex2/input Normal file
View file

@ -0,0 +1,3 @@
Hit Points: 109
Damage: 8
Armor: 2

166
2015/d22/ex1/ex1.py Executable file
View file

@ -0,0 +1,166 @@
#!/usr/bin/env python
import heapq
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Ennemy(NamedTuple):
hp: int
damage: int
class Effects(NamedTuple):
# Effect is active is it is greater or equal to zero
shield: int = -1
poison: int = -1
recharge: int = -1
def tick(self) -> "Effects":
return Effects(*(n - 1 for n in self))
def shield_active(self) -> bool:
return self.shield >= 0
def poison_active(self) -> bool:
return self.poison >= 0
def recharge_active(self) -> bool:
return self.recharge >= 0
def with_shield(self) -> "Effects":
assert self.shield <= 0 # Sanity check
return self._replace(shield=6)
def with_poison(self) -> "Effects":
assert self.poison <= 0 # Sanity check
return self._replace(poison=6)
def with_recharge(self) -> "Effects":
assert self.recharge <= 0 # Sanity check
return self._replace(recharge=5)
class Player(NamedTuple):
hp: int
mana: int
effects: Effects
MISSILE = 53
DRAIN = 73
SHIELD = 113
POISON = 173
RECHARGE = 229
def solve(input: str) -> int:
def parse(input: str) -> Ennemy:
return Ennemy(*map(int, (line.split(": ")[1] for line in input.splitlines())))
def step(player: Player, ennemy: Ennemy) -> Iterator[tuple[int, Player, Ennemy]]:
def tick_spells(player: Player, ennemy: Ennemy) -> tuple[Player, Ennemy]:
player = player._replace(effects=player.effects.tick())
if player.effects.recharge_active():
player = player._replace(mana=player.mana + 101)
if player.effects.poison_active():
ennemy = ennemy._replace(hp=ennemy.hp - 3)
return player, ennemy
# Note: does *not* drain the mana for the spell
def possible_spells(
player: Player,
ennemy: Ennemy,
) -> Iterator[tuple[int, Player, Ennemy]]:
if player.mana >= MISSILE:
yield (
MISSILE,
player,
ennemy._replace(hp=ennemy.hp - 4),
)
if player.mana >= DRAIN:
yield (
DRAIN,
player._replace(hp=player.hp + 2),
ennemy._replace(hp=ennemy.hp - 2),
)
if player.mana >= SHIELD and player.effects.shield <= 0:
yield (
SHIELD,
player._replace(effects=player.effects.with_shield()),
ennemy,
)
if player.mana >= POISON and player.effects.poison <= 0:
yield (
POISON,
player._replace(effects=player.effects.with_poison()),
ennemy,
)
if player.mana >= RECHARGE and player.effects.recharge <= 0:
yield (
RECHARGE,
player._replace(effects=player.effects.with_recharge()),
ennemy,
)
def boss_turn(player: Player, ennemy: Ennemy) -> tuple[Player, Ennemy]:
# Spells are ticked at start of turn
player, ennemy = tick_spells(player, ennemy)
# Ennemy can't attack if they're dead
if ennemy.hp <= 0:
return player, ennemy
armor = 7 if player.effects.shield_active() else 0
damage = max(1, ennemy.damage - armor)
return player._replace(hp=player.hp - damage), ennemy
# We lose if we run out of hp
if player.hp <= 0:
return
# Spells are ticked at start of turn
player, ennemy = tick_spells(player, ennemy)
# Don't spend a spell if the ennemy is already dead
if ennemy.hp <= 0:
yield 0, player, ennemy
for cost, player, ennemy in possible_spells(player, ennemy):
yield cost, *boss_turn(player._replace(mana=player.mana - cost), ennemy)
def dijkstra(player: Player, ennemy: Ennemy) -> int:
# Priority queue of (mana_spent, player, ennemy)
queue = [(0, player, ennemy)]
seen: set[tuple[Player, Ennemy]] = set()
while len(queue) > 0:
total_cost, p, e = heapq.heappop(queue)
if p.hp <= 0:
continue
if e.hp <= 0:
return total_cost
# We must have seen (p, e) with a smaller distance before
if (p, e) in seen:
continue
# First time encountering (p, e), must be the smallest distance to it
seen.add((p, e))
# Add all neighbours to be visited
for cost, p, e in step(p, e):
heapq.heappush(queue, (total_cost + cost, p, e))
assert False # Sanity check
ennemy = parse(input)
player = Player(50, 500, Effects())
return dijkstra(player, ennemy)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

2
2015/d22/ex1/input Normal file
View file

@ -0,0 +1,2 @@
Hit Points: 51
Damage: 9

168
2015/d22/ex2/ex2.py Executable file
View file

@ -0,0 +1,168 @@
#!/usr/bin/env python
import heapq
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Ennemy(NamedTuple):
hp: int
damage: int
class Effects(NamedTuple):
# Effect is active is it is greater or equal to zero
shield: int = -1
poison: int = -1
recharge: int = -1
def tick(self) -> "Effects":
return Effects(*(n - 1 for n in self))
def shield_active(self) -> bool:
return self.shield >= 0
def poison_active(self) -> bool:
return self.poison >= 0
def recharge_active(self) -> bool:
return self.recharge >= 0
def with_shield(self) -> "Effects":
assert self.shield <= 0 # Sanity check
return self._replace(shield=6)
def with_poison(self) -> "Effects":
assert self.poison <= 0 # Sanity check
return self._replace(poison=6)
def with_recharge(self) -> "Effects":
assert self.recharge <= 0 # Sanity check
return self._replace(recharge=5)
class Player(NamedTuple):
hp: int
mana: int
effects: Effects
MISSILE = 53
DRAIN = 73
SHIELD = 113
POISON = 173
RECHARGE = 229
def solve(input: str) -> int:
def parse(input: str) -> Ennemy:
return Ennemy(*map(int, (line.split(": ")[1] for line in input.splitlines())))
def step(player: Player, ennemy: Ennemy) -> Iterator[tuple[int, Player, Ennemy]]:
def tick_spells(player: Player, ennemy: Ennemy) -> tuple[Player, Ennemy]:
player = player._replace(effects=player.effects.tick())
if player.effects.recharge_active():
player = player._replace(mana=player.mana + 101)
if player.effects.poison_active():
ennemy = ennemy._replace(hp=ennemy.hp - 3)
return player, ennemy
# Note: does *not* drain the mana for the spell
def possible_spells(
player: Player,
ennemy: Ennemy,
) -> Iterator[tuple[int, Player, Ennemy]]:
if player.mana >= MISSILE:
yield (
MISSILE,
player,
ennemy._replace(hp=ennemy.hp - 4),
)
if player.mana >= DRAIN:
yield (
DRAIN,
player._replace(hp=player.hp + 2),
ennemy._replace(hp=ennemy.hp - 2),
)
if player.mana >= SHIELD and player.effects.shield <= 0:
yield (
SHIELD,
player._replace(effects=player.effects.with_shield()),
ennemy,
)
if player.mana >= POISON and player.effects.poison <= 0:
yield (
POISON,
player._replace(effects=player.effects.with_poison()),
ennemy,
)
if player.mana >= RECHARGE and player.effects.recharge <= 0:
yield (
RECHARGE,
player._replace(effects=player.effects.with_recharge()),
ennemy,
)
def boss_turn(player: Player, ennemy: Ennemy) -> tuple[Player, Ennemy]:
# Spells are ticked at start of turn
player, ennemy = tick_spells(player, ennemy)
# Ennemy can't attack if they're dead
if ennemy.hp <= 0:
return player, ennemy
armor = 7 if player.effects.shield_active() else 0
damage = max(1, ennemy.damage - armor)
return player._replace(hp=player.hp - damage), ennemy
# Apply hard mode HP loss
player = player._replace(hp=player.hp - 1)
# We lose if we run out of hp
if player.hp <= 0:
return
# Spells are ticked at start of turn
player, ennemy = tick_spells(player, ennemy)
# Don't spend a spell if the ennemy is already dead
if ennemy.hp <= 0:
yield 0, player, ennemy
for cost, player, ennemy in possible_spells(player, ennemy):
yield cost, *boss_turn(player._replace(mana=player.mana - cost), ennemy)
def dijkstra(player: Player, ennemy: Ennemy) -> int:
# Priority queue of (mana_spent, player, ennemy)
queue = [(0, player, ennemy)]
seen: set[tuple[Player, Ennemy]] = set()
while len(queue) > 0:
total_cost, p, e = heapq.heappop(queue)
if p.hp <= 0:
continue
if e.hp <= 0:
return total_cost
# We must have seen (p, e) with a smaller distance before
if (p, e) in seen:
continue
# First time encountering (p, e), must be the smallest distance to it
seen.add((p, e))
# Add all neighbours to be visited
for cost, p, e in step(p, e):
heapq.heappush(queue, (total_cost + cost, p, e))
assert False # Sanity check
ennemy = parse(input)
player = Player(50, 500, Effects())
return dijkstra(player, ennemy)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

2
2015/d22/ex2/input Normal file
View file

@ -0,0 +1,2 @@
Hit Points: 51
Damage: 9

67
2015/d23/ex1/ex1.py Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env python
import enum
import sys
from typing import NamedTuple
class Op(enum.StrEnum):
HLF = "hlf"
TPL = "tpl"
INC = "inc"
JMP = "jmp"
JIE = "jie"
JIO = "jio"
class Instruction(NamedTuple):
op: Op
x: str
y: str | None = None
@classmethod
def from_str(cls, input: str) -> "Instruction":
op, rest = input.split(None, 1)
return cls(Op(op), *rest.split(", "))
def solve(input: str) -> int:
def parse(input: str) -> list[Instruction]:
return [Instruction.from_str(line) for line in input.splitlines()]
instructions = parse(input)
registers: dict[str, int] = {"a": 0, "b": 0}
ip = 0
while True:
if ip < 0 or ip >= len(instructions):
break
instr = instructions[ip]
ip += 1
match instr.op:
case Op.HLF:
registers[instr.x] //= 2
case Op.TPL:
registers[instr.x] *= 3
case Op.INC:
registers[instr.x] += 1
case Op.JMP:
ip += int(instr.x) - 1 # Account auto-increment
case Op.JIE:
assert instr.y is not None
if registers[instr.x] % 2 == 0:
ip += int(instr.y) - 1 # Account auto-increment
case Op.JIO:
assert instr.y is not None
if registers[instr.x] == 1:
ip += int(instr.y) - 1 # Account auto-increment
return registers["b"]
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

46
2015/d23/ex1/input Normal file
View file

@ -0,0 +1,46 @@
jio a, +16
inc a
inc a
tpl a
tpl a
tpl a
inc a
inc a
tpl a
inc a
inc a
tpl a
tpl a
tpl a
inc a
jmp +23
tpl a
inc a
inc a
tpl a
inc a
inc a
tpl a
tpl a
inc a
inc a
tpl a
inc a
tpl a
inc a
tpl a
inc a
inc a
tpl a
inc a
tpl a
tpl a
inc a
jio a, +8
inc b
jie a, +4
tpl a
inc a
jmp +2
hlf a
jmp -7

67
2015/d23/ex2/ex2.py Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env python
import enum
import sys
from typing import NamedTuple
class Op(enum.StrEnum):
HLF = "hlf"
TPL = "tpl"
INC = "inc"
JMP = "jmp"
JIE = "jie"
JIO = "jio"
class Instruction(NamedTuple):
op: Op
x: str
y: str | None = None
@classmethod
def from_str(cls, input: str) -> "Instruction":
op, rest = input.split(None, 1)
return cls(Op(op), *rest.split(", "))
def solve(input: str) -> int:
def parse(input: str) -> list[Instruction]:
return [Instruction.from_str(line) for line in input.splitlines()]
instructions = parse(input)
registers: dict[str, int] = {"a": 1, "b": 0}
ip = 0
while True:
if ip < 0 or ip >= len(instructions):
break
instr = instructions[ip]
ip += 1
match instr.op:
case Op.HLF:
registers[instr.x] //= 2
case Op.TPL:
registers[instr.x] *= 3
case Op.INC:
registers[instr.x] += 1
case Op.JMP:
ip += int(instr.x) - 1 # Account auto-increment
case Op.JIE:
assert instr.y is not None
if registers[instr.x] % 2 == 0:
ip += int(instr.y) - 1 # Account auto-increment
case Op.JIO:
assert instr.y is not None
if registers[instr.x] == 1:
ip += int(instr.y) - 1 # Account auto-increment
return registers["b"]
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

46
2015/d23/ex2/input Normal file
View file

@ -0,0 +1,46 @@
jio a, +16
inc a
inc a
tpl a
tpl a
tpl a
inc a
inc a
tpl a
inc a
inc a
tpl a
tpl a
tpl a
inc a
jmp +23
tpl a
inc a
inc a
tpl a
inc a
inc a
tpl a
tpl a
inc a
inc a
tpl a
inc a
tpl a
inc a
tpl a
inc a
inc a
tpl a
inc a
tpl a
tpl a
inc a
jio a, +8
inc b
jie a, +4
tpl a
inc a
jmp +2
hlf a
jmp -7

46
2015/d24/ex1/ex1.py Executable file
View file

@ -0,0 +1,46 @@
#!/usr/bin/env python
import itertools
import math
import sys
def solve(input: str) -> int:
def parse(input: str) -> list[int]:
return [int(n) for n in input.splitlines()]
def package_groups(packages: list[int]) -> tuple[list[int], list[int], list[int]]:
assert sum(packages) % 3 == 0 # Sanity check
target_weight = sum(packages) // 3
# I'm lazy, a brute-force double loop is good enough
for first_len in range(1, len(packages) + 1):
for perm in itertools.combinations(range(len(packages)), first_len):
first = [packages[p] for p in perm]
if sum(first) != target_weight:
continue
others = [p for i, p in enumerate(packages) if i not in perm]
for sec_len in range(1, len(others) + 1):
for perm in itertools.combinations(range(len(others)), sec_len):
second = [others[p] for p in perm]
if sum(second) != target_weight:
continue
last = [p for i, p in enumerate(others) if i not in perm]
return first, second, last
assert False # Sanity check
def quantum_entanglement(packages: list[int]) -> int:
return math.prod(packages)
packages = parse(input)
best_split = package_groups(packages)
return quantum_entanglement(best_split[0])
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

29
2015/d24/ex1/input Normal file
View file

@ -0,0 +1,29 @@
1
2
3
7
11
13
17
19
23
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113

71
2015/d24/ex2/ex2.py Executable file
View file

@ -0,0 +1,71 @@
#!/usr/bin/env python
import itertools
import math
import sys
from collections.abc import Iterator
def solve(input: str) -> int:
def parse(input: str) -> list[int]:
return [int(n) for n in input.splitlines()]
def package_groups(
packages: list[int],
) -> Iterator[tuple[list[int], list[int], list[int], list[int]]]:
assert sum(packages) % 4 == 0 # Sanity check
target_weight = sum(packages) // 4
# I'm lazy, a brute-force triple loop is good enough
found = False
for first_len in range(1, len(packages) + 1):
for perm in itertools.combinations(range(len(packages)), first_len):
first = [packages[p] for p in perm]
if sum(first) != target_weight:
continue
others = [p for i, p in enumerate(packages) if i not in perm]
for sec_len in range(1, len(others) + 1):
for perm in itertools.combinations(range(len(others)), sec_len):
second = [others[p] for p in perm]
if sum(second) != target_weight:
continue
others_ = [p for i, p in enumerate(others) if i not in perm]
for third_len in range(1, len(others_) + 1):
for perm in itertools.combinations(
range(len(others_)), third_len
):
third = [others_[p] for p in perm]
last = [
others_[i]
for i in range(len(others_))
if i not in perm
]
yield first, second, third, last
# We only care to enumerate all valid *first* packages
# Not *all* permutations
found = True
break
if found:
break
if found:
break
if found:
break
# *Don't* break if `found`, we want to keep enumerating this length
if found:
break
def quantum_entanglement(packages: list[int]) -> int:
return math.prod(packages)
packages = parse(input)
return min(quantum_entanglement(split[0]) for split in package_groups(packages))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

29
2015/d24/ex2/input Normal file
View file

@ -0,0 +1,29 @@
1
2
3
7
11
13
17
19
23
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113

43
2015/d25/ex1/ex1.py Executable file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env python
import sys
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
def solve(input: str) -> int:
def parse(input: str) -> tuple[int, int]:
*_, row, column = input.replace(".", "").split(", ")
return int(row.split()[-1]), int(column.split()[-1])
def mod_pow(n: int, pow: int, mod: int) -> int:
if pow == 0:
return 1
if pow == 1:
return n % mod
res = mod_pow(n, pow // 2, mod) ** 2
if pow % 2 == 1:
res *= n
return res % mod
def lookup(row: int, column: int) -> int:
n = column + row - 1
top_right = n * (n + 1) // 2
i = top_right - row
return 20151125 * mod_pow(252533, i, 33554393) % 33554393
row, column = parse(input)
return lookup(row, column)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()

1
2015/d25/ex1/input Normal file
View file

@ -0,0 +1 @@
To continue, please consult the code grid in the manual. Enter the code at row 2947, column 3029.

9
2015/d25/ex2/ex2.py Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env python
def main() -> None:
print("There is no part two...")
if __name__ == "__main__":
main()

1
2015/d25/ex2/input Normal file
View file

@ -0,0 +1 @@
To continue, please consult the code grid in the manual. Enter the code at row 2947, column 3029.