Day 9: Part 1 and 2

Signed-off-by: James Griffin <james@unsupervised.ca>
This commit is contained in:
2020-12-09 11:24:19 -04:00
parent a5386931db
commit 1cb55213bc
5 changed files with 1207 additions and 3 deletions

10
main.go
View File

@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/thatguygriff/aoc2020/eight"
"github.com/thatguygriff/aoc2020/nine"
)
func main() {
@@ -36,6 +36,10 @@ func main() {
// fmt.Println(seven.PartTwo())
// Day 8
fmt.Println(eight.PartOne())
fmt.Println(eight.PartTwo())
// fmt.Println(eight.PartOne())
// fmt.Println(eight.PartTwo())
// Day 9
fmt.Println(nine.PartOne())
fmt.Println(nine.PartTwo())
}

135
nine/day_nine.go Normal file
View File

@@ -0,0 +1,135 @@
package nine
import (
"bufio"
"fmt"
"os"
"strconv"
)
type xmas struct {
preamble int
values []int
}
func newXmas(filename string, preamble int) (*xmas, error) {
x := &xmas{}
if err := x.load(filename, preamble); err != nil {
return nil, err
}
return x, nil
}
func (x *xmas) load(filename string, preamble int) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
v, err := strconv.Atoi(scanner.Text())
if err != nil {
return err
}
x.values = append(x.values, v)
}
x.preamble = preamble
return nil
}
func (x *xmas) detectVulnerability() (int, error) {
index := x.preamble
if index > len(x.values) {
return 0, fmt.Errorf("Preamble is larger than the range of inputs")
}
var match bool
for index < len(x.values) {
searchable := x.values[index-x.preamble : index]
match = false
for i := 0; i < len(searchable); i++ {
for j := i + 1; j < len(searchable); j++ {
if searchable[i] == searchable[j] {
continue
}
if searchable[i]+searchable[j] == x.values[index] {
match = true
}
}
}
if !match {
return x.values[index], nil
}
index++
}
return 0, fmt.Errorf("Did not find a vulnerable value")
}
func (x *xmas) computeWeakness() (int, error) {
v, err := x.detectVulnerability()
if err != nil {
return 0, nil
}
for i := 0; i < len(x.values); i++ {
sum := x.values[i]
min := x.values[i]
max := x.values[i]
if x.values[i] == v {
return 0, fmt.Errorf("Did not find encryption weakness before %d", v)
}
for j := i + 1; j < len(x.values); j++ {
sum += x.values[j]
if x.values[j] < min {
min = x.values[j]
}
if x.values[j] > max {
max = x.values[j]
}
// We found the contiguous range of values!
if sum == v {
return min + max, nil
}
// This means that the contiguous run starting at i was a bust
if sum > v {
break
}
}
}
return 0, nil
}
// PartOne Find the first vulnerable number in the xmas chain
func PartOne() string {
x, _ := newXmas("nine/input.txt", 25)
v, _ := x.detectVulnerability()
return fmt.Sprintf("The first vulnerable value in the XMAS input is %d", v)
}
// PartTwo Find the encryption weaknes in the xmas chain
func PartTwo() string {
x, _ := newXmas("nine/input.txt", 25)
w, _ := x.computeWeakness()
return fmt.Sprintf("The encryption weakness in the XMAS input is %d", w)
}

45
nine/day_nine_test.go Normal file
View File

@@ -0,0 +1,45 @@
package nine
import "testing"
func Test_program_load(t *testing.T) {
x := xmas{}
err := x.load("sample.txt", 5)
if err != nil {
t.Log(err)
t.FailNow()
}
if len(x.values) != 20 {
t.Logf("Expected 20 values, Got %d values", len(x.values))
t.FailNow()
}
}
func Test_weakness_detection(t *testing.T) {
x, err := newXmas("sample.txt", 5)
if err != nil {
t.Log(err)
t.FailNow()
}
v, err := x.detectVulnerability()
if err != nil || v != 127 {
t.Logf("Expected vulnerability of 127, Got vulnerability %d", v)
t.FailNow()
}
}
func Test_weakness_compute(t *testing.T) {
x, err := newXmas("sample.txt", 5)
if err != nil {
t.Log(err)
t.FailNow()
}
e, err := x.computeWeakness()
if err != nil || e != 62 {
t.Logf("Expected weaknes 62, Got weakness %d", e)
t.FailNow()
}
}

1000
nine/input.txt Normal file

File diff suppressed because it is too large Load Diff

20
nine/sample.txt Normal file
View File

@@ -0,0 +1,20 @@
35
20
15
25
47
40
62
55
65
95
102
117
150
182
127
219
299
277
309
576