-
Notifications
You must be signed in to change notification settings - Fork 0
/
exercise.go
112 lines (97 loc) · 2.93 KB
/
exercise.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package exercises
import (
"fmt"
"strconv"
"strings"
"github.com/asphaltbuffet/advent-of-code/internal/common"
)
// Exercise for Advent of Code 2022 day 21.
type Exercise struct {
common.BaseExercise
}
// One returns the answer to the first part of the exercise.
// answer:
func (e Exercise) One(instr string) (any, error) {
raw := parse(instr)
result, err := calc("root", raw, make(map[string]int))
if err != nil {
return nil, fmt.Errorf("calculating part 1 answer: %w", err)
}
return result, nil
}
// Two returns the answer to the second part of the exercise.
// wrong: 7010269744524
// answer: 3558714869436
func (e Exercise) Two(instr string) (any, error) {
raw := parse(instr)
results := map[string]int{}
// force error when calculating "humn"
raw["humn"] = "die_die_die"
// change root equation to be left / right = 1
reversed := map[string]string{"root": "1"}
orig := strings.Split(raw["root"], " ")
orig[1] = "/"
raw["root"] = strings.Join(orig, " ")
currentName := "root"
for currentName != "humn" {
var left, operator, right string
_, _ = fmt.Sscanf(raw[currentName], "%s %s %s", &left, &operator, &right)
leftVal, errLeft := calc(left, raw, results)
if errLeft == nil {
reversed[left] = strconv.Itoa(leftVal)
}
rightVal, errRight := calc(right, raw, results)
if errRight == nil {
reversed[right] = strconv.Itoa(rightVal)
}
switch operator {
case "+":
switch {
case errLeft != nil:
reversed[left] = fmt.Sprintf("%s - %s", currentName, right)
currentName = left
case errRight != nil:
reversed[right] = fmt.Sprintf("%s - %s", currentName, left)
currentName = right
default:
return nil, fmt.Errorf("no error path found in %q: %s", currentName, raw[currentName])
}
case "-":
switch {
case errLeft != nil:
reversed[left] = fmt.Sprintf("%s + %s", currentName, right)
currentName = left
case errRight != nil:
reversed[right] = fmt.Sprintf("%s - %s", left, currentName)
currentName = right
default:
return nil, fmt.Errorf("no error path found in %q: %s", currentName, raw[currentName])
}
case "*":
switch {
case errLeft != nil:
reversed[left] = fmt.Sprintf("%s / %s", currentName, right)
currentName = left
case errRight != nil:
reversed[right] = fmt.Sprintf("%s / %s", currentName, left)
currentName = right
default:
return nil, fmt.Errorf("no error path found in %q: %s", currentName, raw[currentName])
}
case "/":
switch {
case errLeft != nil:
reversed[left] = fmt.Sprintf("%s * %s", currentName, right)
currentName = left
case errRight != nil:
reversed[right] = fmt.Sprintf("%s / %s", left, currentName)
currentName = right
default:
return nil, fmt.Errorf("no error path found in %q: %s", currentName, raw[currentName])
}
default:
return nil, fmt.Errorf("%q has invalid operator in %q", currentName, raw[currentName])
}
}
return calc("humn", reversed, map[string]int{})
}