Skip to content

Commit b07e0b5

Browse files
committed
day13 done!
1 parent baa5f4f commit b07e0b5

File tree

4 files changed

+142
-2
lines changed

4 files changed

+142
-2
lines changed

2020/day13/day13.go

+97-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,102 @@
11
package day13
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"math"
6+
"strconv"
7+
"strings"
8+
)
49

510
func Run(lines []string) error {
6-
return fmt.Errorf("not yet implemented")
11+
timestamp, err := strconv.Atoi(lines[0])
12+
if err != nil {
13+
return fmt.Errorf("invalid timestamp '%s'", lines[0])
14+
}
15+
busIDs, offsets, err := parseBusIDs(lines[1])
16+
if err != nil {
17+
return fmt.Errorf("error parsing bus IDs: %v", err)
18+
}
19+
20+
id, departure, err := ComputeBestDeparture(timestamp, busIDs)
21+
if err != nil {
22+
return err
23+
}
24+
waitTime := departure - timestamp
25+
result := id * waitTime
26+
27+
fmt.Println("Part 1:", result)
28+
29+
sequentialDeparture := ComputeSequentialDeparture(busIDs, offsets)
30+
fmt.Println("Part 2:", sequentialDeparture)
31+
32+
return nil
33+
}
34+
35+
func parseBusIDs(input string) ([]int, []int, error) {
36+
splat := strings.Split(input, ",")
37+
ids := []int{}
38+
offsets := []int{}
39+
for idx, idstr := range splat {
40+
if idstr != "x" {
41+
id, err := strconv.Atoi(idstr)
42+
if err != nil {
43+
return nil, nil, fmt.Errorf("invalid bus ID '%s'", idstr)
44+
}
45+
ids = append(ids, id)
46+
offsets = append(offsets, idx)
47+
}
48+
}
49+
return ids, offsets, nil
50+
}
51+
52+
func ComputeSequentialDeparture(ids []int, offsets []int) int64 {
53+
incrementor := int64(ids[0])
54+
timeIndex := int64(incrementor)
55+
foundMatch := make([]bool, len(offsets))
56+
foundMatch[0] = true
57+
remainingIntervals := len(ids) - 1
58+
for {
59+
for idx := range ids {
60+
if (timeIndex+int64(offsets[idx]))%int64(ids[idx]) == 0 {
61+
if !foundMatch[idx] {
62+
incrementor *= int64(ids[idx])
63+
foundMatch[idx] = true
64+
remainingIntervals -= 1
65+
}
66+
}
67+
}
68+
69+
if remainingIntervals == 0 {
70+
if isValidDeparture(timeIndex, ids, offsets) {
71+
return timeIndex
72+
} else {
73+
panic("something went horribly wrong")
74+
}
75+
}
76+
77+
timeIndex += incrementor
78+
}
79+
}
80+
81+
func isValidDeparture(timeIndex int64, ids []int, offsets []int) bool {
82+
for idx := range ids {
83+
if (timeIndex+int64(offsets[idx]))%int64(ids[idx]) != 0 {
84+
return false
85+
}
86+
}
87+
return true
88+
}
89+
90+
func ComputeBestDeparture(timestamp int, busIDs []int) (int, int, error) {
91+
bestID := -1
92+
bestDeparture := -1
93+
for _, id := range busIDs {
94+
bestDivisor := int(math.Ceil(float64(timestamp) / float64(id)))
95+
departure := bestDivisor * id
96+
if bestDeparture == -1 || departure < bestDeparture {
97+
bestID = id
98+
bestDeparture = departure
99+
}
100+
}
101+
return bestID, bestDeparture, nil
7102
}

2020/day13/day13_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -1 +1,42 @@
11
package day13
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestPart1(t *testing.T) {
10+
busIds, remainders, err := parseBusIDs("7,13,x,x,59,x,31,19")
11+
require.NoError(t, err)
12+
require.Equal(t, []int{7, 13, 59, 31, 19}, busIds)
13+
require.Equal(t, []int{0, 1, 4, 6, 7}, remainders)
14+
id, departure, err := ComputeBestDeparture(939, busIds)
15+
require.NoError(t, err)
16+
require.Equal(t, 59, id)
17+
require.Equal(t, 944, departure)
18+
}
19+
20+
var testCases = []struct {
21+
sequentialDeparture int64
22+
ids []int
23+
offsets []int
24+
}{
25+
{3417, []int{17, 13, 19}, []int{0, 2, 3}},
26+
{754018, []int{67, 7, 59, 61}, []int{0, 1, 2, 3}},
27+
{779210, []int{67, 7, 59, 61}, []int{0, 2, 3, 4}},
28+
{1261476, []int{67, 7, 59, 61}, []int{0, 1, 3, 4}},
29+
{1202161486, []int{1789, 37, 47, 1889}, []int{0, 1, 2, 3}},
30+
}
31+
32+
func TestIsValidDeparture(t *testing.T) {
33+
for _, testCase := range testCases {
34+
require.True(t, isValidDeparture(testCase.sequentialDeparture, testCase.ids, testCase.offsets))
35+
}
36+
}
37+
38+
func TestComputeSequentialDeparture(t *testing.T) {
39+
for _, testCase := range testCases {
40+
require.Equal(t, testCase.sequentialDeparture, ComputeSequentialDeparture(testCase.ids, testCase.offsets))
41+
}
42+
}

2020/day13/input.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1008833
2+
19,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,643,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,17,13,x,x,x,x,23,x,x,x,x,x,x,x,509,x,x,x,x,x,37,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,29

2020/day13/scratch.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
17,13,19
2+
0,2,3

0 commit comments

Comments
 (0)