package day_05 import ( "fmt" "slices" "strconv" "strings" ) type Rules map[int][]int type Manual []int // task:https://adventofcode.com/2024/day/5 // short summary - count valid columns func SolveBasic(input string) int { manuals, rules := loadManualAndRules(input) sum := 0 for _, manual := range manuals { if isManualValid(manual, rules) { sum += manual[len(manual)/2] } } return sum } // task:https://adventofcode.com/2024/day/5#part2 // short summary - fix and count invalid columns func SolveComplex(input string) int { manuals, rules := loadManualAndRules(input) sum := 0 for _, manual := range manuals { if !isManualValid(manual, rules) { manual = fixManual(manual, rules) sum += manual[len(manual)/2] } } return sum } func fixManual(manual Manual, rules Rules) Manual { for { index := violationIndex(manual, rules) if index == -1 { return manual } violation := manual[index] manual = slices.Delete(manual, index, index+1) for i := 0; i < len(manual); i++ { if values, present := rules[manual[i]]; present { if slices.Contains(values, violation) { manual = slices.Insert(manual, i, violation) break } } } } } // helper methods func isManualValid(manual Manual, rules Rules) bool { return violationIndex(manual, rules) == -1 } func violationIndex(manual Manual, rules Rules) int { illegalValues := []int{} for i, num := range manual { if slices.Contains(illegalValues, num) { return i } if _, contains := rules[num]; contains { illegalValues = append(illegalValues, rules[num]...) } } return -1 } func loadManualAndRules(input string) ([]Manual, Rules) { substrings := strings.Split(input, "\n\n") rules := loadRules(substrings[0]) manuals := loadManuals(substrings[1]) return manuals, rules } func loadManuals(s string) []Manual { var manuals []Manual for _, line := range strings.Split(s, "\n") { manuals = append(manuals, loadManual(line)) } return manuals } func loadManual(line string) []int { var manual Manual for _, value := range strings.Split(line, ",") { manual = append(manual, must(strconv.Atoi(value))) } return manual } func must(val int, err error) int { if err != nil { panic(err) } return val } func loadRules(s string) Rules { rules := map[int][]int{} for _, line := range strings.Split(s, "\n") { var k, v int _, err := fmt.Sscanf(line, "%d|%d", &k, &v) if err != nil { panic(err) } rules[v] = append(rules[v], k) } return rules }