day5
This commit is contained in:
148
2024/go/day05/day05.go
Normal file
148
2024/go/day05/day05.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package day05
|
||||||
|
|
||||||
|
import (
|
||||||
|
"adventofcode2024/utils"
|
||||||
|
_ "sort"
|
||||||
|
"strings"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Part1(input string) int {
|
||||||
|
num := 0
|
||||||
|
rules := make(map[int][]int)
|
||||||
|
|
||||||
|
sections := strings.Split(input, "\n\n")
|
||||||
|
rules_str := strings.Split(sections[0], "\n")
|
||||||
|
updates_str := strings.Split(sections[1], "\n")
|
||||||
|
updates := make([][]int, len(updates_str))
|
||||||
|
|
||||||
|
for _, rule := range rules_str {
|
||||||
|
fields := strings.Split(rule, "|")
|
||||||
|
// Convert the fields to integers
|
||||||
|
val1 := utils.MustAtoi(fields[0])
|
||||||
|
val2 := utils.MustAtoi(fields[1])
|
||||||
|
rules[val1] = append(rules[val1], val2)
|
||||||
|
}
|
||||||
|
for i, update := range updates_str {
|
||||||
|
fields := strings.Split(update, ",")
|
||||||
|
for _, field := range fields {
|
||||||
|
updates[i] = append(updates[i], utils.MustAtoi(field))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, update := range updates {
|
||||||
|
good := true
|
||||||
|
reverseSlice(update)
|
||||||
|
fmt.Printf("rules: %v\n", rules)
|
||||||
|
fmt.Printf("update: %v\n", update)
|
||||||
|
for i, page := range update {
|
||||||
|
for _, rule := range rules[page] {
|
||||||
|
if contains(update[i+1:], rule) {
|
||||||
|
good = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !good {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if good {
|
||||||
|
fmt.Printf("good: %v\n", update)
|
||||||
|
num += update[len(update)/2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
func Part2(input string) int {
|
||||||
|
num := 0
|
||||||
|
rules := make(map[int][]int)
|
||||||
|
|
||||||
|
sections := strings.Split(input, "\n\n")
|
||||||
|
rules_str := strings.Split(sections[0], "\n")
|
||||||
|
updates_str := strings.Split(sections[1], "\n")
|
||||||
|
updates := make([][]int, len(updates_str))
|
||||||
|
|
||||||
|
for _, rule := range rules_str {
|
||||||
|
fields := strings.Split(rule, "|")
|
||||||
|
// Convert the fields to integers
|
||||||
|
val1 := utils.MustAtoi(fields[0])
|
||||||
|
val2 := utils.MustAtoi(fields[1])
|
||||||
|
rules[val1] = append(rules[val1], val2)
|
||||||
|
}
|
||||||
|
for i, update := range updates_str {
|
||||||
|
fields := strings.Split(update, ",")
|
||||||
|
for _, field := range fields {
|
||||||
|
updates[i] = append(updates[i], utils.MustAtoi(field))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, update := range updates {
|
||||||
|
reverseSlice(update)
|
||||||
|
if !isGood(update, rules) {
|
||||||
|
fmt.Printf("not good: %v\n", update)
|
||||||
|
makeGood(update, rules)
|
||||||
|
fmt.Printf("good: %v\n", update)
|
||||||
|
num += update[len(update)/2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(slice []int, x int) bool {
|
||||||
|
for _, value := range slice {
|
||||||
|
if value == x {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func location(slice []int, x int) int {
|
||||||
|
for i, value := range slice {
|
||||||
|
if value == x {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func reverseSlice(slice []int) {
|
||||||
|
for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
slice[i], slice[j] = slice[j], slice[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGood(update []int, rules map[int][]int) bool {
|
||||||
|
good := true
|
||||||
|
for i, page := range update {
|
||||||
|
for _, rule := range rules[page] {
|
||||||
|
if contains(update[i+1:], rule) {
|
||||||
|
good = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !good {
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeGood(update []int, rules map[int][]int) []int {
|
||||||
|
for i, page := range update {
|
||||||
|
for _, rule := range rules[page] {
|
||||||
|
loc := location(update[i+1:], rule)
|
||||||
|
if loc != -1 {
|
||||||
|
swap(update, loc+i+1, i)
|
||||||
|
makeGood(update, rules)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return update
|
||||||
|
}
|
||||||
|
|
||||||
|
func swap(slice []int, i, j int) {
|
||||||
|
if i < 0 || i >= len(slice) || j < 0 || j >= len(slice) {
|
||||||
|
panic("Index out of range")
|
||||||
|
}
|
||||||
|
slice[i], slice[j] = slice[j], slice[i]
|
||||||
|
}
|
||||||
71
2024/go/day05/day05_test.go
Normal file
71
2024/go/day05/day05_test.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package day05
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
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`)
|
||||||
|
require.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`)
|
||||||
|
require.Equal(t, 123, r)
|
||||||
|
}
|
||||||
1362
2024/go/day05/input.txt
Normal file
1362
2024/go/day05/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,8 @@ import (
|
|||||||
"adventofcode2024/day01"
|
"adventofcode2024/day01"
|
||||||
"adventofcode2024/day02"
|
"adventofcode2024/day02"
|
||||||
"adventofcode2024/day03"
|
"adventofcode2024/day03"
|
||||||
"adventofcode2024/day04"
|
"adventofcode2024/day04"
|
||||||
|
"adventofcode2024/day05"
|
||||||
)
|
)
|
||||||
// Usage: go run main.go <NN>
|
// Usage: go run main.go <NN>
|
||||||
// assumes input is in day<NN>/input.txt
|
// assumes input is in day<NN>/input.txt
|
||||||
@@ -32,6 +32,9 @@ func main() {
|
|||||||
case 4:
|
case 4:
|
||||||
fmt.Printf("part 1: %d\n", day04.Part1(utils.Readfile(d)))
|
fmt.Printf("part 1: %d\n", day04.Part1(utils.Readfile(d)))
|
||||||
fmt.Printf("part 2: %d\n", day04.Part2(utils.Readfile(d)))
|
fmt.Printf("part 2: %d\n", day04.Part2(utils.Readfile(d)))
|
||||||
|
case 5:
|
||||||
|
fmt.Printf("part 1: %d\n", day05.Part1(utils.Readfile(d)))
|
||||||
|
fmt.Printf("part 2: %d\n", day05.Part2(utils.Readfile(d)))
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("no such day: %d", d))
|
panic(fmt.Errorf("no such day: %d", d))
|
||||||
}
|
}
|
||||||
@@ -39,7 +42,7 @@ func main() {
|
|||||||
|
|
||||||
// Reads day from os.Args.
|
// Reads day from os.Args.
|
||||||
func day() int {
|
func day() int {
|
||||||
latest := 3
|
latest := 4
|
||||||
if len(os.Args) == 1 {
|
if len(os.Args) == 1 {
|
||||||
return latest
|
return latest
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user