From a8dbb6bd2281087279d2b587484c133a4cce8fa9 Mon Sep 17 00:00:00 2001 From: FrederikBaerentsen Date: Sat, 7 Dec 2024 16:57:34 +0100 Subject: [PATCH] Solved 2024/07 P1+P2 --- 2024/07/7.md | 103 ++++++++++++++++++++++++++++++++++++++++++++ 2024/07/solution.py | 77 +++++++++++++++++++++++++++++++++ 2024/07/test.py | 23 ++++++++++ 3 files changed, 203 insertions(+) create mode 100644 2024/07/7.md create mode 100644 2024/07/solution.py create mode 100644 2024/07/test.py diff --git a/2024/07/7.md b/2024/07/7.md new file mode 100644 index 0000000..4c5b84d --- /dev/null +++ b/2024/07/7.md @@ -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). + diff --git a/2024/07/solution.py b/2024/07/solution.py new file mode 100644 index 0000000..d85b065 --- /dev/null +++ b/2024/07/solution.py @@ -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) + diff --git a/2024/07/test.py b/2024/07/test.py new file mode 100644 index 0000000..567349e --- /dev/null +++ b/2024/07/test.py @@ -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])))