From ec27a5ec6cb5f3df06826015b7d932cacbf1bb17 Mon Sep 17 00:00:00 2001 From: Parnic Date: Thu, 30 Jun 2022 08:03:18 -0500 Subject: [PATCH] Day 16 solution Following the formula for part 1 was straightforward enough, but finding the pattern for part 2 and deducing the shortcut formula took me a while. That first 0 1 propagate enough that by the time we get halfway through applying the formula, it's all 0s and 1s, so sort of like an addition with a mask on what numbers we're adding. Also, fun fact: changing the numberSet from an array of ints (my initial implementation) to an array of int8's (what's here now) reduced the memory footprint of the application substantially (from something like 50mb to closer to 8). --- days/16.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ inputs/16p.txt | 1 + inputs/16s1.txt | 1 + inputs/16s2.txt | 1 + inputs/16s3.txt | 1 + inputs/16s4.txt | 1 + main.go | 1 + 7 files changed, 110 insertions(+) create mode 100644 days/16.go create mode 100644 inputs/16p.txt create mode 100644 inputs/16s1.txt create mode 100644 inputs/16s2.txt create mode 100644 inputs/16s3.txt create mode 100644 inputs/16s4.txt diff --git a/days/16.go b/days/16.go new file mode 100644 index 0000000..cf8ce52 --- /dev/null +++ b/days/16.go @@ -0,0 +1,104 @@ +package days + +import ( + "fmt" + "math" + + u "parnic.com/aoc2019/utilities" +) + +type Day16 struct { + numberSet []int8 +} + +func (d *Day16) Parse() { + numberSequence := u.GetStringContents("16p") + d.numberSet = make([]int8, len(numberSequence)) + for i, numRune := range numberSequence { + d.numberSet[i] = int8(numRune - '0') + } +} + +func (d Day16) Num() int { + return 16 +} + +func (d *Day16) Part1() string { + transformed := make([]int8, len(d.numberSet)) + copy(transformed, d.numberSet) + + transformPattern := []int8{0, 1, 0, -1} + + phases := 100 + workingSet := make([]int8, len(transformed)) + for i := 0; i < phases; i++ { + copy(workingSet, transformed) + + // fmt.Printf("Phase %d. Input signal: %v\n", (i + 1), transformed) + for destIdx := range transformed { + repeated := 0 + patternIdx := 0 + workingVal := int64(0) + for idx := range transformed { + if repeated >= destIdx { + repeated = 0 + patternIdx++ + if patternIdx == len(transformPattern) { + patternIdx = 0 + } + } else { + repeated++ + } + + // fmt.Printf("%d*%d", transformed[idx], transformPattern[patternIdx]) + // if idx < len(transformed)-1 { + // fmt.Print(" + ") + // } + workingVal += int64(transformed[idx] * transformPattern[patternIdx]) + } + + workingSet[destIdx] = int8(int64(math.Abs(float64(workingVal))) % 10) + // fmt.Printf(" = %d\n", workingSet[destIdx]) + } + + copy(transformed, workingSet) + } + + finalVal := 0 + for i := range transformed[0:8] { + finalVal += int(transformed[i]) * int(math.Pow10(8-1-i)) + } + return fmt.Sprintf("First 8 digits of the final output list: %s%d%s", u.TextBold, finalVal, u.TextReset) +} + +func (d *Day16) Part2() string { + transformed := make([]int8, len(d.numberSet)*10000) + for i := 0; i < 10000; i++ { + copy(transformed[i*len(d.numberSet):(i*len(d.numberSet))+len(d.numberSet)], d.numberSet) + } + + finalMsgOffset := 0 + for i := 0; i < 7; i++ { + finalMsgOffset += int(d.numberSet[i]) * int(math.Pow10(7-1-i)) + } + + if finalMsgOffset < len(transformed)/2 { + panic("offset must be in the back half of the message for this solution to work") + } + + phases := 100 + for p := 0; p < phases; p++ { + rollingTotal := int8(0) + for i := len(transformed) - 1; i >= finalMsgOffset; i-- { + rollingTotal += transformed[i] + rollingTotal = rollingTotal % 10 + transformed[i] = rollingTotal + } + } + + finalVal := 0 + for i := range transformed[finalMsgOffset : finalMsgOffset+8] { + finalVal += int(transformed[finalMsgOffset+i]) * int(math.Pow10(8-1-i)) + } + return fmt.Sprintf("Embedded message in the final output list: %s%d%s", u.TextBold, finalVal, u.TextReset) +} diff --git a/inputs/16p.txt b/inputs/16p.txt new file mode 100644 index 0000000..d1962d3 --- /dev/null +++ b/inputs/16p.txt @@ -0,0 +1 @@ +59791875142707344554745984624833270124746225787022156176259864082972613206097260696475359886661459314067969858521185244807128606896674972341093111690401527976891268108040443281821862422244152800144859031661510297789792278726877676645835805097902853584093615895099152578276185267316851163313487136731134073054989870018294373731775466754420075119913101001966739563592696702233028356328979384389178001923889641041703308599918672055860556825287836987992883550004999016194930620165247185883506733712391462975446192414198344745434022955974228926237100271949068464343172968939069550036969073411905889066207300644632441054836725463178144030305115977951503567 \ No newline at end of file diff --git a/inputs/16s1.txt b/inputs/16s1.txt new file mode 100644 index 0000000..e9a9ea1 --- /dev/null +++ b/inputs/16s1.txt @@ -0,0 +1 @@ +12345678 \ No newline at end of file diff --git a/inputs/16s2.txt b/inputs/16s2.txt new file mode 100644 index 0000000..1a27961 --- /dev/null +++ b/inputs/16s2.txt @@ -0,0 +1 @@ +80871224585914546619083218645595 \ No newline at end of file diff --git a/inputs/16s3.txt b/inputs/16s3.txt new file mode 100644 index 0000000..f1e15dd --- /dev/null +++ b/inputs/16s3.txt @@ -0,0 +1 @@ +19617804207202209144916044189917 \ No newline at end of file diff --git a/inputs/16s4.txt b/inputs/16s4.txt new file mode 100644 index 0000000..7f52157 --- /dev/null +++ b/inputs/16s4.txt @@ -0,0 +1 @@ +69317163492948606335995924319873 \ No newline at end of file diff --git a/main.go b/main.go index 0be53fe..7820b04 100644 --- a/main.go +++ b/main.go @@ -46,6 +46,7 @@ var dayMap = []day{ &days.Day13{}, &days.Day14{}, &days.Day15{}, + &days.Day16{}, } func main() {