Skip to content

Commit f6537b7

Browse files
committed
Added days 2020-12 and 2020-13
1 parent 17e9266 commit f6537b7

File tree

2 files changed

+262
-0
lines changed

2 files changed

+262
-0
lines changed

2020/12-Rain Risk.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, grid, graph, dot, assembly, re, itertools
3+
from collections import Counter, deque, defaultdict
4+
5+
from compass import *
6+
7+
8+
# This functions come from https://github.com/mcpower/adventofcode - Thanks!
9+
def lmap(func, *iterables):
10+
return list(map(func, *iterables))
11+
12+
13+
def ints(s: str):
14+
return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano!
15+
16+
17+
def positive_ints(s: str):
18+
return lmap(int, re.findall(r"\d+", s)) # thanks mserrano!
19+
20+
21+
def floats(s: str):
22+
return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s))
23+
24+
25+
def positive_floats(s: str):
26+
return lmap(float, re.findall(r"\d+(?:\.\d+)?", s))
27+
28+
29+
def words(s: str):
30+
return re.findall(r"[a-zA-Z]+", s)
31+
32+
33+
test_data = {}
34+
35+
test = 1
36+
test_data[test] = {
37+
"input": """F10
38+
N3
39+
F7
40+
R90
41+
F11""",
42+
"expected": ["25", "286"],
43+
}
44+
45+
test = "real"
46+
input_file = os.path.join(
47+
os.path.dirname(__file__),
48+
"Inputs",
49+
os.path.basename(__file__).replace(".py", ".txt"),
50+
)
51+
test_data[test] = {
52+
"input": open(input_file, "r+").read(),
53+
"expected": ["820", "66614"],
54+
}
55+
56+
57+
# -------------------------------- Control program execution ------------------------- #
58+
59+
case_to_test = "real"
60+
part_to_test = 2
61+
62+
# -------------------------------- Initialize some variables ------------------------- #
63+
64+
puzzle_input = test_data[case_to_test]["input"]
65+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
66+
puzzle_actual_result = "Unknown"
67+
68+
69+
# -------------------------------- Actual code execution ----------------------------- #
70+
71+
relative_directions = {
72+
"L": 1j,
73+
"R": -1j,
74+
"F": 1,
75+
"B": -1,
76+
}
77+
78+
79+
if part_to_test == 1:
80+
position = 0
81+
direction = east
82+
for string in puzzle_input.split("\n"):
83+
if string[0] in ("N", "S", "E", "W"):
84+
position += text_to_direction[string[0]] * int(string[1:])
85+
elif string[0] == "F":
86+
position += direction * int(string[1:])
87+
elif string[0] in ("L", "R"):
88+
angle = int(string[1:]) % 360
89+
if angle == 0:
90+
pass
91+
elif angle == 90:
92+
direction *= relative_directions[string[0]]
93+
elif angle == 180:
94+
direction *= -1
95+
elif angle == 270:
96+
direction *= -1 * relative_directions[string[0]]
97+
98+
puzzle_actual_result = int(abs(position.real) + abs(position.imag))
99+
100+
101+
else:
102+
ship_pos = 0
103+
wpt_rel_pos = 10 + 1j
104+
for string in puzzle_input.split("\n"):
105+
if string[0] in ("N", "S", "E", "W"):
106+
wpt_rel_pos += text_to_direction[string[0]] * int(string[1:])
107+
elif string[0] == "F":
108+
delta = wpt_rel_pos * int(string[1:])
109+
ship_pos += delta
110+
elif string[0] in ("L", "R"):
111+
angle = int(string[1:]) % 360
112+
if angle == 0:
113+
pass
114+
elif angle == 90:
115+
wpt_rel_pos *= relative_directions[string[0]]
116+
elif angle == 180:
117+
wpt_rel_pos *= -1
118+
elif angle == 270:
119+
wpt_rel_pos *= -1 * relative_directions[string[0]]
120+
121+
puzzle_actual_result = int(abs(ship_pos.real) + abs(ship_pos.imag))
122+
123+
124+
# -------------------------------- Outputs / results --------------------------------- #
125+
126+
print("Case :", case_to_test, "- Part", part_to_test)
127+
print("Expected result : " + str(puzzle_expected_result))
128+
print("Actual result : " + str(puzzle_actual_result))
129+
# Date created: 2020-12-12 07:21:36.624800
130+
# Part 1: 2020-12-12 07:28:36
131+
# Part 2: 2020-12-12 07:34:51

