Compare commits
10 Commits
40bcf3052f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 34be9e0847 | |||
| 6ea67eac0c | |||
| bb366fbe17 | |||
| 681b7bae16 | |||
| c8ded5c42d | |||
| b37f1ec366 | |||
| 40e2e329e0 | |||
| fa5bf2e85b | |||
| ea1b57b17e | |||
| 174671e6f5 |
@@ -8,15 +8,19 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
var reindeerPattern = regexp.MustCompile(`\w+ can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds\.`)
|
||||||
registry.Register("2015D14", ParseInput, PartOne, PartTwo)
|
|
||||||
}
|
const raceTime = 2503
|
||||||
|
|
||||||
type Reindeer struct {
|
type Reindeer struct {
|
||||||
Speed int
|
Speed int
|
||||||
FlyTime int
|
FlyTime int
|
||||||
RestTime int
|
RestTime int
|
||||||
CycleTime int
|
Points int
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.Register("2015D14", ParseInput, PartOne, PartTwo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseInput(filepath string) []string {
|
func ParseInput(filepath string) []string {
|
||||||
@@ -24,28 +28,37 @@ func ParseInput(filepath string) []string {
|
|||||||
return strings.Split(string(content), "\n")
|
return strings.Split(string(content), "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateMaxDistance(data []string, time int) int {
|
func parseReindeer(line string) Reindeer {
|
||||||
maxDistance := 0
|
matches := reindeerPattern.FindStringSubmatch(line)
|
||||||
pattern := regexp.MustCompile(`\w+ can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds\.`)
|
speed, _ := strconv.Atoi(matches[1])
|
||||||
|
flyTime, _ := strconv.Atoi(matches[2])
|
||||||
|
restTime, _ := strconv.Atoi(matches[3])
|
||||||
|
return Reindeer{Speed: speed, FlyTime: flyTime, RestTime: restTime}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseReindeers(data []string) []Reindeer {
|
||||||
|
reindeers := make([]Reindeer, 0, len(data))
|
||||||
for _, line := range data {
|
for _, line := range data {
|
||||||
matches := pattern.FindStringSubmatch(line)
|
reindeers = append(reindeers, parseReindeer(line))
|
||||||
var reindeer Reindeer
|
|
||||||
reindeer.Speed, _ = strconv.Atoi(matches[1])
|
|
||||||
reindeer.FlyTime, _ = strconv.Atoi(matches[2])
|
|
||||||
reindeer.RestTime, _ = strconv.Atoi(matches[3])
|
|
||||||
reindeer.CycleTime = reindeer.FlyTime + reindeer.RestTime
|
|
||||||
|
|
||||||
fullCycles := time / reindeer.CycleTime
|
|
||||||
distance := fullCycles * reindeer.Speed * reindeer.FlyTime
|
|
||||||
|
|
||||||
remainingTime := time % reindeer.CycleTime
|
|
||||||
if remainingTime > reindeer.FlyTime {
|
|
||||||
distance += reindeer.Speed * reindeer.FlyTime
|
|
||||||
} else {
|
|
||||||
distance += reindeer.Speed * remainingTime
|
|
||||||
}
|
}
|
||||||
|
return reindeers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reindeer Reindeer) distanceAtTime(time int) int {
|
||||||
|
cycleTime := reindeer.FlyTime + reindeer.RestTime
|
||||||
|
fullCycles := time / cycleTime
|
||||||
|
distance := fullCycles * reindeer.Speed * reindeer.FlyTime
|
||||||
|
remainingTime := time % cycleTime
|
||||||
|
distance += reindeer.Speed * min(remainingTime, reindeer.FlyTime)
|
||||||
|
return distance
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateMaxDistance(data []string, time int) int {
|
||||||
|
reindeers := parseReindeers(data)
|
||||||
|
maxDistance := 0
|
||||||
|
|
||||||
|
for _, reindeer := range reindeers {
|
||||||
|
distance := reindeer.distanceAtTime(time)
|
||||||
if distance > maxDistance {
|
if distance > maxDistance {
|
||||||
maxDistance = distance
|
maxDistance = distance
|
||||||
}
|
}
|
||||||
@@ -54,10 +67,42 @@ func calculateMaxDistance(data []string, time int) int {
|
|||||||
return maxDistance
|
return maxDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calculateMaxPoints(data []string, time int) int {
|
||||||
|
reindeers := parseReindeers(data)
|
||||||
|
|
||||||
|
for second := 1; second <= time; second++ {
|
||||||
|
maxDistance := 0
|
||||||
|
distances := make([]int, len(reindeers))
|
||||||
|
|
||||||
|
for idx := range reindeers {
|
||||||
|
distance := reindeers[idx].distanceAtTime(second)
|
||||||
|
distances[idx] = distance
|
||||||
|
if distance > maxDistance {
|
||||||
|
maxDistance = distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx := range reindeers {
|
||||||
|
if distances[idx] == maxDistance {
|
||||||
|
reindeers[idx].Points++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxPoints := 0
|
||||||
|
for idx := range reindeers {
|
||||||
|
if reindeers[idx].Points > maxPoints {
|
||||||
|
maxPoints = reindeers[idx].Points
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxPoints
|
||||||
|
}
|
||||||
|
|
||||||
func PartOne(data []string) int {
|
func PartOne(data []string) int {
|
||||||
return calculateMaxDistance(data, 2503)
|
return calculateMaxDistance(data, raceTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PartTwo(data []string) int {
|
func PartTwo(data []string) int {
|
||||||
return 0
|
return calculateMaxPoints(data, raceTime)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,3 +14,11 @@ func TestPartOne(t *testing.T) {
|
|||||||
t.Errorf("calculateMaxDistance(testInput, 1000) = %d, want %d", got, expected)
|
t.Errorf("calculateMaxDistance(testInput, 1000) = %d, want %d", got, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPartTwo(t *testing.T) {
|
||||||
|
expected := 689
|
||||||
|
got := calculateMaxPoints(testInput, 1000)
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("calculateMaxPoints(testInput, 1000) = %d, want %d", got, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
64
internal/2018/DayFive/code.go
Normal file
64
internal/2018/DayFive/code.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package dayfive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"advent-of-code/internal/registry"
|
||||||
|
"os"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.Register("2018D5", ParseInput, PartOne, PartTwo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseInput(filepath string) string {
|
||||||
|
content, _ := os.ReadFile(filepath)
|
||||||
|
return string(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reactPolymer(data string) int {
|
||||||
|
stack := []rune{}
|
||||||
|
|
||||||
|
for _, char := range data {
|
||||||
|
if len(stack) == 0 {
|
||||||
|
stack = append(stack, char)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
top := stack[len(stack)-1]
|
||||||
|
|
||||||
|
if unicode.ToLower(top) == unicode.ToLower(char) && top != char {
|
||||||
|
stack = stack[:len(stack)-1]
|
||||||
|
} else {
|
||||||
|
stack = append(stack, char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PartOne(data string) int {
|
||||||
|
return reactPolymer(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PartTwo(data string) int {
|
||||||
|
unitTypes := make(map[rune]bool)
|
||||||
|
for _, char := range data {
|
||||||
|
unitTypes[unicode.ToLower(char)] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
shortestPolymerLength := len(data)
|
||||||
|
for unitType := range unitTypes {
|
||||||
|
filtered := make([]rune, 0, len(data))
|
||||||
|
for _, char := range data {
|
||||||
|
if unicode.ToLower(char) != unitType {
|
||||||
|
filtered = append(filtered, char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
length := reactPolymer(string(filtered))
|
||||||
|
if length < shortestPolymerLength {
|
||||||
|
shortestPolymerLength = length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortestPolymerLength
|
||||||
|
}
|
||||||
21
internal/2018/DayFive/code_test.go
Normal file
21
internal/2018/DayFive/code_test.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package dayfive
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var testInput = "dabAcCaCBAcCcaDA"
|
||||||
|
|
||||||
|
func TestPartOne(t *testing.T) {
|
||||||
|
expected := 10
|
||||||
|
got := PartOne(testInput)
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("PartOne() = %d, want %d", got, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPartTwo(t *testing.T) {
|
||||||
|
expected := 4
|
||||||
|
got := PartTwo(testInput)
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("PartTwo() = %d, want %d", got, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package year2018
|
package year2018
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "advent-of-code/internal/2018/DayFive"
|
||||||
_ "advent-of-code/internal/2018/DayFour"
|
_ "advent-of-code/internal/2018/DayFour"
|
||||||
_ "advent-of-code/internal/2018/DayOne"
|
_ "advent-of-code/internal/2018/DayOne"
|
||||||
_ "advent-of-code/internal/2018/DayThree"
|
_ "advent-of-code/internal/2018/DayThree"
|
||||||
|
|||||||
1
internal/data/2018/DayFive/input.txt
Normal file
1
internal/data/2018/DayFive/input.txt
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user