Skip to content

Commit

Permalink
add day 5 solutions and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmckendry committed Dec 5, 2024
1 parent 7541e3b commit af9640a
Show file tree
Hide file tree
Showing 5 changed files with 1,679 additions and 0 deletions.
105 changes: 105 additions & 0 deletions 2024/05p1.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import "core:fmt"
import "core:strconv"
import "core:strings"

D05P1 :: proc() {
input_string := #load("inputs/05.txt", string)
lines := strings.split(input_string, "\n", context.temp_allocator)

sum_middle_page_numbers := get_sum_middle_page_numbers(lines)
fmt.printf("Sum of all correct middle page numbers: %d\n", sum_middle_page_numbers)
}

get_sum_middle_page_numbers :: proc(page_ordering_rules: []string) -> int {
sum := 0
rules, updates := parse_page_ordering_rules(page_ordering_rules)
defer {
for _, key in rules {
delete(key)
}
delete(rules)
for update in updates {
delete(update)
}
delete(updates)
}

valid_updates: [dynamic]int
defer delete(valid_updates)

for update, i in updates {
previous_pages: [dynamic]int
defer delete(previous_pages)
is_valid := true
for page in update {
// if any page in rules appears before the rule key, it is not valid
page_rules, ok := rules[page]
if !ok {
append(&previous_pages, page)
continue
}

for previous_page in previous_pages {
for rule in page_rules {
if rule == previous_page {
is_valid = false
break
}
}
}

append(&previous_pages, page)
}

if is_valid {
append(&valid_updates, i)
}
}

for idx in valid_updates {
// get the middle page number of all valid updates
sum += updates[idx][len(updates[idx]) / 2]
}

return sum
}

parse_page_ordering_rules :: proc(
lines: []string,
) -> (
rules: map[int][dynamic]int,
updates: [dynamic][dynamic]int,
) {
updates_start_at: int
for line, i in lines {
if line == "" {
updates_start_at = i + 1
break
}

parts := strings.split(line, "|", context.temp_allocator)
left := strconv.atoi(parts[0])
right := strconv.atoi(parts[1])

rule, ok := rules[left]
if !ok {
rule = [dynamic]int{}
}

append(&rule, right)
rules[left] = rule
}

for line in lines[updates_start_at:] {
parts := strings.split(line, ",", context.temp_allocator)
update := [dynamic]int{}
for part in parts {
append(&update, strconv.atoi(part))
}
append(&updates, update)
}

return
}
96 changes: 96 additions & 0 deletions 2024/05p2.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import "core:fmt"
import "core:strings"

D05P2 :: proc() {
input_string := #load("inputs/05.txt", string)
lines := strings.split(input_string, "\n", context.temp_allocator)

sum_middle_page_numbers := get_sum_middle_invalid_page_numbers(lines)
fmt.printf("Sum of all invalid middle page numbers: %d\n", sum_middle_page_numbers)
}

get_sum_middle_invalid_page_numbers :: proc(page_ordering_rules: []string) -> int {
sum := 0
rules, updates := parse_page_ordering_rules(page_ordering_rules)
defer {
for _, key in rules {
delete(key)
}
delete(rules)
for update in updates {
delete(update)
}
delete(updates)
}

invalid_updates: [dynamic]int
defer delete(invalid_updates)

for update, i in updates {
previous_pages: [dynamic]int
defer delete(previous_pages)
is_valid := true
for page in update {
// if any page in rules appears before the rule key, it is not valid
page_rules, ok := rules[page]
if !ok {
append(&previous_pages, page)
continue
}

for previous_page in previous_pages {
for rule in page_rules {
if rule == previous_page {
is_valid = false
break
}
}
}

append(&previous_pages, page)
}

if !is_valid {
append(&invalid_updates, i)
}
}

for update in invalid_updates {
reorderd_update := reorder_invalid_update(updates[update], &rules)
defer delete(reorderd_update)
sum += reorderd_update[len(reorderd_update) / 2]
}

return sum
}

reorder_invalid_update :: proc(
update: [dynamic]int,
rules: ^map[int][dynamic]int,
) -> [dynamic]int {
ordered: [dynamic]int

for page in update {
insert_position := len(ordered) // default to end of list

for ordered_page, i in ordered {
rules_for_page, has_rules := rules[page] // get rules for page

// if no rules, the page can be appended at the end
if has_rules {
for must_come_after in rules_for_page {
if must_come_after == ordered_page {
insert_position = min(i, insert_position)
break
}
}
}
}

inject_at(&ordered, insert_position, page)
}

return ordered
}
Loading

0 comments on commit af9640a

Please sign in to comment.