mirror of
https://github.com/RussellChamp/advent-of-code-2021.git
synced 2026-10-27 21:52:32 +00:00
day 14 and 15
This commit is contained in:
1 parent
6e22bbe567
commit
4737afa383
12 files changed
+678
-3
No files matched your search
Executable
BIN
Binary file not shown.
+165
@@ -0,0 +1,165 @@
|
||||
/* Day 14: Extended Polymerization */
|
||||
package main
|
||||
|
||||
import (
|
||||
"AoC2021/utils/args"
|
||||
"AoC2021/utils/log"
|
||||
"AoC2021/utils/timer"
|
||||
"bufio"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
argMap := args.Parse(os.Args)
|
||||
setLogLevel(argMap)
|
||||
selectedPart, partSpecified := argMap["part"]
|
||||
|
||||
log.Println(log.NORMAL, "--- Day 14: Extended Polymerization ---")
|
||||
timer.Start()
|
||||
if !partSpecified || selectedPart == "1" {
|
||||
part1()
|
||||
timer.TickAtLevel(log.NORMAL)
|
||||
log.Println(log.NORMAL)
|
||||
}
|
||||
|
||||
if !partSpecified || selectedPart == "2" {
|
||||
part2()
|
||||
timer.TickAtLevel(log.NORMAL)
|
||||
log.Println(log.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
func part1() {
|
||||
log.Println(log.NORMAL, "* Part 1 *")
|
||||
log.Println(log.NORMAL, " Goal: Apply 10 steps of pair insertion to the polymer template and find the most and least common elements in the result.")
|
||||
log.Println(log.NORMAL, " Answer: What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?")
|
||||
|
||||
doTheThing(10)
|
||||
}
|
||||
|
||||
func part2() {
|
||||
log.Println(log.NORMAL, "* Part 2 *")
|
||||
log.Println(log.NORMAL, " Goal: Apply 40 steps of pair insertion to the polymer template and find the most and least common elements in the result.")
|
||||
log.Println(log.NORMAL, " Answer: What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?")
|
||||
|
||||
doTheThing(40)
|
||||
}
|
||||
|
||||
func doTheThing(totalSteps int) {
|
||||
|
||||
template, pairs := readInput()
|
||||
log.Println(log.DIAGNOSTIC, template, pairs)
|
||||
|
||||
// perform the loop 'totalSteps' times
|
||||
for step := 0; step < totalSteps; step++ {
|
||||
// starting from the front of the template, check two-letter pairs
|
||||
for tIdx := 0; tIdx < len(template)-1; tIdx++ {
|
||||
// the lookup key will be the next two letters in the template
|
||||
key := template[tIdx : tIdx+2]
|
||||
// if we find a match in the pairs map
|
||||
value, found := pairs[key]
|
||||
if found {
|
||||
// insert the new character between the original two letters
|
||||
template = template[:tIdx+1] + value + template[tIdx+1:]
|
||||
// increment the idx counter once more so that we skip over the character that we just inserted
|
||||
tIdx++
|
||||
}
|
||||
}
|
||||
log.Printf(log.DEBUG, "After step #%d template is length %d\n", step+1, len(template))
|
||||
timer.TickAtLevel(log.DEBUG)
|
||||
}
|
||||
|
||||
// COUNT all character occurances
|
||||
countMap := make(map[byte]int)
|
||||
|
||||
for idx := 0; idx < len(template); idx++ {
|
||||
countMap[template[idx]]++
|
||||
}
|
||||
log.Println(log.DIAGNOSTIC, "CountMap:", countMap)
|
||||
|
||||
mostCommonLetter, mostCommonCount := getMostCommon(countMap)
|
||||
leastCommonLetter, leastCommonCount := getLeastCommon(countMap)
|
||||
|
||||
log.Printf(log.NORMAL, "After %d steps, the most common (%s=%d) minus the least common (%s=%d) is %d\n", totalSteps, mostCommonLetter, mostCommonCount, leastCommonLetter, leastCommonCount, mostCommonCount-leastCommonCount)
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
log.Println(log.DEBUG, "Oh snap!")
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func setLogLevel(argMap map[string]string) {
|
||||
logLevelStr, found := argMap["log"]
|
||||
if found {
|
||||
logLevel, err := strconv.Atoi(logLevelStr)
|
||||
check(err)
|
||||
log.SetLogLevel(logLevel)
|
||||
}
|
||||
}
|
||||
|
||||
func readInput() (string, map[string]string) {
|
||||
input, err := os.Open("./input.txt")
|
||||
check(err)
|
||||
defer input.Close()
|
||||
|
||||
scanner := bufio.NewScanner(input)
|
||||
lines := 0
|
||||
|
||||
// TEMPLATE LINE
|
||||
if !scanner.Scan() {
|
||||
panic("Error parsing input template")
|
||||
}
|
||||
template := scanner.Text()
|
||||
lines++
|
||||
|
||||
// NEW LINE
|
||||
if !scanner.Scan() {
|
||||
panic("Error parsing input newline")
|
||||
}
|
||||
_ = scanner.Text()
|
||||
lines++
|
||||
|
||||
// PAIRS
|
||||
pairs := make(map[string]string)
|
||||
for scanner.Scan() {
|
||||
pair := strings.Split(scanner.Text(), " -> ")
|
||||
if len(pair) != 2 {
|
||||
panic("Error parsing input pairs")
|
||||
}
|
||||
pairs[pair[0]] = pair[1]
|
||||
lines++
|
||||
}
|
||||
|
||||
log.Printf(log.NORMAL, "Read %d pairs from %d lines in input\n", len(pairs), lines)
|
||||
|
||||
return template, pairs
|
||||
}
|
||||
|
||||
func getMostCommon(countMap map[byte]int) (string, int) {
|
||||
mostCommonStr := ""
|
||||
mostCommonCount := -math.MaxInt
|
||||
for key, value := range countMap {
|
||||
if value > mostCommonCount {
|
||||
mostCommonStr, mostCommonCount = string(key), value
|
||||
}
|
||||
}
|
||||
|
||||
return mostCommonStr, mostCommonCount
|
||||
}
|
||||
|
||||
func getLeastCommon(countMap map[byte]int) (string, int) {
|
||||
leastCommonStr := ""
|
||||
leastCommonCount := math.MaxInt
|
||||
for key, value := range countMap {
|
||||
if value < leastCommonCount {
|
||||
leastCommonStr, leastCommonCount = string(key), value
|
||||
}
|
||||
}
|
||||
|
||||
return leastCommonStr, leastCommonCount
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"AoC2021/utils/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDay14(t *testing.T) {
|
||||
assert.IsTrue(t, true, "cool")
|
||||
assert.EqualsStr(t, "foo", "bar", "baz")
|
||||
}
|
||||
Reference in new issue
Block a user