🌅
This commit is contained in:
221
solutions/day21/day21.go
Normal file
221
solutions/day21/day21.go
Normal file
@@ -0,0 +1,221 @@
|
||||
package day21
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
OpAdd int = iota
|
||||
OpMul
|
||||
OpSub
|
||||
OpDiv
|
||||
OpTarget
|
||||
)
|
||||
|
||||
func opString(v int) string {
|
||||
switch v {
|
||||
case OpAdd:
|
||||
return "+"
|
||||
case OpMul:
|
||||
return "*"
|
||||
case OpSub:
|
||||
return "-"
|
||||
case OpDiv:
|
||||
return "/"
|
||||
case OpTarget:
|
||||
return "=="
|
||||
default:
|
||||
return "???????"
|
||||
}
|
||||
}
|
||||
|
||||
type MonkeyState struct {
|
||||
valueSet bool
|
||||
value int
|
||||
operation int
|
||||
left string
|
||||
right string
|
||||
}
|
||||
|
||||
func step(monkeys map[string]MonkeyState) bool {
|
||||
changedSomething := false
|
||||
|
||||
for monkey, state := range monkeys {
|
||||
if !state.valueSet && monkeys[state.left].valueSet && monkeys[state.right].valueSet {
|
||||
switch state.operation {
|
||||
case OpAdd:
|
||||
state.value = monkeys[state.left].value + monkeys[state.right].value
|
||||
case OpSub:
|
||||
state.value = monkeys[state.left].value - monkeys[state.right].value
|
||||
case OpMul:
|
||||
state.value = monkeys[state.left].value * monkeys[state.right].value
|
||||
case OpDiv:
|
||||
state.value = monkeys[state.left].value / monkeys[state.right].value
|
||||
}
|
||||
state.valueSet = true
|
||||
monkeys[monkey] = state
|
||||
changedSomething = true
|
||||
}
|
||||
}
|
||||
|
||||
return changedSomething
|
||||
}
|
||||
|
||||
func contains(ls []string, x string) bool {
|
||||
for _, tester := range ls {
|
||||
if tester == x {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Run(filename string) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file:", err)
|
||||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
monkeys := map[string]MonkeyState{}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
monkey := line[0:4]
|
||||
data := line[6:]
|
||||
value, err := strconv.Atoi(data)
|
||||
if err == nil {
|
||||
monkeys[monkey] = MonkeyState{true, value, 0, "", ""}
|
||||
} else {
|
||||
left := data[0:4]
|
||||
right := data[7:]
|
||||
switch data[5] {
|
||||
case '+':
|
||||
monkeys[monkey] = MonkeyState{false, 0, OpAdd, left, right}
|
||||
case '-':
|
||||
monkeys[monkey] = MonkeyState{false, 0, OpSub, left, right}
|
||||
case '*':
|
||||
monkeys[monkey] = MonkeyState{false, 0, OpMul, left, right}
|
||||
case '/':
|
||||
monkeys[monkey] = MonkeyState{false, 0, OpDiv, left, right}
|
||||
default:
|
||||
fmt.Println("Bad operation", string(data[5]))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
file.Close()
|
||||
|
||||
for !monkeys["root"].valueSet {
|
||||
step(monkeys)
|
||||
}
|
||||
fmt.Println("Root monkey value, part 1:", monkeys["root"].value)
|
||||
|
||||
humn := monkeys["humn"]
|
||||
humn.valueSet = false
|
||||
humn.operation = OpTarget
|
||||
monkeys["humn"] = humn
|
||||
unwoundMonkeys := []string{"humn"}
|
||||
updatedSomething := true
|
||||
for updatedSomething {
|
||||
updatedSomething = false
|
||||
for monkey, state := range monkeys {
|
||||
if contains(unwoundMonkeys, state.left) || contains(unwoundMonkeys, state.right) {
|
||||
if state.valueSet {
|
||||
state.valueSet = false
|
||||
monkeys[monkey] = state
|
||||
unwoundMonkeys = append(unwoundMonkeys, monkey)
|
||||
updatedSomething = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("monkeys now", monkeys)
|
||||
var targetValue int
|
||||
var nextNode string
|
||||
|
||||
if monkeys[monkeys["root"].left].valueSet {
|
||||
targetValue = monkeys[monkeys["root"].left].value
|
||||
nextNode = monkeys["root"].right
|
||||
fmt.Println("Root's right is the unknown one", nextNode)
|
||||
} else {
|
||||
targetValue = monkeys[monkeys["root"].right].value
|
||||
nextNode = monkeys["root"].left
|
||||
fmt.Println("Root's left is the unknown one", nextNode)
|
||||
}
|
||||
|
||||
for !monkeys["humn"].valueSet {
|
||||
nextState := monkeys[nextNode]
|
||||
|
||||
if nextState.valueSet {
|
||||
fmt.Println("PANIC: Grounded in a node with the value set")
|
||||
return
|
||||
} else if nextState.operation == OpTarget {
|
||||
nextState.value = targetValue
|
||||
nextState.valueSet = true
|
||||
monkeys[nextNode] = nextState
|
||||
} else if monkeys[nextState.left].valueSet {
|
||||
nextState.value = targetValue
|
||||
nextState.valueSet = true
|
||||
monkeys[nextNode] = nextState
|
||||
switch nextState.operation {
|
||||
case OpAdd:
|
||||
// T = V + X
|
||||
// T - V = X
|
||||
targetValue = targetValue - monkeys[nextState.left].value
|
||||
case OpMul:
|
||||
// T = V * X
|
||||
// T / V = X
|
||||
targetValue = targetValue / monkeys[nextState.left].value
|
||||
case OpSub:
|
||||
// T = V - X
|
||||
// T + X = V
|
||||
// X = V - T
|
||||
targetValue = monkeys[nextState.left].value - targetValue
|
||||
case OpDiv:
|
||||
// T = V / X
|
||||
// TX = V
|
||||
// X = V / T
|
||||
targetValue = monkeys[nextState.left].value / targetValue
|
||||
default:
|
||||
fmt.Println("PANIC: Bad operation in back compute")
|
||||
}
|
||||
nextNode = nextState.right
|
||||
} else if monkeys[nextState.right].valueSet {
|
||||
nextState.value = targetValue
|
||||
nextState.valueSet = true
|
||||
monkeys[nextNode] = nextState
|
||||
switch nextState.operation {
|
||||
case OpAdd:
|
||||
// T = X + V
|
||||
// T - V = X
|
||||
targetValue = targetValue - monkeys[nextState.right].value
|
||||
case OpMul:
|
||||
// T = X * V
|
||||
targetValue = targetValue / monkeys[nextState.right].value
|
||||
case OpSub:
|
||||
// T = X - V
|
||||
// T + V = X
|
||||
targetValue = targetValue + monkeys[nextState.right].value
|
||||
case OpDiv:
|
||||
// T = X / V
|
||||
// TV = X
|
||||
targetValue = targetValue * monkeys[nextState.right].value
|
||||
default:
|
||||
fmt.Println("PANIC: Bad operation in back compute")
|
||||
}
|
||||
nextNode = nextState.left
|
||||
} else {
|
||||
fmt.Println("PANIC: Trouble with a double split in search")
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Println("Actually, my value should be", monkeys["humn"].value)
|
||||
}
|
||||
Reference in New Issue
Block a user