Day 01. solutions

This commit is contained in:
Borna Rajković 2024-12-01 10:55:43 +01:00
parent a9253ccb1b
commit eff1d70d1c
6 changed files with 1152 additions and 0 deletions

8
data.go Normal file
View File

@ -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

1000
day_01/data.txt Normal file

File diff suppressed because it is too large Load Diff

6
day_01/example_data.txt Normal file
View File

@ -0,0 +1,6 @@
3 4
4 3
2 5
1 3
3 9
3 3

76
day_01/solution.go Normal file
View File

@ -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
}

24
day_01/solution_test.go Normal file
View File

@ -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)
}
}

38
main.go Normal file
View File

@ -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
}