day 3 - part 2
This commit is contained in:
parent
aa67f2a238
commit
e32a98204d
5 changed files with 128 additions and 1 deletions
53
src/aoc_2024/day3/part2.py
Normal file
53
src/aoc_2024/day3/part2.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Match, List, Any
|
||||||
|
|
||||||
|
|
||||||
|
def detect_mul(data: str) -> list[Match]:
|
||||||
|
return re.findall(r"mul\((\d{1,3}),(\d{1,3})\)", data)
|
||||||
|
|
||||||
|
|
||||||
|
def compute_multiplication(data: str) -> int:
|
||||||
|
result = 0
|
||||||
|
for match in detect_mul(data):
|
||||||
|
left = int(match[0])
|
||||||
|
right = int(match[1])
|
||||||
|
result += left * right
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def find_activated_parts(data: str) -> str:
|
||||||
|
res = []
|
||||||
|
|
||||||
|
start_match = re.search(r"^.*?don't\(\)", data)
|
||||||
|
if start_match:
|
||||||
|
start_data = start_match[0]
|
||||||
|
res.append(start_data)
|
||||||
|
data = data.removeprefix(start_data)
|
||||||
|
|
||||||
|
middle_match = re.search(r"^.*don't\(\)", data)
|
||||||
|
if middle_match:
|
||||||
|
middle_data = middle_match[0]
|
||||||
|
matches = re.findall(r"do\(\).*?don't\(\)", middle_data)
|
||||||
|
res.extend(matches)
|
||||||
|
data = data.removeprefix(middle_data)
|
||||||
|
|
||||||
|
end_match = re.search(r"do\(\).*$", data)
|
||||||
|
if end_match:
|
||||||
|
end_data = end_match[0]
|
||||||
|
res.append(end_data)
|
||||||
|
|
||||||
|
return "".join(res)
|
||||||
|
|
||||||
|
|
||||||
|
def main(input_file: Path) -> int:
|
||||||
|
input_data = ""
|
||||||
|
for line in input_file.open():
|
||||||
|
input_data += line.strip()
|
||||||
|
activated_parts = find_activated_parts(input_data)
|
||||||
|
return compute_multiplication(activated_parts)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
file = Path(__file__).parent / "input-data"
|
||||||
|
print(main(file))
|
1
tests/aoc_2024/day3/test-data-part2
Normal file
1
tests/aoc_2024/day3/test-data-part2
Normal file
|
@ -0,0 +1 @@
|
||||||
|
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
|
|
@ -61,5 +61,5 @@ def test_compute_multiplication2_from_multiple_muls():
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
file = Path(__file__).parent / "test-data"
|
file = Path(__file__).parent / "test-data-part1"
|
||||||
assert part1.main(file) == 161
|
assert part1.main(file) == 161
|
||||||
|
|
73
tests/aoc_2024/day3/test_part2.py
Normal file
73
tests/aoc_2024/day3/test_part2.py
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from aoc_2024.day3 import part2
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_activated_parts():
|
||||||
|
input_data = "xmul(2,4)&mul[3,7]!^don't()_mdo()ul(5,5)+mudon't()l(32,64](mul(11,8)undo()?mul(8,5))"
|
||||||
|
assert (
|
||||||
|
part2.find_activated_parts(input_data)
|
||||||
|
== "xmul(2,4)&mul[3,7]!^don't()do()ul(5,5)+mudon't()do()?mul(8,5))"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_mul_is_successful():
|
||||||
|
res = part2.detect_mul("mul(1,5)")[0]
|
||||||
|
assert res[0] == "1"
|
||||||
|
assert res[1] == "5"
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_mul_with_3_digits_is_successful():
|
||||||
|
assert part2.detect_mul("mul(123,567)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_mul_with_4_digits_fails():
|
||||||
|
assert not part2.detect_mul("mul(1234,5678)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_mul_with_space_fails():
|
||||||
|
assert not part2.detect_mul("mul(123 ,678)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_mul_without_mul_fails():
|
||||||
|
assert not part2.detect_mul("div(1,5)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_multiple_muls_is_successful():
|
||||||
|
res = part2.detect_mul(
|
||||||
|
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
|
||||||
|
)
|
||||||
|
match1 = res[0]
|
||||||
|
assert match1[0] == "2"
|
||||||
|
assert match1[1] == "4"
|
||||||
|
match2 = res[1]
|
||||||
|
assert match2[0] == "5"
|
||||||
|
assert match2[1] == "5"
|
||||||
|
match3 = res[2]
|
||||||
|
assert match3[0] == "11"
|
||||||
|
assert match3[1] == "8"
|
||||||
|
match4 = res[3]
|
||||||
|
assert match4[0] == "8"
|
||||||
|
assert match4[1] == "5"
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_multiplication_from_mul():
|
||||||
|
assert part2.compute_multiplication("mul(1,5)") == 5
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_multiplication2_from_mul():
|
||||||
|
assert part2.compute_multiplication("mul(8,5)") == 40
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_multiplication2_from_multiple_muls():
|
||||||
|
assert (
|
||||||
|
part2.compute_multiplication(
|
||||||
|
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
|
||||||
|
)
|
||||||
|
== 161
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
file = Path(__file__).parent / "test-data-part2"
|
||||||
|
assert part2.main(file) == 48
|
Loading…
Add table
Add a link
Reference in a new issue