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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"aoc2024/day03"
|
"aoc2024/day05"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
data, _ := os.ReadFile("day03/input.txt")
|
data, _ := os.ReadFile("day05/input.txt")
|
||||||
fmt.Printf("part 1: %d\n", day03.Part1(string(data)))
|
fmt.Printf("part 1: %d\n", day05.Part1(string(data)))
|
||||||
fmt.Printf("part 2: %d\n", day03.Part2(string(data)))
|
fmt.Printf("part 2: %d\n", day05.Part2(string(data)))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user