]> fbox.kageds.com Git - adventofcode.git/commitdiff
day11
authorAlan R Evans <alan@kageds.com>
Mon, 27 Nov 2023 14:38:53 +0000 (14:38 +0000)
committerAlan R Evans <alan@kageds.com>
Mon, 27 Nov 2023 14:38:53 +0000 (14:38 +0000)
2022/go/day11/day11.go [new file with mode: 0644]
2022/go/day11/day11_test.go [new file with mode: 0644]
2022/go/day11/input.txt [new file with mode: 0644]
2022/go/main.go

diff --git a/2022/go/day11/day11.go b/2022/go/day11/day11.go
new file mode 100644 (file)
index 0000000..4d24078
--- /dev/null
@@ -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
+}
\ No newline at end of file
diff --git a/2022/go/day11/day11_test.go b/2022/go/day11/day11_test.go
new file mode 100644 (file)
index 0000000..46b8b60
--- /dev/null
@@ -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)
+}
diff --git a/2022/go/day11/input.txt b/2022/go/day11/input.txt
new file mode 100644 (file)
index 0000000..e5e8e6e
--- /dev/null
@@ -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
\ No newline at end of file
index c92f46b96e685163fd45237634d9ffa6b0183f11..0c06107ed2c7c4f35b68314aa05c59d7b2416605 100644 (file)
@@ -18,6 +18,8 @@ import (
        "adventofcode2022/day08"
        "adventofcode2022/day09"
        "adventofcode2022/day10"
        "adventofcode2022/day08"
        "adventofcode2022/day09"
        "adventofcode2022/day10"
+       "adventofcode2022/day11"
+
 
 )
 
 
 )
 
@@ -58,6 +60,9 @@ func main() {
        case 10:
                fmt.Printf("part 1: %d\n", day10.Part1(utils.Readfile(d)))
                fmt.Printf("part 2: %s\n", day10.Part2(utils.Readfile(d)))
        case 10:
                fmt.Printf("part 1: %d\n", day10.Part1(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:
                panic(fmt.Errorf("no such day: %d", d))
        }
        default:
                panic(fmt.Errorf("no such day: %d", d))
        }
@@ -65,7 +70,7 @@ func main() {
 
 // Reads day from os.Args.
 func day() int {
 
 // Reads day from os.Args.
 func day() int {
-       latest := 9
+       latest := 10
        if len(os.Args) == 1 {
                return latest
        }
        if len(os.Args) == 1 {
                return latest
        }