package main import ( "errors" "fmt" "strings" helpers "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := helpers.StdinToStringSlice() part1(inp) fmt.Println() part2(inp) } func part1(inp []string) { rules, updates := processInput(inp) var result int for i := range updates { if rules.Validate(updates[i]) { result = result + updates[i][len(updates[i])/2] } } fmt.Println("# Part 1") fmt.Printf("Valid Updates: %d\n", result) } func part2(inp []string) { rules, updates := processInput(inp) var result int for i := range updates { var iter int var wasIncorrect bool for !rules.Validate(updates[i]) { if iter > 100 { panic(errors.New("Naive correction won't work...")) } updates[i] = rules.Correct(updates[i]) iter++ wasIncorrect = true } if wasIncorrect { result = result + updates[i][len(updates[i])/2] } } fmt.Println("# Part 2") fmt.Printf("Corrected Updates: %d\n", result) } func processInput(inp []string) (*PageOrderingRules, [][]int) { var rawRules []string var strUpdates []string var inRules bool inRules = true for i := range inp { if inp[i] == "" { inRules = false continue } if inRules { rawRules = append(rawRules, inp[i]) } else { strUpdates = append(strUpdates, inp[i]) } } var updates [][]int rules := PageOrderingRules{Rules: parseOrderingRules(rawRules)} for i := range strUpdates { updates = append(updates, parseUpdate(strUpdates[i])) } return &rules, updates } type PageOrderingRules struct { Rules []Rule } func (p *PageOrderingRules) Correct(update []int) []int { if p.Validate(update) { return update } for i := range p.Rules { update = p.Rules[i].Correct(update) } return update } func (p *PageOrderingRules) Validate(update []int) bool { for i := range p.Rules { if !p.Rules[i].Validates(update) { return false } } return true } func (p PageOrderingRules) String() string { var ret string for i := range p.Rules { ret = fmt.Sprintf("%s%s\n", ret, p.Rules[i]) } return ret } type Rule struct { first, second int } func (r *Rule) Validates(update []int) bool { for i := range update { if update[i] == r.first { for j := range update { if update[j] == r.second { return i < j } } } } return true } func (r *Rule) Correct(update []int) []int { if r.Validates(update) { return update } var idx, jdx int for i := range update { if update[i] == r.first { idx = i } if update[i] == r.second { jdx = i } } update[idx], update[jdx] = update[jdx], update[idx] return update } func (r Rule) String() string { return fmt.Sprintf("%d|%d", r.first, r.second) } func parseOrderingRules(inp []string) []Rule { var ret []Rule for i := range inp { if inp[i] == "" { return ret } rule := Rule{} fmt.Sscanf(inp[i], "%d|%d", &rule.first, &rule.second) ret = append(ret, rule) } return ret } func parseUpdate(inp string) []int { var ret []int pts := strings.Split(inp, ",") for i := range pts { var wrk int fmt.Sscanf(pts[i], "%d", &wrk) ret = append(ret, wrk) } return ret }