Day 9: Part 1 and 2
Signed-off-by: James Griffin <james@unsupervised.ca>
This commit is contained in:
10
main.go
10
main.go
@@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/thatguygriff/aoc2020/eight"
|
"github.com/thatguygriff/aoc2020/nine"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -36,6 +36,10 @@ func main() {
|
|||||||
// fmt.Println(seven.PartTwo())
|
// fmt.Println(seven.PartTwo())
|
||||||
|
|
||||||
// Day 8
|
// Day 8
|
||||||
fmt.Println(eight.PartOne())
|
// fmt.Println(eight.PartOne())
|
||||||
fmt.Println(eight.PartTwo())
|
// fmt.Println(eight.PartTwo())
|
||||||
|
|
||||||
|
// Day 9
|
||||||
|
fmt.Println(nine.PartOne())
|
||||||
|
fmt.Println(nine.PartTwo())
|
||||||
}
|
}
|
||||||
|
135
nine/day_nine.go
Normal file
135
nine/day_nine.go
Normal 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
45
nine/day_nine_test.go
Normal 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
1000
nine/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
20
nine/sample.txt
Normal file
20
nine/sample.txt
Normal 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
|
Reference in New Issue
Block a user