add day5
This commit is contained in:
1362
day5/data.txt
Normal file
1362
day5/data.txt
Normal file
File diff suppressed because it is too large
Load Diff
100
day5/findvalid.go
Normal file
100
day5/findvalid.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func check(e error) {
|
||||||
|
if e != nil { panic(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(slice []int, element int) bool {
|
||||||
|
for _, value := range slice {
|
||||||
|
if value == element {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_prerequisites(rules [][2]int, target int) []int {
|
||||||
|
out := make([]int, 0, 10)
|
||||||
|
|
||||||
|
// find rules
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule[1] == target && !contains(out, rule[0]) {
|
||||||
|
out = append(out, rule[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
dat, err := os.ReadFile("data.txt")
|
||||||
|
check(err)
|
||||||
|
dat_str := string(dat[:len(dat) - 1])
|
||||||
|
|
||||||
|
|
||||||
|
blocks := strings.Split(dat_str, "\n\n")
|
||||||
|
|
||||||
|
rules := make([][2]int, 0, 1000)
|
||||||
|
for _, rule := range strings.Split(blocks[0], "\n") {
|
||||||
|
str_rules := strings.Split(rule, "|")
|
||||||
|
|
||||||
|
num1, err := strconv.Atoi(str_rules[0])
|
||||||
|
check(err)
|
||||||
|
num2, err := strconv.Atoi(str_rules[1])
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
rules = append(rules, [2]int{ num1, num2 })
|
||||||
|
}
|
||||||
|
|
||||||
|
orderings := make([][]int, 0, 1000)
|
||||||
|
for _, line := range strings.Split(blocks[1], "\n") {
|
||||||
|
str_orderings := strings.Split(line, ",")
|
||||||
|
|
||||||
|
elements := make([]int, 0, len(str_orderings))
|
||||||
|
for _, elem := range str_orderings {
|
||||||
|
num, err := strconv.Atoi(elem)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
elements = append(elements, num)
|
||||||
|
}
|
||||||
|
|
||||||
|
orderings = append(orderings, elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check orderings
|
||||||
|
acc := 0
|
||||||
|
var pre []int
|
||||||
|
for _, ordering := range orderings {
|
||||||
|
|
||||||
|
// check single line
|
||||||
|
valid := true
|
||||||
|
for i := len(ordering) - 1; i >= 0; i-- {
|
||||||
|
pre = get_prerequisites(rules, ordering[i])
|
||||||
|
|
||||||
|
for _, p := range pre {
|
||||||
|
if contains(ordering, p) {
|
||||||
|
if !contains(ordering[:i], p) {
|
||||||
|
valid = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !valid { break }
|
||||||
|
}
|
||||||
|
|
||||||
|
// add middle elem to acc
|
||||||
|
if valid {
|
||||||
|
acc += ordering[len(ordering)/2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(acc)
|
||||||
|
}
|
||||||
150
day5/reorder.go
Normal file
150
day5/reorder.go
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func check(e error) {
|
||||||
|
if e != nil { panic(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(slice []int, element int) bool {
|
||||||
|
for _, value := range slice {
|
||||||
|
if value == element {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func index(slice []int, element int) int {
|
||||||
|
for i, value := range slice {
|
||||||
|
if value == element {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse_rules(text string) [][2]int {
|
||||||
|
lines := strings.Split(text, "\n")
|
||||||
|
rules := make([][2]int, 0, len(lines))
|
||||||
|
|
||||||
|
for _, rule := range lines {
|
||||||
|
str_rules := strings.Split(rule, "|")
|
||||||
|
|
||||||
|
num1, err := strconv.Atoi(str_rules[0])
|
||||||
|
check(err)
|
||||||
|
num2, err := strconv.Atoi(str_rules[1])
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
rules = append(rules, [2]int{ num1, num2 })
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse_page_numbers(text string) [][]int {
|
||||||
|
lines := strings.Split(text, "\n")
|
||||||
|
page_numbers := make([][]int, 0, len(lines))
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
str_page_numbers := strings.Split(line, ",")
|
||||||
|
|
||||||
|
elements := make([]int, 0, len(str_page_numbers))
|
||||||
|
for _, elem := range str_page_numbers {
|
||||||
|
num, err := strconv.Atoi(elem)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
elements = append(elements, num)
|
||||||
|
}
|
||||||
|
|
||||||
|
page_numbers = append(page_numbers, elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
return page_numbers
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_prerequisites(rules [][2]int, target int) []int {
|
||||||
|
out := make([]int, 0, 10)
|
||||||
|
|
||||||
|
// find rules
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule[1] == target && !contains(out, rule[0]) {
|
||||||
|
out = append(out, rule[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func is_valid(numbering []int, rules [][2]int) bool {
|
||||||
|
// iterate over numbering
|
||||||
|
for i := len(numbering) - 1; i >= 0; i-- {
|
||||||
|
// iterate of dependencies for the current char
|
||||||
|
for _, p := range get_prerequisites(rules, numbering[i]) {
|
||||||
|
// check rule
|
||||||
|
idx := index(numbering, p)
|
||||||
|
if idx > i {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func correct_page_numbering(numbering []int, rules [][2]int) []int {
|
||||||
|
for !is_valid(numbering, rules) {
|
||||||
|
// check for every rule
|
||||||
|
for _, rule := range rules {
|
||||||
|
// if applies
|
||||||
|
i := index(numbering, rule[0])
|
||||||
|
j := index(numbering, rule[1])
|
||||||
|
if i >= 0 && j >= 0 {
|
||||||
|
// swap page numbers if needed
|
||||||
|
if i > j {
|
||||||
|
temp := numbering[i]
|
||||||
|
numbering[i] = numbering[j]
|
||||||
|
numbering[j] = temp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numbering
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// get input from file
|
||||||
|
dat, err := os.ReadFile("data.txt")
|
||||||
|
check(err)
|
||||||
|
dat_str := string(dat[:len(dat) - 1])
|
||||||
|
|
||||||
|
// parse rules and page numbers
|
||||||
|
blocks := strings.Split(dat_str, "\n\n")
|
||||||
|
rules := parse_rules(blocks[0])
|
||||||
|
page_numbers := parse_page_numbers(blocks[1])
|
||||||
|
|
||||||
|
|
||||||
|
// collect invalid page numberings
|
||||||
|
invalid_page_numbers := make([][]int, 0, len(page_numbers)/2)
|
||||||
|
|
||||||
|
for _, single_page_numbering := range page_numbers {
|
||||||
|
if !is_valid(single_page_numbering, rules) {
|
||||||
|
invalid_page_numbers = append(invalid_page_numbers, single_page_numbering)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// correct page numberings
|
||||||
|
acc := 0
|
||||||
|
var correct []int
|
||||||
|
|
||||||
|
for _, p := range invalid_page_numbers {
|
||||||
|
correct = correct_page_numbering(p, rules)
|
||||||
|
acc += correct[len(correct)/2]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(acc)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user