diff --git a/day5/.null-ls_704051_main.go b/day5/.null-ls_704051_main.go deleted file mode 100644 index d0ad98e..0000000 --- a/day5/.null-ls_704051_main.go +++ /dev/null @@ -1,194 +0,0 @@ -package main - -import ( - "fmt" - "slices" - "strconv" - "strings" - - "git.mstar.dev/mstar/aoc24/util" - "git.mstar.dev/mstar/goutils/other" - "git.mstar.dev/mstar/goutils/sliceutils" -) - -/* -Gameplan: -1. Einlesen als roh linien -2. Linien bis \n\n sind Regeln -3. Jede Linie danach muss den Regeln folgen -4. Regeln in zwei maps speichern - - 1. Map zuvor -> []danach: Jede nr hat eine Liste an nr, welche nach key kommen müssen - - 2. Map danach -> []zuvor: Jede nr hat eine liste an nr, welche vor key kommen müssen -5. -*/ - -type RulePair struct { - Left, Right int -} - -func parseRule(rule string) (int, int) { - tmp := strings.Split(rule, "|") - return other.Must(strconv.Atoi(tmp[0])), other.Must(strconv.Atoi(tmp[1])) -} - -func parseUpdate(line string) []int { - tmp := strings.Split(line, ",") - return sliceutils.Map(tmp, func(t string) int { return other.Must(strconv.Atoi(t)) }) -} - -func checkUpdateWithRules(rulesAfter, rulesBefore map[int][]int, update []int) bool { - for i, num := range update { - for _, elem := range update[:i] { - if sliceutils.Contains(rulesAfter[num], elem) { - // fmt.Printf("%v failed rule %d: %v\n", update, num, rulesAfter[num]) - return false - } - } - for _, elem := range update[i:] { - if sliceutils.Contains(rulesBefore[num], elem) { - // fmt.Printf("%v failed rule %d: %v\n", update, num, rulesBefore[num]) - return false - } - } - } - return true -} - -func getCenterVal(elems []int) int { - return elems[len(elems)/2] -} - -func sortByRules(nrsIn []int, rules []RulePair) []int { - nrsToUse := slices.Clone(nrsIn) - _ = nrsToUse - nrsOut := []int{} - sortedAfterRules := slices.Clone(rules) - slices.SortFunc( - rules, - func(a, b RulePair) int { return a.Left - b.Left }, - ) - for len(sortedAfterRules) != 0 { - popAt := []int{} - for i, rule := range sortedAfterRules { - if !sliceutils.Contains(nrsToUse, rule.Left) || - !sliceutils.Contains(nrsToUse, rule.Right) { - popAt = append(popAt, i) - } - } - } - - return nrsOut -} - -func findLowestIndex(inSlice, elems []int) int { - index := len(inSlice) - for _, elem := range elems { - i := slices.Index(inSlice, elem) - if i < index { - index = i - } - } - if index == len(inSlice) { - return -1 - } - return index -} - -func main() { - blocks := strings.Split(string(util.LoadFileFromArgs()), "\n\n") - ruleLines := sliceutils.Filter( - strings.Split(blocks[0], "\n"), - func(t string) bool { return len(t) != 0 }, - ) - applyLines := sliceutils.Filter( - strings.Split(blocks[1], "\n"), - func(t string) bool { return len(t) != 0 }, - ) - - rulesAfter := map[int][]int{} - rulesBefore := map[int][]int{} - rulePairs := []RulePair{} - - for _, rule := range ruleLines { - before, after := parseRule(rule) - rulesAfter[before] = append(rulesAfter[before], after) - rulesBefore[after] = append(rulesBefore[after], before) - rulePairs = append(rulePairs, RulePair{before, after}) - } - for k, nums := range rulesBefore { - slices.Sort(nums) - rulesBefore[k] = sliceutils.RemoveDuplicate(nums) - } - for k, nums := range rulesAfter { - slices.Sort(nums) - rulesAfter[k] = sliceutils.RemoveDuplicate(nums) - } - // fmt.Printf("Rules before a number: %v\nRules after a number: %v\n", rulesBefore, rulesAfter) - updates := sliceutils.Map(applyLines, func(t string) []int { return parseUpdate(t) }) - correctUpdates := [][]int{} - incorrectUpdates := [][]int{} - for _, update := range updates { - if checkUpdateWithRules(rulesAfter, rulesBefore, update) { - correctUpdates = append(correctUpdates, update) - } else { - incorrectUpdates = append(incorrectUpdates, update) - } - } - _ = incorrectUpdates - - acc := 0 - for _, elems := range correctUpdates { - acc += getCenterVal(elems) - } - fmt.Printf("Task 1: %d\n", acc) - // fmt.Printf("#rulesBefore: %d, #rulesAfter: %d\n", len(rulesBefore), len(rulesAfter)) - // allRuleNumbers := []int{} - // for k, _ := range rulesBefore { - // allRuleNumbers = append(allRuleNumbers, k) - // } - // for k, _ := range rulesAfter { - // allRuleNumbers = append(allRuleNumbers, k) - // } - // allRuleNumbers = sliceutils.RemoveDuplicate(allRuleNumbers) - // fmt.Printf("#allRuleNumbers: %d, allRuleNumbers: %v \n", len(allRuleNumbers), allRuleNumbers) - for i := range incorrectUpdates { - fmt.Printf("Checking invalid update %v\n", incorrectUpdates[i]) - for !checkUpdateWithRules(rulesAfter, rulesBefore, incorrectUpdates[i]) { - // Go over every element in the update - updateLoop: - for ie, elem := range incorrectUpdates[i] { - // Get all rules where the current number is on the right side of the rule (has to come after) - appliedRulesLeft := sliceutils.Filter(rulePairs, func(t RulePair) bool { - return elem == t.Right - }) - // Same but current number is on the left (has to come before) - appliedRulesRight := sliceutils.Filter(rulePairs, func(t RulePair) bool { - return elem == t.Left - }) - for _, rule := range appliedRulesLeft { - // If rule violation, swap the two elements - if il := slices.Index(incorrectUpdates[i][:ie], rule.Left); il != -1 { - fmt.Printf("Swapping according to rule %#v\n", rule) - incorrectUpdates[i][ie] = rule.Left - incorrectUpdates[i][il] = elem - break updateLoop - } - } - for _, rule := range appliedRulesRight { - if ir := slices.Index(incorrectUpdates[i][ie:], rule.Right); ir != -1 { - fmt.Printf("Swapping according to rule %#v\n", rule) - incorrectUpdates[i][ie] = rule.Right - incorrectUpdates[i][ir] = elem - break updateLoop - } - } - } - } - } - - acc = 0 - for _, elems := range incorrectUpdates { - acc += getCenterVal(elems) - } - fmt.Printf("Task 2: %d\n", acc) -}