--- /dev/null
+use std::{io::BufRead, mem::swap};
+
+use itertools::{self, Itertools};
+
+use crate::utils;
+
+#[derive(Debug)]
+pub struct PageOrdering {
+ ordering: [Vec<i32>; 100],
+}
+
+impl PageOrdering {
+ pub fn new() -> PageOrdering {
+ PageOrdering {
+ ordering: [const { vec![] }; 100],
+ }
+ }
+
+ pub fn add_page_order(&mut self, p1: i32, p2: i32) {
+ let following_page = self.ordering.get_mut(p1 as usize).unwrap();
+ if !following_page.contains(&p2) {
+ following_page.push(p2);
+ }
+ }
+
+ pub fn get_followin_page(&self, p: i32) -> &[i32] {
+ &self.ordering[p as usize]
+ }
+}
+
+type Updates = Vec<Vec<i32>>;
+
+pub fn read_ordering_and_updates<R>(reader: R) -> (PageOrdering, Updates)
+where
+ R: BufRead,
+{
+ let lines = reader.lines().map(Result::unwrap).collect::<Vec<String>>();
+ let mut lines_iter = lines.iter();
+
+ let mut page_ordering = PageOrdering::new();
+ while let Some(l) = lines_iter.next() {
+ if l.is_empty() {
+ break;
+ }
+ let pages = utils::split_to_vec(&l, "|");
+ page_ordering.add_page_order(pages[0], pages[1]);
+ }
+
+ let mut updates: Vec<Vec<i32>> = vec![];
+ while let Some(l) = lines_iter.next() {
+ updates.push(utils::split_to_vec(&l, ","));
+ }
+
+ (page_ordering, updates)
+}
+
+pub fn sum_of_mid_page_from_valid_updates(page_ordering: &PageOrdering, updates: &Updates) -> i32 {
+ let mut sum = 0;
+ 'next_update: for update in updates {
+ for (p1, p2) in update.iter().tuple_windows() {
+ if !page_ordering.get_followin_page(*p1).contains(p2) {
+ continue 'next_update;
+ }
+ }
+ sum += update[update.len() / 2];
+ }
+
+ sum
+}
+
+pub fn sum_of_mid_page_from_corrected_updates(
+ page_ordering: &PageOrdering,
+ updates: &Updates,
+) -> i32 {
+ let mut sum = 0;
+ for update in updates {
+ let l = update.len();
+ let mut updates_corrected = update.clone();
+ let mut modified = false;
+ let mut i = 0;
+ while i < l - 1 {
+ if !page_ordering
+ .get_followin_page(updates_corrected[i])
+ .contains(&updates_corrected[i + 1])
+ {
+ updates_corrected.swap(i, i + 1);
+ modified = true;
+ if i > 0 {
+ i -= 1;
+ }
+ } else {
+ i += 1;
+ }
+ }
+ if modified {
+ sum += updates_corrected[update.len() / 2];
+ }
+ }
+
+ sum
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ static PAGE_ORDERING_AND_UPDATES: &str = "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";
+
+ #[test]
+ fn test_part1() {
+ let (ordering, updates) = read_ordering_and_updates(PAGE_ORDERING_AND_UPDATES.as_bytes());
+ let s = sum_of_mid_page_from_valid_updates(&ordering, &updates);
+ assert_eq!(s, 143);
+ }
+
+ #[test]
+ fn test_part2() {
+ let (ordering, updates) = read_ordering_and_updates(PAGE_ORDERING_AND_UPDATES.as_bytes());
+ let s = sum_of_mid_page_from_corrected_updates(&ordering, &updates);
+ assert_eq!(s, 123);
+ }
+}
day04::nb_of_mas_cross(&word_search)
)
}
+
+pub fn day05() -> String {
+ let f = fs::File::open("data/day05.input").unwrap();
+ let (ordering, updates) = day05::read_ordering_and_updates(BufReader::new(f));
+ format!(
+ "part1: {}, part2: {}",
+ day05::sum_of_mid_page_from_valid_updates(&ordering, &updates),
+ day05::sum_of_mid_page_from_corrected_updates(&ordering, &updates)
+ )
+}