summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2024/05/rust/src/main.rs93
1 files changed, 25 insertions, 68 deletions
diff --git a/2024/05/rust/src/main.rs b/2024/05/rust/src/main.rs
index bf72727..387b301 100644
--- a/2024/05/rust/src/main.rs
+++ b/2024/05/rust/src/main.rs
@@ -1,87 +1,44 @@
#![feature(slice_split_once)]
use std::cmp::Ordering;
-use std::collections::HashMap;
+use std::collections::BinaryHeap;
use std::io;
fn main() -> io::Result<()> {
- let lines = io::stdin().lines().flatten().collect::<Vec<_>>();
- let (rules, updates) = lines.split_once(String::is_empty).unwrap();
- let manual = rules.iter().collect::<Manual>();
+ let mut lines = io::stdin().lines().flatten();
+ let mut heap = BinaryHeap::<(u16, u16)>::new();
- let updates = updates
- .iter()
- .map(|up| {
- up.split(',')
- .map(|p| Page {
- number: p.parse::<u64>().unwrap(),
- manual: &manual,
- })
- .collect::<_>()
- })
- .collect::<Vec<Vec<_>>>();
-
- let mut silver = 0;
- let mut gold = 0;
- for mut up in updates {
- let mid = up.len() / 2;
- if up.is_sorted() {
- silver += up[mid].number;
+ while let Some(s) = lines.next() {
+ if let Some((a, b)) = s.split_once('|') {
+ heap.push((a.parse().unwrap(), b.parse().unwrap()));
} else {
- up.sort_unstable();
- gold += up[mid].number;
+ break;
}
}
+ let order = heap.into_sorted_vec();
- println!("silver: {silver}");
- println!("gold: {gold}");
-
- return Ok(());
-}
-#[derive(Debug)]
-struct Manual {
- order: HashMap<u64, Vec<u64>>,
-}
-
-impl<'a> FromIterator<&'a String> for Manual {
- fn from_iter<T: IntoIterator<Item = &'a String>>(rules: T) -> Self {
- let mut order = HashMap::<u64, Vec<u64>>::new();
- for rule in rules {
- let (pre, post) = rule.split_once('|').unwrap();
- order
- .entry(pre.parse().unwrap())
- .or_default()
- .push(post.parse().unwrap());
- }
- Manual { order }
- }
-}
+ let mut silver = 0;
+ let mut gold = 0;
-#[derive(Clone, Copy)]
-struct Page<'a> {
- number: u64,
- manual: &'a Manual,
-}
+ for line in lines {
+ let mut nums: Vec<u16> = line.split(',').map(|n| n.parse().unwrap()).collect();
+ let presort = nums.clone();
+ let mid = nums.len() / 2;
-impl PartialEq for Page<'_> {
- fn eq(&self, other: &Self) -> bool {
- self.number == other.number
- }
-}
-impl Eq for Page<'_> {}
+ nums.sort_unstable_by(|&a, &b| match order.binary_search(&(a, b)) {
+ Ok(_) => Ordering::Less,
+ Err(_) => Ordering::Greater,
+ });
-impl PartialOrd for Page<'_> {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- if self.manual.order.get(&self.number)?.contains(&other.number) {
- Some(Ordering::Less)
+ if nums.iter().eq(presort.iter()) {
+ silver += presort[mid];
} else {
- Some(Ordering::Greater)
+ gold += nums[mid];
}
}
-}
-impl Ord for Page<'_> {
- fn cmp(&self, other: &Self) -> Ordering {
- self.partial_cmp(other).unwrap()
- }
+ println!("silver: {silver}");
+ println!("gold: {gold}");
+
+ return Ok(());
}