Compare commits

...

2 Commits

Author SHA1 Message Date
24a65d3752 feat: solve part one using brute-force permutation search 2025-12-08 21:26:06 +01:00
0bd0ec5f1e test: add unit test for part one 2025-12-08 21:24:58 +01:00
2 changed files with 140 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
package daythirteen
import (
"advent-of-code/internal/registry"
"math"
"os"
"regexp"
"strconv"
"strings"
)
var inputPattern = regexp.MustCompile(`(\w+) would (gain|lose) (\d+) happiness units by sitting next to (\w+)\.?`)
func init() {
registry.Register("2015D13", ParseInput, PartOne, PartTwo)
}
func buildHappinessMap(data []string) map[string]map[string]int {
happinessMap := make(map[string]map[string]int)
for _, line := range data {
matches := inputPattern.FindStringSubmatch(line)
person := matches[1]
operation := matches[2]
value, _ := strconv.Atoi(matches[3])
neighbor := matches[4]
if happinessMap[person] == nil {
happinessMap[person] = make(map[string]int)
}
if operation == "gain" {
happinessMap[person][neighbor] = value
} else {
happinessMap[person][neighbor] = -value
}
}
return happinessMap
}
func getAllPeople(happinessMap map[string]map[string]int) []string {
people := make([]string, 0, len(happinessMap))
for person := range happinessMap {
people = append(people, person)
}
return people
}
func generatePermutations(items []string) [][]string {
if len(items) == 0 {
return [][]string{{}}
}
var result [][]string
for idx, item := range items {
remaining := make([]string, len(items)-1)
copy(remaining[:idx], items[:idx])
copy(remaining[idx:], items[idx+1:])
for _, permutation := range generatePermutations(remaining) {
result = append(result, append([]string{item}, permutation...))
}
}
return result
}
func calculateTotalHappiness(arrangement []string, happinessMap map[string]map[string]int) int {
totalHappiness := 0
arrangementLength := len(arrangement)
for idx := range arrangementLength {
currentPerson := arrangement[idx]
leftNeighbor := arrangement[(idx-1+arrangementLength)%arrangementLength]
rightNeighbor := arrangement[(idx+1)%arrangementLength]
totalHappiness += happinessMap[currentPerson][leftNeighbor]
totalHappiness += happinessMap[currentPerson][rightNeighbor]
}
return totalHappiness
}
func ParseInput(filepath string) []string {
content, _ := os.ReadFile(filepath)
return strings.Split(string(content), "\n")
}
func PartOne(data []string) int {
happinessMap := buildHappinessMap(data)
allPeople := getAllPeople(happinessMap)
fixedPerson := allPeople[0]
remainingPeople := allPeople[1:]
permutations := generatePermutations(remainingPeople)
maxHappiness := math.MinInt
arrangement := make([]string, len(allPeople))
arrangement[0] = fixedPerson
for _, perm := range permutations {
copy(arrangement[1:], perm)
totalHappiness := calculateTotalHappiness(arrangement, happinessMap)
if totalHappiness > maxHappiness {
maxHappiness = totalHappiness
}
}
return maxHappiness
}
func PartTwo(data []string) int {
return 0
}

View File

@@ -0,0 +1,26 @@
package daythirteen
import "testing"
var testInput = []string{
"Alice would gain 54 happiness units by sitting next to Bob",
"Alice would lose 79 happiness units by sitting next to Carol",
"Alice would lose 2 happiness units by sitting next to David",
"Bob would gain 83 happiness units by sitting next to Alice",
"Bob would lose 7 happiness units by sitting next to Carol",
"Bob would lose 63 happiness units by sitting next to David",
"Carol would lose 62 happiness units by sitting next to Alice",
"Carol would gain 60 happiness units by sitting next to Bob",
"Carol would gain 55 happiness units by sitting next to David",
"David would gain 46 happiness units by sitting next to Alice",
"David would lose 7 happiness units by sitting next to Bob",
"David would gain 41 happiness units by sitting next to Carol",
}
func TestPartOne(t *testing.T) {
expected := 330
got := PartOne(testInput)
if got != expected {
t.Errorf("PartOne() = %d, want %d", got, expected)
}
}