143 lines
2.9 KiB
Go
143 lines
2.9 KiB
Go
package day1
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func getDistance(x, y int) int {
|
|
// Take the distance between two numbers.
|
|
// The distance is the difference between the two numbers.
|
|
|
|
if x > y {
|
|
return (x - y)
|
|
|
|
} else {
|
|
return (y - x)
|
|
|
|
}
|
|
}
|
|
|
|
func processLine(line string) (int, int, error) {
|
|
// Split the line into fields.
|
|
fields := strings.Fields(line)
|
|
if len(fields) != 2 {
|
|
return 0, 0, fmt.Errorf("Expected 2 fields, got %d", len(fields))
|
|
}
|
|
num1, err := strconv.Atoi(fields[0])
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf("Failed to parse first number: %w", err)
|
|
}
|
|
|
|
num2, err := strconv.Atoi(fields[1])
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf("Failed to parse the second number: %w", err)
|
|
}
|
|
|
|
return num1, num2, nil
|
|
|
|
}
|
|
|
|
func readDataSet(filename string) ([]int, []int, error) {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
var firstSet, secondSet []int
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
num1, num2, err := processLine(line)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
firstSet = append(firstSet, num1)
|
|
secondSet = append(secondSet, num2)
|
|
}
|
|
|
|
return firstSet, secondSet, nil
|
|
}
|
|
|
|
func numFreq(dataset []int) map[int]int {
|
|
// Take a slice of numbers and return an array of each number and the amount of times it occurs.
|
|
distribution := make(map[int]int)
|
|
for _, num := range dataset {
|
|
elem, ok := distribution[num]
|
|
if ok {
|
|
distribution[num] = elem + 1
|
|
} else {
|
|
distribution[num] = 1
|
|
}
|
|
}
|
|
return distribution
|
|
}
|
|
|
|
func partTwo(filename string) (int, error) {
|
|
//Solve part two.
|
|
var similarities int
|
|
firstSet, secondSet, err := readDataSet(filename)
|
|
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
secondDistribution := numFreq(secondSet)
|
|
|
|
for _, num := range firstSet {
|
|
freq, ok := secondDistribution[num]
|
|
if ok {
|
|
similarity := num * freq
|
|
similarities = similarities + similarity
|
|
}
|
|
}
|
|
|
|
return similarities, nil
|
|
}
|
|
|
|
func partOne(filename string) (int, error) {
|
|
// Solve part one.
|
|
|
|
firstSet, secondSet, err := readDataSet(filename)
|
|
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
slices.Sort(firstSet)
|
|
slices.Sort(secondSet)
|
|
if len(firstSet) != len(secondSet) {
|
|
return 0, fmt.Errorf("Error: Datasets are not the same size. %v != %v", len(firstSet), len(secondSet))
|
|
}
|
|
var distances int
|
|
for i := 0; i < len(firstSet); i++ {
|
|
distance := getDistance(firstSet[i], secondSet[i])
|
|
distances = distances + distance
|
|
}
|
|
|
|
return distances, nil
|
|
}
|
|
|
|
func Day1(filename string) {
|
|
distances, err := partOne(filename)
|
|
if err != nil {
|
|
fmt.Printf("Error: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println("-------- PART 1 -------")
|
|
fmt.Printf("The total distance is %v\n", distances)
|
|
similarities, err := partTwo(filename)
|
|
if err != nil {
|
|
fmt.Printf("Error: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Println("-------- PART 2 -------")
|
|
fmt.Printf("The similarities between the two sets: %v\n", similarities)
|
|
}
|