package day05 import ( "strconv" "strings" ) type Rule struct { X, Y int } func ParseInput(input string) ([]Rule, [][]int) { sections := strings.Split(input, "\n\n") ruleLines := strings.Split(strings.TrimSpace(sections[0]), "\n") var rules []Rule for _, ruleLine := range ruleLines { parts := strings.Split(ruleLine, "|") x, _ := strconv.Atoi(parts[0]) y, _ := strconv.Atoi(parts[1]) rules = append(rules, Rule{X: x, Y: y}) } updateLines := strings.Split(strings.TrimSpace(sections[1]), "\n") var updates [][]int for _, updateLine := range updateLines { parts := strings.Split(updateLine, ",") var update []int for _, part := range parts { page, _ := strconv.Atoi(part) update = append(update, page) } updates = append(updates, update) } return rules, updates } func ValidateUpdate(update []int, rules []Rule) bool { indexMap := make(map[int]int) for i, page := range update { indexMap[page] = i } for _, rule := range rules { pageX, indexX := indexMap[rule.X] pageY, indexY := indexMap[rule.Y] if indexX && indexY && pageX > pageY { return false } } return true } func FindMiddle(update []int) int { n := len(update) return update[n/2] } func SortUpdate(update []int, rules []Rule) []int { depen := make(map[int][]int) for _, rule := range rules { depen[rule.Y] = append(depen[rule.Y], rule.X) } visited := make(map[int]bool) var sorted []int for _, page := range update { if !visited[page] { sorted = Visit(page, depen, visited, update, sorted) } } return sorted } func Visit(page int, depen map[int][]int, visited map[int]bool, update []int, sorted []int) []int { if visited[page] { return sorted } visited[page] = true for _, d := range depen[page] { if contains(update, d) { sorted = Visit(d, depen, visited, update, sorted) } } sorted = append(sorted, page) return sorted } func contains(slice []int, element int) bool { for _, item := range slice { if item == element { return true } } return false } func Part1(input string) int { rules, updates := ParseInput(input) total := 0 for _, update := range updates { if ValidateUpdate(update, rules) { total += FindMiddle(update) } } return total } func Part2(input string) int { rules, updates := ParseInput(input) var invalidUpdates [][]int total := 0 for _, update := range updates { if !ValidateUpdate(update, rules) { invalidUpdates = append(invalidUpdates, update) } } for _, update := range invalidUpdates { sortedUpdate := SortUpdate(update, rules) total += FindMiddle(sortedUpdate) } return total }