Day05
This commit is contained in:
134
2024/gareth/day05/day05.go
Normal file
134
2024/gareth/day05/day05.go
Normal file
@@ -0,0 +1,134 @@
|
||||
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
|
||||
}
|
||||
71
2024/gareth/day05/day05_test.go
Normal file
71
2024/gareth/day05/day05_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package day05
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPart1(t *testing.T) {
|
||||
r := Part1(`47|53
|
||||
97|13
|
||||
97|61
|
||||
97|47
|
||||
75|29
|
||||
61|13
|
||||
75|53
|
||||
29|13
|
||||
97|29
|
||||
53|29
|
||||
61|53
|
||||
97|53
|
||||
61|29
|
||||
47|13
|
||||
75|47
|
||||
97|75
|
||||
47|61
|
||||
75|61
|
||||
47|29
|
||||
75|13
|
||||
53|13
|
||||
|
||||
75,47,61,53,29
|
||||
97,61,53,29,13
|
||||
75,29,13
|
||||
75,97,47,61,53
|
||||
61,13,29
|
||||
97,13,75,29,47`)
|
||||
assert.Equal(t, 143, r)
|
||||
}
|
||||
|
||||
func TestPart2(t *testing.T) {
|
||||
r := Part2(`47|53
|
||||
97|13
|
||||
97|61
|
||||
97|47
|
||||
75|29
|
||||
61|13
|
||||
75|53
|
||||
29|13
|
||||
97|29
|
||||
53|29
|
||||
61|53
|
||||
97|53
|
||||
61|29
|
||||
47|13
|
||||
75|47
|
||||
97|75
|
||||
47|61
|
||||
75|61
|
||||
47|29
|
||||
75|13
|
||||
53|13
|
||||
|
||||
75,47,61,53,29
|
||||
97,61,53,29,13
|
||||
75,29,13
|
||||
75,97,47,61,53
|
||||
61,13,29
|
||||
97,13,75,29,47`)
|
||||
assert.Equal(t, 123, r)
|
||||
}
|
||||
1377
2024/gareth/day05/input.txt
Normal file
1377
2024/gareth/day05/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"aoc2024/day03"
|
||||
"aoc2024/day05"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data, _ := os.ReadFile("day03/input.txt")
|
||||
fmt.Printf("part 1: %d\n", day03.Part1(string(data)))
|
||||
fmt.Printf("part 2: %d\n", day03.Part2(string(data)))
|
||||
data, _ := os.ReadFile("day05/input.txt")
|
||||
fmt.Printf("part 1: %d\n", day05.Part1(string(data)))
|
||||
fmt.Printf("part 2: %d\n", day05.Part2(string(data)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user