day05
This commit is contained in:
parent
37a8d26f7f
commit
e955977bab
1364
src/day05/input.txt
Normal file
1364
src/day05/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
178
src/day05/mod.rs
Normal file
178
src/day05/mod.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -2,3 +2,4 @@ pub mod day01;
|
|||||||
pub mod day02;
|
pub mod day02;
|
||||||
pub mod day03;
|
pub mod day03;
|
||||||
pub mod day04;
|
pub mod day04;
|
||||||
|
pub mod day05;
|
||||||
|
15
src/main.rs
15
src/main.rs
@ -1,5 +1,6 @@
|
|||||||
use adventofcode_24::{
|
use adventofcode_24::{
|
||||||
day01::solve_day01, day02::solve_day02, day03::solve_day03, day04::solve_day04,
|
day01::solve_day01, day02::solve_day02, day03::solve_day03, day04::solve_day04,
|
||||||
|
day05::solve_day05,
|
||||||
};
|
};
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
|
|
||||||
@ -28,6 +29,11 @@ fn main() {
|
|||||||
.short('4')
|
.short('4')
|
||||||
.help("Path to Day 04 Input file"),
|
.help("Path to Day 04 Input file"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("day05")
|
||||||
|
.short('5')
|
||||||
|
.help("Path to Day 05 Input file"),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
if let Some(file) = matches.get_one::<String>("day01") {
|
if let Some(file) = matches.get_one::<String>("day01") {
|
||||||
@ -67,4 +73,13 @@ fn main() {
|
|||||||
Err(e) => eprintln!("{e}"),
|
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}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user