day11
This commit is contained in:
148
2022/go/day11/day11.go
Normal file
148
2022/go/day11/day11.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package day11
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "fmt"
|
||||||
|
"strings"
|
||||||
|
"sort"
|
||||||
|
"adventofcode2022/utils"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
type op int
|
||||||
|
|
||||||
|
const (
|
||||||
|
addition op = iota + 1
|
||||||
|
multiply
|
||||||
|
square
|
||||||
|
)
|
||||||
|
|
||||||
|
type monkey struct {
|
||||||
|
items []*big.Int
|
||||||
|
operation op
|
||||||
|
opArg *big.Int
|
||||||
|
test *big.Int
|
||||||
|
ifTrue int
|
||||||
|
ifFalse int
|
||||||
|
inspected int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Part1(input string) int {
|
||||||
|
|
||||||
|
monkeys := parseInput(input)
|
||||||
|
var level = big.NewInt(0)
|
||||||
|
for round := 0; round < 20; round++ {
|
||||||
|
for i, monkey := range monkeys {
|
||||||
|
for _, item := range monkey.items {
|
||||||
|
monkeys[i].inspected++
|
||||||
|
switch monkey.operation {
|
||||||
|
case addition:
|
||||||
|
level = new(big.Int).Add(item, monkey.opArg)
|
||||||
|
case multiply:
|
||||||
|
level = new(big.Int).Mul(item, monkey.opArg)
|
||||||
|
case square:
|
||||||
|
level = new(big.Int).Mul(item, item)
|
||||||
|
}
|
||||||
|
level = new(big.Int).Div(level, big.NewInt(3))
|
||||||
|
t := &big.Int{}
|
||||||
|
t.Mod(level, monkey.test)
|
||||||
|
if t.Sign() == 0 {
|
||||||
|
monkeys[monkey.ifTrue].items = append(monkeys[monkey.ifTrue].items, level)
|
||||||
|
} else {
|
||||||
|
monkeys[monkey.ifFalse].items = append(monkeys[monkey.ifFalse].items, level)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
monkeys[i].items = monkeys[i].items[:0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Slice(monkeys, func(i, j int) bool {
|
||||||
|
return monkeys[i].inspected > monkeys[j].inspected
|
||||||
|
})
|
||||||
|
|
||||||
|
return monkeys[0].inspected * monkeys[1].inspected
|
||||||
|
}
|
||||||
|
|
||||||
|
func Part2(input string) int {
|
||||||
|
monkeys := parseInput(input)
|
||||||
|
var level = big.NewInt(0)
|
||||||
|
commonDivisor := big.NewInt(3 * 13 * 19 * 17 * 5 * 7 * 11 * 2)
|
||||||
|
for round := 0; round < 10000; round++ {
|
||||||
|
for i, monkey := range monkeys {
|
||||||
|
for _, item := range monkey.items {
|
||||||
|
monkeys[i].inspected++
|
||||||
|
switch monkey.operation {
|
||||||
|
case addition:
|
||||||
|
level = new(big.Int).Add(item, monkey.opArg)
|
||||||
|
case multiply:
|
||||||
|
level = new(big.Int).Mul(item, monkey.opArg)
|
||||||
|
case square:
|
||||||
|
level = new(big.Int).Mul(item, item)
|
||||||
|
}
|
||||||
|
level = level.Mod(level, commonDivisor)
|
||||||
|
t := &big.Int{}
|
||||||
|
t.Mod(level, monkey.test)
|
||||||
|
if t.Sign() == 0 {
|
||||||
|
monkeys[monkey.ifTrue].items = append(monkeys[monkey.ifTrue].items, level)
|
||||||
|
} else {
|
||||||
|
monkeys[monkey.ifFalse].items = append(monkeys[monkey.ifFalse].items, level)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
monkeys[i].items = monkeys[i].items[:0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Slice(monkeys, func(i, j int) bool {
|
||||||
|
return monkeys[i].inspected > monkeys[j].inspected
|
||||||
|
})
|
||||||
|
|
||||||
|
return monkeys[0].inspected * monkeys[1].inspected
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInput(input string) []monkey {
|
||||||
|
monkeys := []monkey{}
|
||||||
|
|
||||||
|
for i, monkeyString := range strings.Split(input, "\n\n") {
|
||||||
|
for _, line := range strings.Split(monkeyString, "\n") {
|
||||||
|
if strings.HasPrefix(line, "Monkey") {
|
||||||
|
monkeys = append(monkeys, monkey{})
|
||||||
|
} else if strings.HasPrefix(line, " Starting items: ") {
|
||||||
|
s := strings.TrimPrefix(line, " Starting items: ")
|
||||||
|
for _, piece := range strings.Split(s, ", ") {
|
||||||
|
t := utils.MustAtoi(piece)
|
||||||
|
monkeys[i].items = append(monkeys[i].items, big.NewInt(int64(t)))
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(line, " Operation: new = ") {
|
||||||
|
s := strings.TrimPrefix(line, " Operation: new = ")
|
||||||
|
if strings.HasPrefix(s, "old + ") {
|
||||||
|
s2 := strings.TrimPrefix(s, "old + ")
|
||||||
|
monkeys[i].operation = addition
|
||||||
|
t := utils.MustAtoi(s2)
|
||||||
|
monkeys[i].opArg = big.NewInt(int64(t))
|
||||||
|
} else if s == "old * old" {
|
||||||
|
monkeys[i].operation = square
|
||||||
|
} else if strings.HasPrefix(s, "old * ") {
|
||||||
|
s2 := strings.TrimPrefix(s, "old * ")
|
||||||
|
monkeys[i].operation = multiply
|
||||||
|
t := utils.MustAtoi(s2)
|
||||||
|
monkeys[i].opArg = big.NewInt(int64(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if strings.HasPrefix(line, " Test: divisible by ") {
|
||||||
|
s := strings.TrimPrefix(line, " Test: divisible by ")
|
||||||
|
t := utils.MustAtoi(s)
|
||||||
|
monkeys[i].test = big.NewInt(int64(t))
|
||||||
|
} else if strings.HasPrefix(line, " If true: throw to monkey ") {
|
||||||
|
s := strings.TrimPrefix(line, " If true: throw to monkey ")
|
||||||
|
monkeys[i].ifTrue = utils.MustAtoi(s)
|
||||||
|
} else if strings.HasPrefix(line, " If false: throw to monkey ") {
|
||||||
|
s := strings.TrimPrefix(line, " If false: throw to monkey ")
|
||||||
|
monkeys[i].ifFalse = utils.MustAtoi(s)
|
||||||
|
} else if line == "" {
|
||||||
|
// do nothing
|
||||||
|
} else {
|
||||||
|
panic("unknown input")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return monkeys
|
||||||
|
}
|
||||||
45
2022/go/day11/day11_test.go
Normal file
45
2022/go/day11/day11_test.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package day11
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPart1(t *testing.T) {
|
||||||
|
r := Part1(
|
||||||
|
`Monkey 0:
|
||||||
|
Starting items: 79, 98
|
||||||
|
Operation: new = old * 19
|
||||||
|
Test: divisible by 23
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 54, 65, 75, 74
|
||||||
|
Operation: new = old + 6
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 79, 60, 97
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 74
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 0
|
||||||
|
If false: throw to monkey 1
|
||||||
|
`)
|
||||||
|
require.Equal(t, 10605, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPart2(t *testing.T) {
|
||||||
|
r := Part2("")
|
||||||
|
require.Equal(t, 0, r)
|
||||||
|
}
|
||||||
55
2022/go/day11/input.txt
Normal file
55
2022/go/day11/input.txt
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
Monkey 0:
|
||||||
|
Starting items: 54, 98, 50, 94, 69, 62, 53, 85
|
||||||
|
Operation: new = old * 13
|
||||||
|
Test: divisible by 3
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 1
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 71, 55, 82
|
||||||
|
Operation: new = old + 2
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 7
|
||||||
|
If false: throw to monkey 2
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 77, 73, 86, 72, 87
|
||||||
|
Operation: new = old + 8
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 4
|
||||||
|
If false: throw to monkey 7
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 97, 91
|
||||||
|
Operation: new = old + 1
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 6
|
||||||
|
If false: throw to monkey 5
|
||||||
|
|
||||||
|
Monkey 4:
|
||||||
|
Starting items: 78, 97, 51, 85, 66, 63, 62
|
||||||
|
Operation: new = old * 17
|
||||||
|
Test: divisible by 5
|
||||||
|
If true: throw to monkey 6
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 5:
|
||||||
|
Starting items: 88
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 7
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 6:
|
||||||
|
Starting items: 87, 57, 63, 86, 87, 53
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 11
|
||||||
|
If true: throw to monkey 5
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 7:
|
||||||
|
Starting items: 73, 59, 82, 65
|
||||||
|
Operation: new = old + 6
|
||||||
|
Test: divisible by 2
|
||||||
|
If true: throw to monkey 4
|
||||||
|
If false: throw to monkey 3
|
||||||
@@ -18,6 +18,8 @@ import (
|
|||||||
"adventofcode2022/day08"
|
"adventofcode2022/day08"
|
||||||
"adventofcode2022/day09"
|
"adventofcode2022/day09"
|
||||||
"adventofcode2022/day10"
|
"adventofcode2022/day10"
|
||||||
|
"adventofcode2022/day11"
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,6 +60,9 @@ func main() {
|
|||||||
case 10:
|
case 10:
|
||||||
fmt.Printf("part 1: %d\n", day10.Part1(utils.Readfile(d)))
|
fmt.Printf("part 1: %d\n", day10.Part1(utils.Readfile(d)))
|
||||||
fmt.Printf("part 2: %s\n", day10.Part2(utils.Readfile(d)))
|
fmt.Printf("part 2: %s\n", day10.Part2(utils.Readfile(d)))
|
||||||
|
case 11:
|
||||||
|
fmt.Printf("part 1: %d\n", day11.Part1(utils.Readfile(d)))
|
||||||
|
fmt.Printf("part 2: %d\n", day11.Part2(utils.Readfile(d)))
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("no such day: %d", d))
|
panic(fmt.Errorf("no such day: %d", d))
|
||||||
}
|
}
|
||||||
@@ -65,7 +70,7 @@ func main() {
|
|||||||
|
|
||||||
// Reads day from os.Args.
|
// Reads day from os.Args.
|
||||||
func day() int {
|
func day() int {
|
||||||
latest := 9
|
latest := 10
|
||||||
if len(os.Args) == 1 {
|
if len(os.Args) == 1 {
|
||||||
return latest
|
return latest
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user