add part b solver, even if not "ideal"

This commit is contained in:
2024-12-28 15:15:48 +01:00
parent c600440930
commit 2398561b5f
2 changed files with 58 additions and 10 deletions

View File

@@ -0,0 +1,15 @@
## Part Two
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 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?

View File

@@ -1,8 +1,9 @@
package main
import (
"time"
"bufio"
"fmt"
"log"
"os"
"strconv"
"strings"
@@ -44,14 +45,14 @@ func load_puzzle_from_file(target_file_name string) []equation{
return equations_list
}
func generate_combinations(numbers int) []string{
func generate_combinations(numbers int, operators []string) []string{
if numbers == 0 {
return []string {""}
}
combinations := []string{}
for _, c := range []string {"+", "*"}{
for _, prev := range generate_combinations(numbers -1){
for _, c := range operators{
for _, prev := range generate_combinations(numbers -1, operators){
combinations = append(combinations, prev + string(c))
}
}
@@ -59,11 +60,12 @@ func generate_combinations(numbers int) []string{
return combinations
}
func calculate_all_operations_for_equation(eq equation) []string {
func calculate_all_operations_for_equation(eq equation, operations []string) []string {
var final_list []string
combinations := generate_combinations(len(eq.numbers) - 1)
list_combinations := generate_combinations(len(eq.numbers) - 1, operations)
for _, c := range combinations {
for _, c := range list_combinations {
//log.Println(list_combinations, idx, c)
final_list = append(final_list, c)
}
@@ -83,8 +85,14 @@ func is_equation_possible(eq equation, operations []string) bool {
if string(op) == "*" {
current_result = current_result * eq.numbers[ido + 1]
}
if string(op) == "|" {
temp_a := strconv.Itoa(current_result)
temp_b := strconv.Itoa(eq.numbers[ido + 1])
result_string := temp_a + temp_b
current_result, _ = strconv.Atoi(result_string)
}
}
//fmt.Println("Wanted vs Got: ", eq.target_number, current_result)
//log.Println("Wanted vs Got: ", eq.target_number, current_result)
if eq.target_number == current_result {
return true
}
@@ -92,14 +100,39 @@ func is_equation_possible(eq equation, operations []string) bool {
return false
}
func time_track(start time.Time, name string){
elapsed := time.Since(start)
log.Printf("%s took %s", name, elapsed)
}
func main() {
defer time_track(time.Now(), "main")
equations := load_puzzle_from_file(puzzle_file_name)
final_result := 0
possible_operations := []string {"+", "*"}
for _, eq := range equations {
operations_list := calculate_all_operations_for_equation(eq)
operations_list := calculate_all_operations_for_equation(eq, possible_operations)
if is_equation_possible(eq, operations_list){
final_result += eq.target_number
}
}
fmt.Println("Final Result: ", final_result)
log.Println("Final Result - Part A: ", final_result)
// this is WRONG
// the question clearly asks to use "||" as the operators
// I don't want to refactor the code base to handle 2 characters for the operations
//
// the fix would be to instead of returning an array of strings eg: [ +*|| *+|| ]
// to instead return a string of strings [ [+ * || ] [ * + || ] ]
// which would then allow for safe iteration
final_result = 0
possible_operations = []string {"+", "*", "|"}
for _, eq := range equations {
operations_list := calculate_all_operations_for_equation(eq, possible_operations)
if is_equation_possible(eq, operations_list){
final_result += eq.target_number
}
}
log.Println("Final Result - Part B: ", final_result)
}