From 6972ec84a1bc1645866e0d8e0b35b4f0f45e4867 Mon Sep 17 00:00:00 2001 From: James Griffin Date: Sun, 13 Dec 2020 14:43:04 -0400 Subject: [PATCH] Day 13: Part 1 and 2 Signed-off-by: James Griffin --- main.go | 10 ++- thirteen/day_thirteen.go | 138 ++++++++++++++++++++++++++++++++++ thirteen/day_thirteen_test.go | 77 +++++++++++++++++++ thirteen/input.txt | 2 + thirteen/sample.txt | 2 + 5 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 thirteen/day_thirteen.go create mode 100644 thirteen/day_thirteen_test.go create mode 100644 thirteen/input.txt create mode 100644 thirteen/sample.txt diff --git a/main.go b/main.go index 791fc8b..863c00d 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/thatguygriff/aoc2020/twelve" + "github.com/thatguygriff/aoc2020/thirteen" ) func main() { @@ -52,6 +52,10 @@ func main() { // fmt.Println(eleven.PartTwo()) // Day 12 - fmt.Println(twelve.PartOne()) - fmt.Println(twelve.PartTwo()) + // fmt.Println(twelve.PartOne()) + // fmt.Println(twelve.PartTwo()) + + // Day 13 + fmt.Println(thirteen.PartOne()) + fmt.Println(thirteen.PartTwo()) } diff --git a/thirteen/day_thirteen.go b/thirteen/day_thirteen.go new file mode 100644 index 0000000..caa37a6 --- /dev/null +++ b/thirteen/day_thirteen.go @@ -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()) +} diff --git a/thirteen/day_thirteen_test.go b/thirteen/day_thirteen_test.go new file mode 100644 index 0000000..d2b763d --- /dev/null +++ b/thirteen/day_thirteen_test.go @@ -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() + } +} diff --git a/thirteen/input.txt b/thirteen/input.txt new file mode 100644 index 0000000..793ebb1 --- /dev/null +++ b/thirteen/input.txt @@ -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 \ No newline at end of file diff --git a/thirteen/sample.txt b/thirteen/sample.txt new file mode 100644 index 0000000..e473080 --- /dev/null +++ b/thirteen/sample.txt @@ -0,0 +1,2 @@ +939 +7,13,x,x,59,x,31,19 \ No newline at end of file