2020/13-Shuttle Search.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, grid, graph, dot, assembly, re, itertools, math
3+
from collections import Counter, deque, defaultdict
4+
5+
from compass import *
6+
7+
8+
# This functions come from https://github.com/mcpower/adventofcode - Thanks!
9+
def lmap(func, *iterables):
10+
return list(map(func, *iterables))
11+
12+
13+
def ints(s: str):
14+
return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano!
15+
16+
17+
def positive_ints(s: str):
18+
return lmap(int, re.findall(r"\d+", s)) # thanks mserrano!
19+
20+
21+
def floats(s: str):
22+
return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s))
23+
24+
25+
def positive_floats(s: str):
26+
return lmap(float, re.findall(r"\d+(?:\.\d+)?", s))
27+
28+
29+
def words(s: str):
30+
return re.findall(r"[a-zA-Z]+", s)
31+
32+
33+
test_data = {}
34+
35+
test = 1
36+
test_data[test] = {
37+
"input": """939
38+
7,13,x,x,59,x,31,19""",
39+
"expected": ["295", "1068781"],
40+
}
41+
42+
test = "real"
43+
input_file = os.path.join(
44+
os.path.dirname(__file__),
45+
"Inputs",
46+
os.path.basename(__file__).replace(".py", ".txt"),
47+
)
48+
test_data[test] = {
49+
"input": open(input_file, "r+").read(),
50+
"expected": ["2382", "906332393333683"],
51+
}
52+
53+
54+
# -------------------------------- Control program execution ------------------------- #
55+
56+
case_to_test = "real"
57+
part_to_test = 2
58+
59+
# -------------------------------- Initialize some variables ------------------------- #
60+
61+
puzzle_input = test_data[case_to_test]["input"]
62+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
63+
puzzle_actual_result = "Unknown"
64+
65+
66+
# -------------------------------- Actual code execution ----------------------------- #
67+
68+
if part_to_test == 1:
69+
data = puzzle_input.split("\n")
70+
curr_time = int(data[0])
71+
busses = ints(data[1])
72+
next_time = curr_time * 10
73+
74+
for bus in busses:
75+
next_round = bus - curr_time % bus + curr_time
76+
print(next_round, bus, curr_time)
77+
if next_round < next_time:
78+
next_time = next_round
79+
next_bus = bus
80+
81+
puzzle_actual_result = (next_time - curr_time) * next_bus
82+
83+
84+
else:
85+
data = puzzle_input.split("\n")
86+
busses = data[1].split(",")
87+
bus_offsets = {}
88+
89+
i = 0
90+
for bus in busses:
91+
if bus == "x":
92+
pass
93+
else:
94+
bus_offsets[int(bus)] = i
95+
i += 1
96+
97+
timestamp = 0
98+
99+
# I first solved this thanks to a diophantine equation solvers found on Internet
100+
101+
# Then I looked at the solutions megathread to learn more
102+
# This is the proper algorithm that works in a feasible time
103+
# It's called the Chinese remainder theorem
104+
# See https://crypto.stanford.edu/pbc/notes/numbertheory/crt.html
105+
prod_modulos = math.prod(bus_offsets.keys())
106+
for bus, offset in bus_offsets.items():
107+
timestamp += -offset * (prod_modulos // bus) * pow(prod_modulos // bus, -1, bus)
108+
timestamp %= prod_modulos
109+
110+
# The below algorithm is the brute-force version: very slow but should work
111+
# Since timestamp is calculated above, this won't do anything
112+
# To make it run, uncomment the below line
113+
# timestamp = 0
114+
115+
min_bus = min(bus_offsets.keys())
116+
while True:
117+
if all([(timestamp + bus_offsets[bus]) % bus == 0 for bus in bus_offsets]):
118+
puzzle_actual_result = timestamp
119+
break
120+
else:
121+
timestamp += min_bus
122+
123+
124+
# -------------------------------- Outputs / results --------------------------------- #
125+
126+
print("Case :", case_to_test, "- Part", part_to_test)
127+
print("Expected result : " + str(puzzle_expected_result))
128+
print("Actual result : " + str(puzzle_actual_result))
129+
# Date created: 2020-12-13 06:25:25.641468
130+
# Part 1: 2020-12-13 06:31:06
131+
# Part 2: 2020-12-13 07:12:10

0 commit comments

Comments
 (0)