adventofcode/2024/day05/main.go

169 lines
3.0 KiB
Go

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
}