Skip to content

Commit f39c837

Browse files
authored
migrate 2024 code, refactor (#16)
1 parent 67ba48d commit f39c837

File tree

14 files changed

+2278
-26
lines changed

14 files changed

+2278
-26
lines changed

inputs/year_2024/01.dat

Lines changed: 1000 additions & 0 deletions
Large diffs are not rendered by default.

inputs/year_2024/02.dat

Lines changed: 1000 additions & 0 deletions
Large diffs are not rendered by default.

inputs/year_2024/03.dat

Lines changed: 6 additions & 0 deletions
Large diffs are not rendered by default.

scripts/generate_new_day_skeleton_files_from_templates.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import argparse
33

44

5-
TEMPLATES_PATH = os.path.join(".", "src", "advent_of_code", "scripts", "templates")
5+
TEMPLATES_PATH = os.path.join("scripts", "templates")
66

77

88
def parse_input_args():
@@ -45,26 +45,18 @@ def generate_file(template_file_path, input_day, input_year, output_file_path):
4545

4646
if __name__ == "__main__":
4747
args = parse_input_args()
48-
input_day = args.day
48+
input_day_raw = args.day
4949
input_year = args.year
50+
input_day = str(input_day_raw).zfill(2)
5051

5152
day_file_dest = os.path.join(
52-
"src", "advent_of_code", f"year_{input_year}", f"days/{input_day}.py"
53+
"src", "advent_of_code", f"year_{input_year}", f"day_{input_day}.py"
5354
)
5455
template_path = os.path.join(TEMPLATES_PATH, "days_template.txt")
5556
generate_file(template_path, input_day, input_year, day_file_dest)
5657

57-
solvers_file_dest = os.path.join(
58-
"src",
59-
"advent_of_code",
60-
f"year_{input_year}",
61-
f"solvers/day_{input_day}_solvers.py",
62-
)
63-
template_path = os.path.join(TEMPLATES_PATH, "solvers_template.txt")
64-
generate_file(template_path, input_day, input_year, solvers_file_dest)
65-
6658
tests_file_dest = os.path.join(
67-
"tests", f"year_{input_year}", f"test_day_{input_day}_solvers.py"
59+
"tests", f"year_{input_year}", f"test_day_{input_day}.py"
6860
)
6961
template_path = os.path.join(TEMPLATES_PATH, "tests_template.txt")
7062
generate_file(template_path, input_day, input_year, tests_file_dest)

scripts/templates/days_template.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
from advent_of_code.year_{year}.solvers.day_{day}_solvers import (
2-
solve_day_{day},
3-
)
4-
from advent_of_code.utils.input_handling import read_input, parse_args
1+
from advent_of_code.utils.input_handling import read_input
52

63

7-
def main():
8-
args = parse_args()
9-
input = read_input(args.input_file)
10-
result_part_1, result_part_2 = solve_day_{day}(input)
4+
def solve(input):
5+
return (None, None)
6+
7+
8+
def main(input_file):
9+
input = read_input(input_file)
10+
(result_part_1, result_part_2) = solve(input)
1111
print(
1212
f"Day {day}: "
1313
f" Result for part 1 is {result_part_1}. "

scripts/templates/solvers_template.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

scripts/templates/tests_template.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
2-
from advent_of_code.year_{year}.solvers.day_{day}_solvers import (
3-
solve_day_{day},
2+
from advent_of_code.year_{year}.day_{day} import (
3+
solve,
44
)
55

66

src/advent_of_code/utils/input_handling.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,12 @@ def parse_args():
1414
parser.add_argument("--part", type=int)
1515
args = parser.parse_args()
1616
return args
17+
18+
19+
def read_side_by_side_list_format(data):
20+
list1, list2 = [], []
21+
for line in data:
22+
list1.append(int(line.split()[0]))
23+
list2.append(int(line.split()[1]))
24+
25+
return (list1, list2)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from advent_of_code.utils.input_handling import read_input, read_side_by_side_list_format
2+
3+
def compute_distance(i, j):
4+
return abs(i - j)
5+
6+
7+
def solve_part_1(parsed_input):
8+
(list1, list2) = parsed_input
9+
list1_ordered = list(sorted(list1))
10+
list2_ordered = list(sorted(list2))
11+
12+
total_distance = 0
13+
14+
for i, j in zip(list1_ordered, list2_ordered):
15+
total_distance += compute_distance(i, j)
16+
17+
return total_distance
18+
19+
20+
def compute_similarity(i, lst):
21+
return i * lst.count(i)
22+
23+
24+
def solve_part_2(parsed_input):
25+
(list1, list2) = parsed_input
26+
27+
total_similarity_score = 0
28+
29+
for element in list1:
30+
total_similarity_score += compute_similarity(element, list2)
31+
32+
return total_similarity_score
33+
34+
35+
36+
def solve(input):
37+
parsed_input = read_side_by_side_list_format(input)
38+
part_1_solution = solve_part_1(parsed_input)
39+
part_2_solution = solve_part_2(parsed_input)
40+
return (part_1_solution, part_2_solution)
41+
42+
43+
def main(input_file):
44+
input = read_input(input_file)
45+
(result_part_1, result_part_2) = solve(input)
46+
print(
47+
f"Day 01: "
48+
f" Result for part 1 is {result_part_1}. "
49+
f" Result for part 2 is {result_part_2}. "
50+
)
51+
52+
53+
if __name__ == "__main__":
54+
main()
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from advent_of_code.utils.input_handling import read_input
2+
3+
def is_report_safe(report,):
4+
if not ((report==sorted(report)) or (report==sorted(report,reverse=True))):
5+
return False
6+
7+
differences = [abs(report[i+1] - report[i]) for i in range(len(report) - 1)]
8+
if ((max(differences) > 3) or (min(differences)<1)):
9+
return False
10+
11+
return True
12+
13+
14+
def solve_part_1(input):
15+
safe_report_count = 0
16+
for report in input:
17+
if is_report_safe(report):
18+
safe_report_count += 1
19+
return safe_report_count
20+
21+
22+
def solve_part_2(input,):
23+
24+
safe_report_count = 0
25+
26+
for report in input:
27+
if is_report_safe(report):
28+
safe_report_count += 1
29+
else:
30+
for idx, _ in enumerate(report):
31+
tmp_report = report[:]
32+
del tmp_report[idx]
33+
if is_report_safe(tmp_report,):
34+
safe_report_count += 1
35+
break
36+
return safe_report_count
37+
38+
39+
def solve(input):
40+
part_1_solution = solve_part_1(input)
41+
part_2_solution = solve_part_2(input)
42+
return (part_1_solution, part_2_solution)
43+
44+
45+
def parse_input(input_data,dtype=int):
46+
data = [list(map(dtype, line.rstrip("\n").split())) for line in input_data]
47+
return data
48+
49+
50+
def main(input_file):
51+
unparsed_input = read_input(input_file)
52+
parsed_input = parse_input(unparsed_input)
53+
(result_part_1, result_part_2) = solve(parsed_input)
54+
print(
55+
f"Day 02: "
56+
f" Result for part 1 is {result_part_1}. "
57+
f" Result for part 2 is {result_part_2}. "
58+
)
59+
60+
61+
if __name__ == "__main__":
62+
main()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
import re
3+
import math
4+
5+
DO_SUBSTR = 'do()'
6+
DONT_SUBSTR = 'don\'t()'
7+
8+
def find_valid_substrings(s, match_str=r'mul\(\d+,\d+\)'):
9+
return re.findall(match_str, s)
10+
11+
def find_and_multiply_valid_muls_in_string(input_string):
12+
string_score = 0
13+
valid_muls = find_valid_substrings(input_string)
14+
for m in valid_muls:
15+
found_ints = find_valid_substrings(m, match_str=r'\d+')
16+
string_score += math.prod(map(int, found_ints))
17+
return string_score
18+
19+
def instruction_compute(instruction, use_do_dont_rule=False):
20+
21+
if not use_do_dont_rule:
22+
instruction_score = find_and_multiply_valid_muls_in_string(instruction)
23+
else:
24+
instruction_score=0
25+
padded_instruction = DO_SUBSTR+instruction.strip("\n")+DONT_SUBSTR
26+
valid_subs = find_valid_substrings(
27+
padded_instruction,
28+
match_str=r"mul\((\d+),(\d+)\)|(do\(\))|(don't\(\))"
29+
)
30+
counting_active = False
31+
for (i, j, do, dont) in valid_subs:
32+
if do:
33+
counting_active = True
34+
elif dont:
35+
counting_active = False
36+
else:
37+
if counting_active:
38+
instruction_score += int(i)*int(j)
39+
return instruction_score
40+
41+
def solve(input):
42+
43+
part_1_solution, part_2_solution = 0, 0
44+
part_1_solution = instruction_compute(input, False)
45+
part_2_solution = instruction_compute(input, True)
46+
return (part_1_solution, part_2_solution)
47+
48+
49+
def main(input_file):
50+
input = input = open(input_file).read()
51+
(result_part_1, result_part_2) = solve(input)
52+
print(
53+
f"Day 03: "
54+
f" Result for part 1 is {result_part_1}. "
55+
f" Result for part 2 is {result_part_2}. "
56+
)
57+
58+
59+
if __name__ == "__main__":
60+
main()

tests/year_2024/test_day_01.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import pytest
2+
from advent_of_code.year_2024.day_01 import (
3+
solve,
4+
)
5+
6+
7+
@pytest.fixture
8+
def day_01_test_input():
9+
return [
10+
"3 4",
11+
"4 3",
12+
"2 5",
13+
"1 3",
14+
"3 9",
15+
"3 3",
16+
]
17+
18+
19+
@pytest.fixture
20+
def day_01_expected_output():
21+
return (11, 31)
22+
23+
24+
def test_solver(day_01_test_input, day_01_expected_output):
25+
result = solve(day_01_test_input)
26+
assert result == day_01_expected_output

tests/year_2024/test_day_02.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
from advent_of_code.year_2024.day_02 import (
3+
solve,
4+
parse_input,
5+
)
6+
7+
8+
@pytest.fixture
9+
def day_02_test_input():
10+
return [
11+
"7 6 4 2 1",
12+
"1 2 7 8 9",
13+
"9 7 6 2 1",
14+
"1 3 2 4 5",
15+
"8 6 4 4 1",
16+
"1 3 6 7 9",
17+
]
18+
19+
20+
@pytest.fixture
21+
def day_02_expected_output():
22+
return (2,4)
23+
24+
25+
def test_solver(day_02_test_input, day_02_expected_output):
26+
day_02_test_input_parsed = parse_input(day_02_test_input)
27+
result = solve(day_02_test_input_parsed)
28+
assert result == day_02_expected_output

tests/year_2024/test_day_03.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import pytest
2+
from advent_of_code.year_2024.day_03 import (
3+
instruction_compute,
4+
)
5+
6+
@pytest.mark.parametrize("input, use_do_dont_rule, expected", [
7+
["xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))", False, 161],
8+
["xmul(2,4)", False, 8],
9+
["%&mul[3,7]!@^do_not_mul(5,5)", False, 25],
10+
["mul(11,8)mul(8,5)", False, 128],
11+
["xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))", True, 48],
12+
])
13+
def test_instruction_compute(input, use_do_dont_rule, expected):
14+
result = instruction_compute(input, use_do_dont_rule=use_do_dont_rule)
15+
print(result)
16+
assert result == expected
17+
18+

0 commit comments

Comments
 (0)