summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Vink <mike1994vink@gmail.com>2022-12-11 20:10:38 +0100
committerMike Vink <mike1994vink@gmail.com>2022-12-11 20:10:38 +0100
commit999c05159c1f67e60e2d287179776d29f070c5da (patch)
treed5e9595fc2921e21fc16ab7f7bb9756907f10b66
parent76e924fa212f275206730337ebaae5059f3a9d21 (diff)
day10 and day11
-rw-r--r--day10.go102
-rw-r--r--day10.txt136
-rw-r--r--day11.go212
-rw-r--r--day11.txt55
4 files changed, 505 insertions, 0 deletions
diff --git a/day10.go b/day10.go
new file mode 100644
index 0000000..e0deaa0
--- /dev/null
+++ b/day10.go
@@ -0,0 +1,102 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "log"
+ "os"
+ "regexp"
+ "strconv"
+)
+
+type cpu struct {
+ register int
+ cycle int
+ signalLog []int
+}
+
+func (c *cpu) instruction(op string, arg []string) {
+ addx := func(arg []string) {
+ x, err := strconv.Atoi(arg[0])
+ if err != nil {
+ log.Fatal("Got invalid arg to addx", err)
+ }
+ c.signalLog = append(c.signalLog, (c.cycle+1)*c.register, (c.cycle+2)*c.register)
+ c.register += x
+ c.cycle += 2
+ }
+ noop := func(arg []string) {
+ c.signalLog = append(c.signalLog, (c.cycle+1)*c.register)
+ c.cycle += 1
+ }
+
+ switch op {
+ case "addx":
+ addx(arg)
+ case "noop":
+ noop(arg)
+ default:
+ log.Fatal("Got unexpected input")
+ }
+}
+
+func NewCpu() *cpu {
+ return &cpu{
+ register: 1,
+ cycle: 0,
+ signalLog: []int(nil),
+ }
+}
+
+func main() {
+ f, err := os.Open("day10.txt")
+ if err != nil {
+ log.Fatal("could open input file", err)
+ }
+
+ // Part 1: Keep a logahead of signals
+ cpu := NewCpu()
+ s := bufio.NewScanner(f)
+ for s.Scan() {
+ r := regexp.MustCompile(`(?P<instruction>\w+) ?(?P<arg>[-0-9 ]+)?`)
+ m := r.FindStringSubmatch(s.Text())
+ switch words := len(m[1:]); words {
+ case 0:
+ log.Fatal("Got unexpected input")
+ case 1:
+ cpu.instruction(m[1], []string(nil))
+ default:
+ cpu.instruction(m[1], m[2:])
+ }
+ }
+
+ runningSum := 0
+ for _, c := range []int{20, 60, 100, 140, 180, 220} {
+ signal := cpu.signalLog[c-1]
+ fmt.Println(fmt.Sprintf("cycle %d:", c), signal)
+ runningSum += signal
+ }
+ fmt.Println("Part 1:", runningSum)
+
+ // Part 2: Scan the signal log
+ spri, te := 0, 2
+ for cycle, signal := range cpu.signalLog {
+ spri, te = (signal/(cycle+1))-1, (signal/(cycle+1))+1
+ c := cycle % 40
+ if spri <= c && c <= te {
+ cpu.signalLog[cycle] = 1
+ } else {
+ cpu.signalLog[cycle] = 0
+ }
+ }
+ for i := 0; i < len(cpu.signalLog); i += 40 {
+ for _, visi := range cpu.signalLog[i : i+40] {
+ if visi == 1 {
+ fmt.Print("#")
+ } else {
+ fmt.Print(".")
+ }
+ }
+ fmt.Println()
+ }
+}
diff --git a/day10.txt b/day10.txt
new file mode 100644
index 0000000..39384f8
--- /dev/null
+++ b/day10.txt
@@ -0,0 +1,136 @@
+noop
+noop
+addx 5
+addx 3
+noop
+addx 14
+addx -12
+noop
+addx 5
+addx 1
+noop
+addx 19
+addx -15
+noop
+noop
+noop
+addx 7
+addx -1
+addx 4
+noop
+noop
+addx 5
+addx 1
+addx -38
+noop
+addx 21
+addx -18
+addx 2
+addx 2
+noop
+addx 3
+addx 5
+addx -6
+addx 11
+noop
+addx 2
+addx 19
+addx -18
+noop
+addx 8
+addx -3
+addx 2
+addx 5
+addx 2
+addx 3
+addx -2
+addx -38
+noop
+addx 3
+addx 4
+addx 5
+noop
+addx -2
+addx 5
+addx -8
+addx 12
+addx 3
+addx -2
+addx 5
+addx 11
+addx -31
+addx 23
+addx 4
+noop
+noop
+addx 5
+addx 3
+addx -2
+addx -37
+addx 1
+addx 5
+addx 2
+addx 12
+addx -10
+addx 3
+addx 4
+addx -2
+noop
+addx 6
+addx 1
+noop
+noop
+noop
+addx -2
+addx 7
+addx 2
+noop
+addx 3
+addx 3
+addx 1
+noop
+addx -37
+addx 2
+addx 5
+addx 2
+addx 32
+addx -31
+addx 5
+addx 2
+addx 9
+addx 9
+addx -15
+noop
+addx 3
+addx 2
+addx 5
+addx 2
+addx 3
+addx -2
+addx 2
+addx 2
+addx -37
+addx 5
+addx -2
+addx 2
+addx 5
+addx 2
+addx 16
+addx -15
+addx 4
+noop
+addx 1
+addx 2
+noop
+addx 3
+addx 5
+addx -1
+addx 5
+noop
+noop
+noop
+noop
+addx 3
+addx 5
+addx -16
+noop
diff --git a/day11.go b/day11.go
new file mode 100644
index 0000000..abcba52
--- /dev/null
+++ b/day11.go
@@ -0,0 +1,212 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "log"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type monkey struct {
+ items []*item
+ operation func(item *item) int
+ test func(item *item) *monkey
+ by int
+ inspections int
+}
+
+func NewMonkey(items []int, by int, op func(i *item) int, test func(i *item) *monkey) *monkey {
+ itemPtrs := make([]*item, len(items))
+ for i, worry := range items {
+ itemPtrs[i] = NewItem(worry)
+ }
+ return &monkey{items: itemPtrs, operation: op, test: test, by: by}
+}
+
+func (m *monkey) throw(receiver *monkey) {
+ throw, leftover := m.items[0], m.items[1:]
+ m.items = leftover
+ receiver.items = append(receiver.items, throw)
+}
+
+type item struct {
+ worry int
+}
+
+func (i *item) operation(m *monkey, r, mod int) {
+ worry := m.operation(i)
+ m.inspections += 1
+ i.worry = (worry / r) % mod
+}
+
+func (i *item) test(m *monkey) *monkey {
+ return m.test(i)
+}
+
+func NewItem(worry int) *item {
+ return &item{
+ worry: worry,
+ }
+}
+
+// Can someone tell me how to do this better? Multiline regex?
+func makeMonkeys(monkeyCount int, f *os.File) []*monkey {
+ startingItemsRegex := regexp.MustCompile(`\s+Starting items: ([0-9 ,]+)`)
+ operationRegex := regexp.MustCompile(`\s+Operation: new = ([0-9A-Za-z]+) ([+\*]{1}) ([0-9A-Za-z]+)`)
+ testRegex := regexp.MustCompile(`\s+Test: divisible by (\d+)`)
+ testConditionRegex := regexp.MustCompile(`\s+If (true|false): throw to monkey (\d+)`)
+
+ monkeys := make([]*monkey, monkeyCount)
+ makeTest := func(by int, mtrue, mfalse int) func(i *item) *monkey {
+ return func(i *item) *monkey {
+ if i.worry%by == 0 {
+ return monkeys[mtrue]
+ } else {
+ return monkeys[mfalse]
+ }
+ }
+ }
+ makeOp := func(a1, comb, a2 string) func(i *item) int {
+ b := []string{a1, a2}
+ var c func(a, b int) int
+ if comb == "+" {
+ c = func(a, b int) int {
+ return a + b
+ }
+ } else if comb == "*" {
+ c = func(a, b int) int {
+ return a * b
+ }
+ }
+ b0, _ := strconv.Atoi(b[0])
+ b1, _ := strconv.Atoi(b[1])
+ return func(i *item) int {
+ switch {
+ case b[0] == "old" && b[1] == "old":
+ return c(i.worry, i.worry)
+ case b[0] == "old":
+ return c(i.worry, b1)
+ case b[1] == "old":
+ return c(b0, i.worry)
+ default:
+ return c(b0, b1)
+ }
+ }
+ }
+
+ f.Seek(0, 0)
+ s := bufio.NewScanner(f)
+ startingItems := []int{}
+ testMap := make(map[string]int)
+ opMap := make(map[string]string)
+ monkeyPtr := 0
+ for {
+ eof := s.Scan()
+
+ if !eof || len(s.Bytes()) == 0 {
+ monkeys[monkeyPtr] = NewMonkey(
+ startingItems,
+ testMap["by"],
+ makeOp(opMap["arg1"], opMap["combination"], opMap["arg2"]),
+ makeTest(testMap["by"], testMap["true"], testMap["false"]),
+ )
+ monkeyPtr += 1
+ testMap = make(map[string]int)
+ opMap = make(map[string]string)
+ if monkeyPtr >= len(monkeys) {
+ break
+ }
+ }
+
+ m := startingItemsRegex.FindStringSubmatch(s.Text())
+ if len(m) == 2 {
+ itemStr := strings.Split(m[1], ", ")
+ startingItems = make([]int, len(itemStr))
+ for i, strItem := range itemStr {
+ v, err := strconv.Atoi(strItem)
+ if err != nil {
+ log.Fatal("Could not get item worry from string", err)
+ }
+ startingItems[i] = v
+ }
+ }
+ m = operationRegex.FindStringSubmatch(s.Text())
+ if len(m) == 4 {
+ opMap["arg1"] = m[1]
+ opMap["combination"] = m[2]
+ opMap["arg2"] = m[3]
+ }
+ m = testRegex.FindStringSubmatch(s.Text())
+ if len(m) == 2 {
+ by, err := strconv.Atoi(m[1])
+ if err != nil {
+ log.Fatal("Could not convert divisible by", err)
+ }
+ testMap["by"] = by
+ }
+ m = testConditionRegex.FindStringSubmatch(s.Text())
+ if len(m) == 3 {
+ to, err := strconv.Atoi(m[2])
+ if err != nil {
+ log.Fatal("Could not convert monkey to throw to", err)
+ }
+ testMap[m[1]] = to
+ }
+ }
+ return monkeys
+}
+
+func monkeyBusiness(monkeys []*monkey, rounds, worryFactor, mod int) int {
+ for round := 0; round < rounds; round++ {
+ for _, m := range monkeys {
+ for len(m.items) > 0 {
+ item := m.items[0]
+ item.operation(m, worryFactor, mod)
+ to := item.test(m)
+ m.throw(to)
+ }
+ }
+ }
+
+ monkey, business := 0, 0
+ for _, m := range monkeys {
+ if m.inspections > monkey {
+ monkey, business = m.inspections, monkey
+ } else if m.inspections > business {
+ monkey, business = monkey, m.inspections
+ }
+ }
+ return monkey * business
+}
+
+func main() {
+ f, err := os.Open("day11.txt")
+ if err != nil {
+ log.Fatal("could open input file", err)
+ }
+
+ monkeyRegex := regexp.MustCompile(`Monkey (\d+)`)
+ monkeyCount := 0
+ s := bufio.NewScanner(f)
+ for s.Scan() {
+ m := monkeyRegex.FindStringSubmatch(s.Text())
+ if len(m) > 0 {
+ monkeyCount += 1
+ }
+ }
+
+ monkeys := makeMonkeys(monkeyCount, f)
+ mod := 1
+ for _, m := range monkeys {
+ mod *= m.by
+ }
+ mb := monkeyBusiness(monkeys, 20, 3, mod)
+ fmt.Println("Part 1:", mb)
+
+ monkeys = makeMonkeys(monkeyCount, f)
+ mb = monkeyBusiness(monkeys, 10_000, 1, mod)
+ fmt.Println("Part 2:", mb)
+}
diff --git a/day11.txt b/day11.txt
new file mode 100644
index 0000000..4a696d9
--- /dev/null
+++ b/day11.txt
@@ -0,0 +1,55 @@
+Monkey 0:
+ Starting items: 91, 66
+ Operation: new = old * 13
+ Test: divisible by 19
+ If true: throw to monkey 6
+ If false: throw to monkey 2
+
+Monkey 1:
+ Starting items: 78, 97, 59
+ Operation: new = old + 7
+ Test: divisible by 5
+ If true: throw to monkey 0
+ If false: throw to monkey 3
+
+Monkey 2:
+ Starting items: 57, 59, 97, 84, 72, 83, 56, 76
+ Operation: new = old + 6
+ Test: divisible by 11
+ If true: throw to monkey 5
+ If false: throw to monkey 7
+
+Monkey 3:
+ Starting items: 81, 78, 70, 58, 84
+ Operation: new = old + 5
+ Test: divisible by 17
+ If true: throw to monkey 6
+ If false: throw to monkey 0
+
+Monkey 4:
+ Starting items: 60
+ Operation: new = old + 8
+ Test: divisible by 7
+ If true: throw to monkey 1
+ If false: throw to monkey 3
+
+Monkey 5:
+ Starting items: 57, 69, 63, 75, 62, 77, 72
+ Operation: new = old * 5
+ Test: divisible by 13
+ If true: throw to monkey 7
+ If false: throw to monkey 4
+
+Monkey 6:
+ Starting items: 73, 66, 86, 79, 98, 87
+ Operation: new = old * old
+ Test: divisible by 3
+ If true: throw to monkey 5
+ If false: throw to monkey 2
+
+Monkey 7:
+ Starting items: 95, 89, 63, 67
+ Operation: new = old + 2
+ Test: divisible by 2
+ If true: throw to monkey 1
+ If false: throw to monkey 4