diff --git a/day21/common/monkey2.go b/day21/common/monkey2.go new file mode 100644 index 0000000..15493a3 --- /dev/null +++ b/day21/common/monkey2.go @@ -0,0 +1,228 @@ +package common + +import ( + "bufio" + "strconv" + "strings" +) + + +type Monkey interface { + Apply() int + Invert(int) int + IsHuman() bool +} + + +type Human struct { + name string + number int +} + +func (monkey *Human) Apply() int { + return monkey.number +} + +func (monkey *Human) Invert(total int) int { + return total +} + +func (monkey *Human) IsHuman() bool { + return true +} + + +type NumberMonkey struct { + name string + number int +} + +func (monkey *NumberMonkey) Apply() int { + return monkey.number +} + +func (monkey *NumberMonkey) Invert(total int) int { + return total - monkey.number +} + +func (monkey *NumberMonkey) IsHuman() bool { + return false +} + + +type PlusMonkey struct { + name string + operand1 Monkey + operand2 Monkey +} + +func (monkey *PlusMonkey) Apply() int { + return monkey.operand1.Apply() + monkey.operand2.Apply() +} + +func (monkey *PlusMonkey) Invert(total int) int { + if monkey.operand1.IsHuman() { + return monkey.operand1.Invert(total - monkey.operand2.Apply()) + } else { + return monkey.operand2.Invert(total - monkey.operand1.Apply()) + } +} + +func (monkey *PlusMonkey) IsHuman() bool { + return monkey.operand1.IsHuman() || monkey.operand2.IsHuman() +} + + +type MinusMonkey struct { + name string + operand1 Monkey + operand2 Monkey +} + +func (monkey *MinusMonkey) Apply() int { + return monkey.operand1.Apply() - monkey.operand2.Apply() +} + +func (monkey *MinusMonkey) Invert(total int) int { + if monkey.operand1.IsHuman() { + return monkey.operand1.Invert(total + monkey.operand2.Apply()) + } else { + return monkey.operand2.Invert(monkey.operand1.Apply() - total) + } +} + +func (monkey *MinusMonkey) IsHuman() bool { + return monkey.operand1.IsHuman() || monkey.operand2.IsHuman() +} + + +type TimesMonkey struct { + name string + operand1 Monkey + operand2 Monkey +} + +func (monkey *TimesMonkey) Apply() int { + return monkey.operand1.Apply() * monkey.operand2.Apply() +} + +func (monkey *TimesMonkey) Invert(total int) int { + if monkey.operand1.IsHuman() { + return monkey.operand1.Invert(total / monkey.operand2.Apply()) + } else { + return monkey.operand2.Invert(total / monkey.operand1.Apply()) + } +} + +func (monkey *TimesMonkey) IsHuman() bool { + return monkey.operand1.IsHuman() || monkey.operand2.IsHuman() +} + + +type DivisionMonkey struct { + name string + operand1 Monkey + operand2 Monkey +} + +func (monkey *DivisionMonkey) Apply() int { + return monkey.operand1.Apply() / monkey.operand2.Apply() +} + +func (monkey *DivisionMonkey) Invert(total int) int { + if monkey.operand1.IsHuman() { + return monkey.operand1.Invert(total * monkey.operand2.Apply()) + } else { + return monkey.operand2.Invert(monkey.operand1.Apply() / total) + } +} + +func (monkey *DivisionMonkey) IsHuman() bool { + return monkey.operand1.IsHuman() || monkey.operand2.IsHuman() +} + + +type EqualityMonkey struct { + name string + operand1 Monkey + operand2 Monkey +} + +func (monkey *EqualityMonkey) Apply() int { + if monkey.operand1.Apply() == monkey.operand2.Apply() { + return 1 + } else { + return 0 + } +} + +func (monkey *EqualityMonkey) Invert(total int) int { + if monkey.operand1.IsHuman() { + return monkey.operand1.Invert(monkey.operand2.Apply() - total) + } else { + return monkey.operand2.Invert(monkey.operand1.Apply() - total) + } +} + +func (monkey *EqualityMonkey) IsHuman() bool { + return monkey.operand1.IsHuman() || monkey.operand2.IsHuman() +} + + +type StringCouple struct { + left string + right string +} + + +type UnresolvedMonkey struct { + name string + symbol string +} + + +func Parse(scanner bufio.Scanner, rootIsEquality bool) Monkey { + unresolvedMonkeys := make(map[StringCouple]UnresolvedMonkey) + resolvedMonkeys := make(map[string]Monkey) + + for scanner.Scan() { + line := scanner.Text() + splittedLine := strings.Split(line, " ") + if len(splittedLine) == 2 { + number, _ := strconv.Atoi(splittedLine[1]) + if splittedLine[0][:4] == "humn" { + resolvedMonkeys[splittedLine[0][:4]] = &Human{splittedLine[0][:4], number} + } else { + resolvedMonkeys[splittedLine[0][:4]] = &NumberMonkey{splittedLine[0][:4], number} + } + } else { + unresolvedMonkeys[StringCouple{splittedLine[1], splittedLine[3]}] = UnresolvedMonkey{splittedLine[0][:4], splittedLine[2]} + } + } + + for len(unresolvedMonkeys) > 0 { + for monkeyCouple := range(unresolvedMonkeys) { + monkey1, ok1 := resolvedMonkeys[monkeyCouple.left] + monkey2, ok2 := resolvedMonkeys[monkeyCouple.right] + if ok1 && ok2 { + if rootIsEquality && unresolvedMonkeys[monkeyCouple].name == "root" { + resolvedMonkeys[unresolvedMonkeys[monkeyCouple].name] = &EqualityMonkey{unresolvedMonkeys[monkeyCouple].name, monkey1, monkey2} + } else { + switch unresolvedMonkeys[monkeyCouple].symbol { + case "+": + resolvedMonkeys[unresolvedMonkeys[monkeyCouple].name] = &PlusMonkey{unresolvedMonkeys[monkeyCouple].name, monkey1, monkey2} + case "-": + resolvedMonkeys[unresolvedMonkeys[monkeyCouple].name] = &MinusMonkey{unresolvedMonkeys[monkeyCouple].name, monkey1, monkey2} + case "*": + resolvedMonkeys[unresolvedMonkeys[monkeyCouple].name] = &TimesMonkey{unresolvedMonkeys[monkeyCouple].name, monkey1, monkey2} + case "/": + resolvedMonkeys[unresolvedMonkeys[monkeyCouple].name] = &DivisionMonkey{unresolvedMonkeys[monkeyCouple].name, monkey1, monkey2} + } + } + delete(unresolvedMonkeys, monkeyCouple) + } + } + } + + return resolvedMonkeys["root"] +} diff --git a/day21/ex1/main.go b/day21/ex1/main.go new file mode 100644 index 0000000..ffc68a7 --- /dev/null +++ b/day21/ex1/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "aoc2022/day21/common" + "bufio" + "fmt" + "os" +) + +func main() { + rootMonkey := common.Parse(*bufio.NewScanner(os.Stdin), false) + + fmt.Println(rootMonkey.Apply()) +} diff --git a/day21/ex2/main.go b/day21/ex2/main.go new file mode 100644 index 0000000..ca4eb72 --- /dev/null +++ b/day21/ex2/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "aoc2022/day21/common" + "bufio" + "fmt" + "os" +) + +func main() { + rootMonkey := common.Parse(*bufio.NewScanner(os.Stdin), true) + + fmt.Println(rootMonkey.Invert(0)) +}