From 54591fadd85fa998f4a88b4bf21f8ff942c78be3 Mon Sep 17 00:00:00 2001 From: Russell Champoux Date: Tue, 17 Dec 2024 19:15:55 +0000 Subject: [PATCH] day 5 pt2 --- README.md | 4 +-- src/bin/05.rs | 83 ++++++++++++++++++++++++++++----------------------- src/bin/17.rs | 5 ++-- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index a1a0e02..b2725c6 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | [Day 2](./src/bin/02.rs) | `190.5µs` | `487.3µs` | | [Day 3](./src/bin/03.rs) | `524.3µs` | `678.5µs` | | [Day 4](./src/bin/04.rs) | `3.7ms` | `495.5µs` | -| [Day 5](./src/bin/05.rs) | `43.2ms` | `-` | +| [Day 5](./src/bin/05.rs) | `4.9ms` | `190.3ms` | | [Day 6](./src/bin/06.rs) | `59.8µs` | `-` | | [Day 7](./src/bin/07.rs) | `11.9ms` | `-` | | [Day 8](./src/bin/08.rs) | `106.2µs` | `-` | @@ -50,7 +50,7 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | [Day 15](./src/bin/15.rs) | `265.0µs` | `-` | | [Day 16](./src/bin/16.rs) | `38.0ms` | `-` | -**Total: 2019.40ms** +**Total: 2171.40ms** --- diff --git a/src/bin/05.rs b/src/bin/05.rs index 5c32949..8657727 100644 --- a/src/bin/05.rs +++ b/src/bin/05.rs @@ -1,11 +1,16 @@ // use itertools::Itertools; +use itertools::Itertools; + advent_of_code::solution!(5); pub fn part_one(input: &str) -> Option { // Parse the rules let mut reader = input.lines(); - let rules: Vec<_> = reader.by_ref().take_while(|l| !l.is_empty()).map(|r| r.split('|').collect::>()).collect(); + let rules = reader.by_ref().take_while(|l| !l.is_empty()).map(|r| { + let pages = r.split('|').collect_vec(); + (pages[0].parse::().unwrap(), pages[1].parse::().unwrap()) + }).collect_vec(); // println!("{} lines", rules.len()); @@ -15,13 +20,13 @@ pub fn part_one(input: &str) -> Option { // Check each book against all the rules let mut valid_books_count = 0; let total = books.fold(0, |t, book| { - let pages = book.collect::>(); + let pages = book.map(|s| s.parse::().unwrap()).collect_vec(); let is_valid = get_is_valid(&rules, &pages); if is_valid { let middle = pages.len() / 2; - let middle_val = pages[middle].parse::().unwrap(); + let middle_val = pages[middle]; // println!("{middle_val}"); valid_books_count += 1; @@ -35,14 +40,14 @@ pub fn part_one(input: &str) -> Option { Some(total) } -#[allow(unreachable_code)] pub fn part_two(_input: &str) -> Option { - // TODO: Fix this - return None; // Parse the rules let mut reader = _input.lines(); - let rules: Vec<_> = reader.by_ref().take_while(|l| !l.is_empty()).map(|r| r.split('|').collect::>()).collect(); + let rules = reader.by_ref().take_while(|l| !l.is_empty()).map(|r| { + let pages = r.split('|').collect_vec(); + (pages[0].parse::().unwrap(), pages[1].parse::().unwrap()) + }).collect_vec(); // println!("{} lines", rules.len()); @@ -52,7 +57,7 @@ pub fn part_two(_input: &str) -> Option { // Check each book against all the rules let mut valid_books_count = 0; let total = books.fold(0, |t, book| { - let pages = book.collect::>(); + let pages = book.map(|s| s.parse::().unwrap()).collect_vec(); let is_valid = get_is_valid(&rules, &pages); if is_valid { @@ -62,12 +67,12 @@ pub fn part_two(_input: &str) -> Option { // build up a book one page at a time (starting with 2 pages) and // println!("Checking {} permutations of {:?}", factorial(pages.len()).unwrap(), pages); - let valid_pages = find_valid_book(&rules, Vec::from([]), pages).unwrap(); + let valid_pages = order_book(&rules, pages); // println!("Valid pages {:?}", valid_pages); let middle = valid_pages.len() / 2; - let middle_val = valid_pages[middle].parse::().unwrap(); + let middle_val = valid_pages[middle]; // println!("{middle_val}"); valid_books_count += 1; @@ -79,45 +84,49 @@ pub fn part_two(_input: &str) -> Option { Some(total) } -fn get_is_valid(rules: &[Vec<&str>], pages: &[&str]) -> bool { - for (page_a_idx, page_a) in pages.iter().enumerate() { - for page_b in &pages[page_a_idx..] { +fn get_is_valid(rules: &[(u32, u32)], pages: &[u32]) -> bool { + pages.iter().combinations(2).all(|pages| { // check for a violation of the rules! - let is_invalid = rules.iter().any(|r| r[0] == *page_b && r[1] == *page_a); - if is_invalid { return false } - } - } - true + !rules.iter().any(|r| r.0 == *pages[1] && r.1 == *pages[0]) + }) } -fn find_valid_book<'a>(rules: &Vec>, pages: Vec<&'a str>, remaining_pages: Vec<&'a str>) -> Option> { - // println!("Checking {:?}", pages); +fn order_book(rules: &[(u32, u32)], pages: Vec) -> Vec { + let mut ordered_pages = vec![]; - let is_valid = get_is_valid(rules, &pages); - - if remaining_pages.is_empty() && is_valid { - - return Some(pages) + 'page: for p in pages { + for idx in 0..=ordered_pages.len() { + let mut new_pages = ordered_pages.clone(); + new_pages.insert(idx, p); + if get_is_valid(rules, new_pages.as_slice()) { + ordered_pages.insert(idx, p); + continue 'page; + } else if idx == ordered_pages.len() { + panic!(); + } + } } - if !is_valid { - // println!("INVALID! {:?} - Eliminating {} additional permutations", pages, factorial(remaining_pages.len()).unwrap()); - return None - } // trim this branch - - remaining_pages.iter().find_map(|rp| { - let mut next_pages = pages.clone(); - next_pages.push(rp); - let next_remaining_pages = remaining_pages.iter().cloned().filter(|p| p != rp).collect(); - - find_valid_book(rules, next_pages, next_remaining_pages) - }) + ordered_pages } #[cfg(test)] mod tests { use super::*; + #[test] + fn test_combinations() { + let result = (1..=4).combinations(2); + itertools::assert_equal(result, vec![ + vec![1, 2], + vec![1, 3], + vec![1, 4], + vec![2, 3], + vec![2, 4], + vec![3, 4], + ]); + } + #[test] fn test_part_one() { let result = part_one(&advent_of_code::template::read_file("examples", DAY)); diff --git a/src/bin/17.rs b/src/bin/17.rs index c1c5a3c..13a0b00 100644 --- a/src/bin/17.rs +++ b/src/bin/17.rs @@ -61,7 +61,7 @@ pub fn part_two(_input: &str) -> Option { None } -fn run_program(registers: &mut Vec, program: Vec) -> Vec { +fn run_program(registers: &mut [usize], program: Vec) -> Vec { let mut output: Vec = vec![]; let literal = |v: usize| v; @@ -183,9 +183,10 @@ mod tests { assert_eq!(result, Some("4,6,3,5,6,3,5,2,1,0".to_string())); } + #[ignore] #[test] fn test_part_two() { let result = part_two(&advent_of_code::template::read_file("examples", DAY)); - assert_eq!(result, None); + assert_eq!(result, Some(117440)); } }