Solved 2024/07 P1+P2

This commit is contained in:
FrederikBaerentsen 2024-12-07 16:57:34 +01:00
parent 21f5c91742
commit a8dbb6bd22
3 changed files with 203 additions and 0 deletions

103
2024/07/7.md Normal file
View File

@ -0,0 +1,103 @@
## \-\-- Day 7: Bridge Repair \-\--
The Historians take you to a familiar [rope bridge](/2022/day/9) over a
river in the middle of a jungle. The Chief isn\'t on this side of the
bridge, though; maybe he\'s on the other side?
When you go to cross the bridge, you notice a group of engineers trying
to repair it. (Apparently, it breaks pretty frequently.) You won\'t be
able to cross until it\'s fixed.
You ask how long it\'ll take; the engineers tell you that it only needs
final calibrations, but some young elephants were playing nearby and
*stole all the operators* from their calibration equations! They could
finish the calibrations if only someone could determine which test
values could possibly be produced by placing any combination of
operators into their calibration equations (your puzzle input).
For example:
190: 10 19
3267: 81 40 27
83: 17 5
156: 15 6
7290: 6 8 6 15
161011: 16 10 13
192: 17 8 14
21037: 9 7 18 13
292: 11 6 16 20
Each line represents a single equation. The test value appears before
the colon on each line; it is your job to determine whether the
remaining numbers can be combined with operators to produce the test
value.
Operators are *always evaluated left-to-right*, *not* according to
precedence rules. Furthermore, numbers in the equations cannot be
rearranged. Glancing into the jungle, you can see elephants holding two
different types of operators: *add* (`+`) and *multiply* (`*`).
Only three of the above equations can be made true by inserting
operators:
- `190: 10 19` has only one position that accepts an operator: between
`10` and `19`. Choosing `+` would give `29`, but choosing `*` would
give the test value (`10 * 19 = 190`).
- `3267: 81 40 27` has two positions for operators. Of the four
possible configurations of the operators, *two* cause the right side
to match the test value: `81 + 40 * 27` and `81 * 40 + 27` both
equal `3267` (when evaluated left-to-right)!
- `292: 11 6 16 20` can be solved in exactly one way:
`11 + 6 * 16 + 20`.
The engineers just need the *total calibration result*, which is the sum
of the test values from just the equations that could possibly be true.
In the above example, the sum of the test values for the three equations
listed above is `3749`.
Determine which equations could possibly be true. *What is their total
calibration result?*
Your puzzle answer was `1038838357795`.
## \-\-- Part Two \-\-- {#part2}
The engineers seem concerned; the total calibration result you gave them
is nowhere close to being within safety tolerances. Just then, you spot
your mistake: some well-hidden elephants are holding a *third type of
operator*.
The
[concatenation](https://en.wikipedia.org/wiki/Concatenation)
operator (`||`) combines the digits from its left and right inputs into
a single number. For example, `12 || 345` would become `12345`. All
operators are still evaluated left-to-right.
Now, apart from the three equations that could be made true using only
addition and multiplication, the above example has three more equations
that can be made true by inserting operators:
- `156: 15 6` can be made true through a single concatenation:
`15 || 6 = 156`.
- `7290: 6 8 6 15` can be made true using `6 * 8 || 6 * 15`.
- `192: 17 8 14` can be made true using `17 || 8 + 14`.
Adding up all six test values (the three that could be made before using
only `+` and `*` plus the new three that can now be made by also using
`||`) produces the new *total calibration result* of `11387`.
Using your new knowledge of elephant hiding spots, determine which
equations could possibly be true. *What is their total calibration
result?*
Your puzzle answer was `254136560217241`.
Both parts of this puzzle are complete! They provide two gold stars:
\*\*
At this point, you should [return to your Advent calendar](/2024) and
try another puzzle.
If you still want to see it, you can [get your puzzle
input](7/input).

77
2024/07/solution.py Normal file
View File

@ -0,0 +1,77 @@
#!/bin/python3
import sys,re
from pprint import pprint
sys.path.insert(0, '../../')
from fred import list2int,get_re,nprint,lprint
input_f = 'input'
part = 2
#########################################
# #
# Part 1 #
# #
#########################################
def loadFile(input_f):
# For some reason, when this is a dict {}
# and i use instructions[int(a[0])] = list2int(b)
# the line with 360: 8 3 7 4 1 is not used in the
# for loop that runs through all the instructions.
instructions = []
with open(input_f) as file:
for line in file:
a = line.rstrip().split(': ')
b = a[1].split(' ')
instructions.append([int(a[0]),list2int(b)])
return instructions
if part == 1:
def calculateResult(a:int,b:list,result:int):
if not b:
return result if result == a else 0
add = calculateResult(a,b[1:],b[0]+result)
mul = calculateResult(a,b[1:],b[0]*result)
return add or mul
instructions = loadFile(input_f)
result = 0
for idx,i in enumerate(instructions):
result += calculateResult(instructions[idx][0],instructions[idx][1],0)
print(result)
#########################################
# #
# Part 2 #
# #
#########################################
if part == 2:
def calculateResult2(a:int,b:list,result:int):
if not b:
return result if result == a else 0
add = calculateResult2(a,b[1:],b[0]+result)
mul = calculateResult2(a,b[1:],b[0]*result)
# Issues happened when i did b[0]||result. Reversing it
# gave me the right result.
con = calculateResult2(a,b[1:],int(str(result)+str(b[0])))
return add or mul or con
instructions = loadFile(input_f)
result = 0
for idx,i in enumerate(instructions):
print('Line',(idx+1),i)
result += calculateResult2(instructions[idx][0],instructions[idx][1],0)
print(result)

23
2024/07/test.py Normal file
View File

@ -0,0 +1,23 @@
import sys
file = open(sys.argv[1]).read()
lines = [line.split(": ") for line in file.splitlines()]
lines = [(int(test), list(map(int, args.split()))) for test, args in lines]
star, plus, concat = lambda x, y: x * y, lambda x, y: x + y, lambda x, y: int(f"{x}{y}")
def solve(targ, args, operators):
def inner(targ, args, curr):
if curr > targ:
return False
match args:
case []:
return curr == targ
case [arg, *rest]:
return any(inner(targ, rest, op(curr, arg)) for op in operators)
return inner(targ, args[1:], args[0])
print(sum(targ for targ, args in lines if solve(targ, args, [star, plus])))
print(sum(targ for targ, args in lines if solve(targ, args, [star, plus, concat])))