Day 13: 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/twelve"
|
"github.com/thatguygriff/aoc2020/thirteen"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -52,6 +52,10 @@ func main() {
|
|||||||
// fmt.Println(eleven.PartTwo())
|
// fmt.Println(eleven.PartTwo())
|
||||||
|
|
||||||
// Day 12
|
// Day 12
|
||||||
fmt.Println(twelve.PartOne())
|
// fmt.Println(twelve.PartOne())
|
||||||
fmt.Println(twelve.PartTwo())
|
// fmt.Println(twelve.PartTwo())
|
||||||
|
|
||||||
|
// Day 13
|
||||||
|
fmt.Println(thirteen.PartOne())
|
||||||
|
fmt.Println(thirteen.PartTwo())
|
||||||
}
|
}
|
||||||
|
138
thirteen/day_thirteen.go
Normal file
138
thirteen/day_thirteen.go
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package thirteen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bus struct {
|
||||||
|
id int
|
||||||
|
}
|
||||||
|
|
||||||
|
type note struct {
|
||||||
|
departure int
|
||||||
|
routes []bus
|
||||||
|
sequence []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func notes(f string) (*note, error) {
|
||||||
|
n := ¬e{}
|
||||||
|
if err := n.load(f); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *note) load(filename string) error {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
first := true
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
if first {
|
||||||
|
time, err := strconv.Atoi(scanner.Text())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.departure = time
|
||||||
|
first = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buses := strings.Split(scanner.Text(), ",")
|
||||||
|
for _, b := range buses {
|
||||||
|
if b == "x" {
|
||||||
|
n.sequence = append(n.sequence, -1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.Atoi(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.routes = append(n.routes, bus{id: id})
|
||||||
|
n.sequence = append(n.sequence, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *note) firstBus() int {
|
||||||
|
wait := 0
|
||||||
|
now := n.departure
|
||||||
|
|
||||||
|
for {
|
||||||
|
for _, bus := range n.routes {
|
||||||
|
if now%bus.id == 0 {
|
||||||
|
fmt.Println("Found", bus.id, "after a wait of", wait)
|
||||||
|
return wait * bus.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
now++
|
||||||
|
wait++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *note) sequenceStart() int {
|
||||||
|
if len(n.sequence) == 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
time := 0
|
||||||
|
for {
|
||||||
|
// Naive interval skipping, only check times where the first bus is scheduled
|
||||||
|
interval := n.sequence[0]
|
||||||
|
found := true
|
||||||
|
for i := 1; i < len(n.sequence); i++ {
|
||||||
|
// Skip unconstrained rules
|
||||||
|
if n.sequence[i] == -1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time+i)%n.sequence[i] == 0 {
|
||||||
|
// We know that the bus at i is correct, so we can skip interval*bus id ahead for the next time this is valid
|
||||||
|
interval *= n.sequence[i]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// We reach this point if the sequence is broken. We now advance
|
||||||
|
// to the next time the first bus is valid
|
||||||
|
time += interval
|
||||||
|
found = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return time
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartOne find the product of the wait * bus id to get to the airport
|
||||||
|
func PartOne() string {
|
||||||
|
n, err := notes("thirteen/input.txt")
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Found a product of %d", n.firstBus())
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartTwo What is the answer to the consequtive departure minutes contest
|
||||||
|
func PartTwo() string {
|
||||||
|
n, err := notes("thirteen/input.txt")
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("The earliest minute is %d", n.sequenceStart())
|
||||||
|
}
|
77
thirteen/day_thirteen_test.go
Normal file
77
thirteen/day_thirteen_test.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package thirteen
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Test_note_load(t *testing.T) {
|
||||||
|
n, err := notes("sample.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Logf(err.Error())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(n.routes) != 5 {
|
||||||
|
t.Logf("Expected 5 routes, found %d", n.routes)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.departure != 939 {
|
||||||
|
t.Logf("Expected departure of 939, found %d", n.departure)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_find_first(t *testing.T) {
|
||||||
|
n, _ := notes("sample.txt")
|
||||||
|
|
||||||
|
result := n.firstBus()
|
||||||
|
|
||||||
|
if result != 295 {
|
||||||
|
t.Logf("Expected product of 295 for first bus, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_contest_start(t *testing.T) {
|
||||||
|
n, _ := notes("sample.txt")
|
||||||
|
|
||||||
|
result := n.sequenceStart()
|
||||||
|
if result != 1068781 {
|
||||||
|
t.Logf("Expected time of 1068781 for sequence, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
n.sequence = []int{17, -1, 13, 19}
|
||||||
|
result = n.sequenceStart()
|
||||||
|
if result != 3417 {
|
||||||
|
t.Logf("Expected time of 3417 for sequence, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
n.sequence = []int{67, 7, 59, 61}
|
||||||
|
result = n.sequenceStart()
|
||||||
|
if result != 754018 {
|
||||||
|
t.Logf("Expected time of 754018 for sequence, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
n.sequence = []int{67, -1, 7, 59, 61}
|
||||||
|
result = n.sequenceStart()
|
||||||
|
if result != 779210 {
|
||||||
|
t.Logf("Expected time of 779210 for sequence, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
n.sequence = []int{67, 7, -1, 59, 61}
|
||||||
|
result = n.sequenceStart()
|
||||||
|
if result != 1261476 {
|
||||||
|
t.Logf("Expected time of 1261476 for sequence, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
n.sequence = []int{1789, 37, 47, 1889}
|
||||||
|
result = n.sequenceStart()
|
||||||
|
if result != 1202161486 {
|
||||||
|
t.Logf("Expected time of 1202161486 for sequence, got %d", result)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
2
thirteen/input.txt
Normal file
2
thirteen/input.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
1002561
|
||||||
|
17,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,409,x,29,x,x,x,x,x,x,x,x,x,x,13,x,x,x,x,x,x,x,x,x,23,x,x,x,x,x,x,x,373,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,19
|
2
thirteen/sample.txt
Normal file
2
thirteen/sample.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
939
|
||||||
|
7,13,x,x,59,x,31,19
|
Reference in New Issue
Block a user