Day 01. solutions
This commit is contained in:
parent
a9253ccb1b
commit
eff1d70d1c
|
@ -0,0 +1,8 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "embed"
|
||||||
|
|
||||||
|
// File embedding all data required in final solutions
|
||||||
|
|
||||||
|
//go:embed day_01/data.txt
|
||||||
|
var Day01Data string
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
3 4
|
||||||
|
4 3
|
||||||
|
2 5
|
||||||
|
1 3
|
||||||
|
3 9
|
||||||
|
3 3
|
|
@ -0,0 +1,76 @@
|
||||||
|
package day_01
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// task:https://adventofcode.com/2024/day/1
|
||||||
|
// short summary - we are offered two lists of location IDs,
|
||||||
|
// and we need to compare the smallest ID from one list with the
|
||||||
|
// smallest from the other one,
|
||||||
|
// and calculate the difference between them
|
||||||
|
|
||||||
|
func SolveBasic(input string) int {
|
||||||
|
firstIds, secondIds := loadSortedLocationIds(input)
|
||||||
|
|
||||||
|
diff := 0
|
||||||
|
for i := 0; i < len(firstIds); i++ {
|
||||||
|
diff += abs(firstIds[i] - secondIds[i])
|
||||||
|
}
|
||||||
|
return diff
|
||||||
|
}
|
||||||
|
|
||||||
|
// task:https://adventofcode.com/2024/day/1#part2
|
||||||
|
// short summary - the initial comparison wasn't that good,
|
||||||
|
// so instead we need to check how often values
|
||||||
|
// from the first list appear in the second one, multiply the value with the number
|
||||||
|
// of appearances and sum all of that up
|
||||||
|
func SolveComplex(input string) int {
|
||||||
|
firstIds, secondIds := loadSortedLocationIds(input)
|
||||||
|
|
||||||
|
// we could have avoided this and run a binary search and count for every number
|
||||||
|
// but this was simpler and perhaps even faster to run
|
||||||
|
idOccurrences := map[int]int{}
|
||||||
|
for _, locationId := range secondIds {
|
||||||
|
// this works for missing values as idOccurrences[location]
|
||||||
|
// will return 0 if no value is present for numbers
|
||||||
|
idOccurrences[locationId] = idOccurrences[locationId] + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := 0
|
||||||
|
for _, locationId := range firstIds {
|
||||||
|
// this works for the same reason as above
|
||||||
|
sum += idOccurrences[locationId] * locationId
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper methods
|
||||||
|
|
||||||
|
func loadSortedLocationIds(input string) ([]int, []int) {
|
||||||
|
lines := strings.Split(input, "\n")
|
||||||
|
// we create slices of the required size at start
|
||||||
|
firstIds := make([]int, len(lines))
|
||||||
|
secondIds := make([]int, len(lines))
|
||||||
|
|
||||||
|
for i, line := range lines {
|
||||||
|
if _, err := fmt.Sscan(line, &firstIds[i], &secondIds[i]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Ints(firstIds)
|
||||||
|
sort.Ints(secondIds)
|
||||||
|
|
||||||
|
return firstIds, secondIds
|
||||||
|
}
|
||||||
|
|
||||||
|
// go doesn't have an Abs(int) int func so we write our own
|
||||||
|
func abs(value int) int {
|
||||||
|
if value < 0 {
|
||||||
|
return -value
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package day_01_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"advent_of_code_2024/day_01"
|
||||||
|
_ "embed"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed example_data.txt
|
||||||
|
var BasicExampleData string
|
||||||
|
|
||||||
|
func TestBasicSolutionExample(t *testing.T) {
|
||||||
|
result := day_01.SolveBasic(BasicExampleData)
|
||||||
|
if result != 11 {
|
||||||
|
t.Fatalf("Expected 11 received %d", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComplexSolutionExample(t *testing.T) {
|
||||||
|
result := day_01.SolveComplex(BasicExampleData)
|
||||||
|
if result != 31 {
|
||||||
|
t.Fatalf("Expected 31 received %d", result)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"advent_of_code_2024/day_01"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
selectedDay := selectSolutionRun()
|
||||||
|
|
||||||
|
switch selectedDay {
|
||||||
|
case "01-basic":
|
||||||
|
fmt.Printf("Day 01. Basic: %d\n", day_01.SolveBasic(Day01Data)) // 2113135
|
||||||
|
case "01-complex":
|
||||||
|
fmt.Printf("Day 01. Complex: %d\n", day_01.SolveComplex(Day01Data)) // 19097157
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func selectSolutionRun() string {
|
||||||
|
selectedDay := ""
|
||||||
|
if len(os.Args) == 2 {
|
||||||
|
// if command line arg passed use that
|
||||||
|
selectedDay = os.Args[1]
|
||||||
|
} else if len(os.Args) == 1 {
|
||||||
|
// otherwise ask user for the solution
|
||||||
|
fmt.Printf("Enter the solution to be run: e.g. 01-basic,21-complex...\n")
|
||||||
|
if _, err := fmt.Scan(&selectedDay); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if too many arguments are passed return error message
|
||||||
|
fmt.Printf("Invalid number of arguments\nUsage: %s day-basic|day-complex\n e.g. %s 01-basic", os.Args[0], os.Args[0])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return selectedDay
|
||||||
|
}
|
Loading…
Reference in New Issue