Day 14 solution

This commit is contained in:
2021-12-14 15:41:16 +00:00
parent 000e241684
commit 6b21ea4aff
7 changed files with 374 additions and 0 deletions

View File

@@ -144,3 +144,12 @@ There are 837 dots after 1 fold
#### # #### ### # # ## # # ##
This is the activation code
```
### Day fourteen
```sh
$ ./aoc2021 --fourteen
The solution for "fourteen" is:
The result of subtracting the least from most common element quantities is 2988
The result of subtracting the least from most common element quantities is 3572761917024
```

102
fourteen/input.txt Normal file
View File

@@ -0,0 +1,102 @@
VFHKKOKKCPBONFHNPHPN
VS -> B
HK -> B
FO -> P
NC -> F
VN -> C
BS -> O
HS -> K
NS -> C
CV -> P
NV -> C
PH -> H
PB -> B
PK -> K
HF -> P
FV -> C
NN -> H
VO -> K
VP -> P
BC -> B
KK -> S
OK -> C
PN -> H
SB -> V
KO -> P
KH -> C
KS -> S
FP -> B
PV -> B
BO -> C
OS -> H
NB -> S
SP -> C
HN -> N
FN -> B
PO -> O
FS -> O
NH -> B
SO -> P
OB -> S
KC -> C
OO -> H
BB -> V
SC -> F
NP -> P
SH -> C
BH -> O
BP -> F
CC -> S
BN -> H
SS -> P
BF -> B
VK -> P
OV -> H
FC -> S
VB -> S
PF -> N
HH -> O
HC -> V
CH -> B
HP -> H
FF -> H
VF -> V
CS -> F
KP -> F
OP -> H
KF -> F
PP -> V
OC -> C
PS -> F
ON -> H
BK -> B
HV -> S
CO -> K
FH -> C
FB -> F
OF -> V
SN -> S
PC -> K
NF -> F
NK -> P
NO -> P
CP -> P
CK -> S
HB -> H
BV -> C
SF -> K
HO -> H
OH -> B
KV -> S
KN -> F
SK -> K
VH -> S
CN -> S
VC -> P
CB -> H
SV -> S
VV -> P
CF -> F
FK -> F
KB -> V

24
fourteen/main.go Normal file
View File

@@ -0,0 +1,24 @@
package fourteen
import "fmt"
type Fourteen struct {
polymer polymer
}
func Init(filepath string) *Fourteen {
fourteen := &Fourteen{
polymer: polymer{},
}
fourteen.polymer.load(filepath)
return fourteen
}
func (d *Fourteen) Answer() string {
return fmt.Sprintf("The result of subtracting the least from most common element quantities is %d", d.polymer.elementCount(10))
}
func (d *Fourteen) FollowUp() string {
return fmt.Sprintf("The result of subtracting the least from most common element quantities is %d", d.polymer.elementCountMap(40))
}

146
fourteen/polymer.go Normal file
View File

@@ -0,0 +1,146 @@
package fourteen
import (
"bufio"
"fmt"
"os"
)
type polymer struct {
template string
rules map[string]string
}
func (p *polymer) load(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
p.rules = map[string]string{}
scannedTemplate := false
for scanner.Scan() {
if !scannedTemplate {
p.template = scanner.Text()
scannedTemplate = true
continue
}
if scanner.Text() == "" {
continue
}
var pair, insert string
if count, err := fmt.Sscanf(scanner.Text(), "%s -> %s", &pair, &insert); count != 2 || err != nil {
return fmt.Errorf("expected to scan 2 values from %q, found %d: %w", scanner.Text(), count, err)
}
p.rules[pair] = insert
}
return nil
}
func (p *polymer) elementCount(size int) int {
result := p.step(size)
elemCounts := map[rune]int{}
for _, r := range result {
elemCounts[r]++
}
min := len(result)
max := 0
for _, v := range elemCounts {
if v < min {
min = v
}
if v > max {
max = v
}
}
return max - min
}
func (p *polymer) elementCountMap(size int) int {
_, counts := p.stepMap(size)
min := -1
max := -1
for _, v := range counts {
if v < min || min == -1 {
min = v
}
if v > max {
max = v
}
}
return max - min
}
func (p *polymer) stepMap(steps int) (map[string]int, map[string]int) {
pairs := map[string]int{}
counts := map[string]int{}
// Build initial pairs and counts from template
for i := 0; i < len(p.template)-1; i++ {
// Count first element from pair
counts[string(p.template[i])]++
pairs[fmt.Sprintf("%c%c", p.template[i], p.template[i+1])]++
// If this is the last pair add the second element
if i == len(p.template)-2 {
counts[string(p.template[i+1])]++
}
}
for i := 0; i < steps; i++ {
pairs, counts = p.stepMapOne(pairs, counts)
}
return pairs, counts
}
func (p *polymer) stepMapOne(pairs map[string]int, counts map[string]int) (map[string]int, map[string]int) {
newPairs := map[string]int{}
for k, v := range pairs {
result := p.rules[k]
counts[result] += (1 * v)
pair1 := fmt.Sprintf("%c%s", k[0], result)
pair2 := fmt.Sprintf("%s%c", result, k[1])
newPairs[pair1] += 1 * v
newPairs[pair2] += 1 * v
}
return newPairs, counts
}
func (p *polymer) step(steps int) string {
seed := p.template
for i := 0; i < steps; i++ {
seed = p.stepOne(seed)
}
return seed
}
func (p *polymer) stepOne(from string) string {
result := ""
for i := 0; i < len(from)-1; i++ {
// Add first element from pair
result += string(from[i])
// Lookup and add element result from pair
pair := fmt.Sprintf("%c%c", from[i], from[i+1])
result += p.rules[pair]
// If this is the last pair add the second element
if i == len(from)-2 {
result += string(from[i+1])
}
}
return result
}

72
fourteen/polymer_test.go Normal file
View File

@@ -0,0 +1,72 @@
package fourteen
import "testing"
func Test_read(t *testing.T) {
p := polymer{}
if err := p.load("test_input.txt"); err != nil {
t.Log(err)
t.FailNow()
}
if p.template != "NNCB" {
t.Logf("Expected template of NNCB, found %s", p.template)
t.Fail()
}
if len(p.rules) != 16 {
t.Logf("Expected 16 rules, found %d", len(p.rules))
t.Fail()
}
}
func Test_step(t *testing.T) {
p := polymer{}
p.load("test_input.txt")
if result := p.step(1); result != "NCNBCHB" {
t.Logf("Expected NCNBCHB, found %s", result)
t.Fail()
}
if result := p.step(2); result != "NBCCNBBBCBHCB" {
t.Logf("Expected NBCCNBBBCBHCB, found %s", result)
t.Fail()
}
if result := p.step(3); result != "NBBBCNCCNBBNBNBBCHBHHBCHB" {
t.Logf("Expected NBBBCNCCNBBNBNBBCHBHHBCHB, found %s", result)
t.Fail()
}
if result := p.step(4); result != "NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB" {
t.Logf("Expected NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB, found %s", result)
t.Fail()
}
}
func Test_elemCount(t *testing.T) {
p := polymer{}
p.load("test_input.txt")
if result := p.elementCount(10); result != 1588 {
t.Logf("Expected a result of 1588, got %d", result)
t.Fail()
}
}
func Test_elemMapCount(t *testing.T) {
p := polymer{}
p.load("test_input.txt")
if result := p.elementCountMap(10); result != 1588 {
t.Logf("Expected a result of 1588, got %d", result)
t.Fail()
}
if result := p.elementCountMap(40); result != 2188189693529 {
t.Logf("Expected a result of 2188189693529, got %d", result)
t.Fail()
}
}

18
fourteen/test_input.txt Normal file
View File

@@ -0,0 +1,18 @@
NNCB
CH -> B
HH -> N
CB -> H
NH -> C
HB -> C
HC -> B
HN -> C
NN -> C
BH -> H
NC -> B
NB -> B
BN -> B
BB -> N
BC -> B
CC -> N
CN -> C

View File

@@ -9,6 +9,7 @@ import (
"unsupervised.ca/aoc2021/eleven"
"unsupervised.ca/aoc2021/five"
"unsupervised.ca/aoc2021/four"
"unsupervised.ca/aoc2021/fourteen"
"unsupervised.ca/aoc2021/nine"
"unsupervised.ca/aoc2021/one"
"unsupervised.ca/aoc2021/seven"
@@ -61,6 +62,8 @@ func main() {
day = twelve.Init("twelve/input.txt")
case "thirteen":
day = thirteen.Init("thirteen/input.txt")
case "fourteen":
day = fourteen.Init("fourteen/input.txt")
default:
fmt.Printf("%q does not have a solution.\n", flagParts[1])
help()