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) }