This commit is contained in:
itsscb 2024-12-17 21:16:49 +01:00
parent 37a8d26f7f
commit e955977bab
4 changed files with 1558 additions and 0 deletions

1364
src/day05/input.txt Normal file

File diff suppressed because it is too large Load Diff

178
src/day05/mod.rs Normal file
View File

@ -0,0 +1,178 @@
use std::{collections::HashMap, error::Error, fs};
/// Solves the problem for day 04.
///
/// # Errors
///
/// This function will return an error if the file cannot be read or if the input is invalid.
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
pub fn solve_day05(path: &str) -> Result<(i32, i32), Box<dyn Error>> {
let content = fs::read_to_string(path)?;
let (rules, updates) = parse_input(&content);
let ordered_updates = updates
.iter()
.map(|update| order_updates(update, &rules))
.collect::<Vec<_>>();
let result_one = updates
.iter()
.zip(ordered_updates.iter())
.filter(|(a, b)| a == b)
.map(|(a, _)| a.clone())
.collect::<Vec<_>>();
let result_two = updates
.iter()
.zip(ordered_updates.iter())
.filter(|(a, b)| a != b)
.map(|(_, b)| b.clone())
.collect::<Vec<_>>();
let part_one = sum_middle_value(&result_one);
let part_two = sum_middle_value(&result_two);
Ok((part_one, part_two))
}
fn parse_input(input: &str) -> (HashMap<i32, Vec<i32>>, Vec<Vec<i32>>) {
let parts: Vec<_> = input.split("\n\n").collect();
let mut map: HashMap<i32, Vec<i32>> = HashMap::new();
parts[0].split('\n').for_each(|r| {
let values = r
.split('|')
.map(|i| i.parse().unwrap())
.collect::<Vec<i32>>();
let index = values[0];
map.entry(index)
.or_default()
.append(values[1..].to_vec().as_mut());
});
// .collect();
let updates: Vec<Vec<i32>> = parts[1]
.split('\n')
.map(|r| r.split(',').map(|i| i.parse().unwrap()).collect())
.collect();
(map, updates)
}
fn order_updates(updates: &[i32], rules: &HashMap<i32, Vec<i32>>) -> Vec<i32> {
if !updates.iter().any(|u| rules.contains_key(u)) {
return updates.to_vec();
}
let mut ordered_updates: Vec<i32> = updates.to_vec();
ordered_updates.sort_by(|a, b| {
for (key, values) in rules {
if a == key && values.contains(b) {
return std::cmp::Ordering::Less;
// } else if b == key && values.contains(a) {
// return std::cmp::Ordering::Greater;
// } else if a < b {
// return std::cmp::Ordering::Less;
// } else if a > b {
// return std::cmp::Ordering::Greater;
}
}
std::cmp::Ordering::Equal
});
ordered_updates
}
fn sum_middle_value(input: &[Vec<i32>]) -> i32 {
input
.iter()
.filter_map(|row| {
if row.is_empty() || row.len() % 2 == 0 {
None
} else {
Some(row[row.len() / 2])
}
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_input() {
let input = "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
29,13,75
75,97,47,61,53
61,13,29
97,13,75,29,47";
let (rules, updates) = parse_input(input);
assert_eq!(rules.len(), 6);
assert_eq!(rules[&47], vec![53, 13, 61, 29]);
assert_eq!(rules[&53], vec![29, 13]);
assert_eq!(updates.len(), 6);
assert_eq!(updates[0], vec![75, 47, 61, 53, 29]);
let sum = sum_middle_value(&updates);
assert_eq!(sum, 61 + 53 + 13 + 47 + 13 + 75);
let want = vec![75, 29, 13];
let got = order_updates(&updates[2], &rules);
dbg!(&got, &updates[2]);
assert_eq!(got, want);
let want = vec![97, 75, 47, 61, 53];
let got = order_updates(&updates[3], &rules);
dbg!(&got, &updates[3]);
assert_eq!(got, want);
let want = vec![61, 29, 13];
let got = order_updates(&updates[4], &rules);
dbg!(&got, &updates[4]);
assert_eq!(got, want);
let want = vec![97, 75, 47, 29, 13];
let got = order_updates(&updates[5], &rules);
dbg!(&got, &want, &updates[5]);
assert_eq!(got, want);
let want = 61;
let got = sum_middle_value(&[order_updates(&updates[0], &rules)]);
assert_eq!(got, want);
let want = 143;
let got = sum_middle_value(
&updates
.iter()
.take(3)
.map(|u| order_updates(u, &rules))
.collect::<Vec<_>>(),
);
assert_eq!(got, want);
}
}

View File

@ -2,3 +2,4 @@ pub mod day01;
pub mod day02;
pub mod day03;
pub mod day04;
pub mod day05;

View File

@ -1,5 +1,6 @@
use adventofcode_24::{
day01::solve_day01, day02::solve_day02, day03::solve_day03, day04::solve_day04,
day05::solve_day05,
};
use clap::{Arg, Command};
@ -28,6 +29,11 @@ fn main() {
.short('4')
.help("Path to Day 04 Input file"),
)
.arg(
Arg::new("day05")
.short('5')
.help("Path to Day 05 Input file"),
)
.get_matches();
if let Some(file) = matches.get_one::<String>("day01") {
@ -67,4 +73,13 @@ fn main() {
Err(e) => eprintln!("{e}"),
}
}
if let Some(file) = matches.get_one::<String>("day05") {
match solve_day05(file) {
Ok((r1, r2)) => {
println!("Result of Day 05:\nOrdered middle page count: {r1}\nPart two: {r2}");
}
Err(e) => eprintln!("{e}"),
}
}
}