From 24ba3836dcbda0cb29edc20630233cf279963989 Mon Sep 17 00:00:00 2001 From: red Date: Sun, 24 Mar 2024 22:25:11 +0100 Subject: [PATCH] Improvement: Small changes --- src/bfs.rs | 2 +- src/common.rs | 2 +- src/year_2015/day_13.rs | 10 +-- src/year_2016/day_14.rs | 158 ++++++++++++++++++++-------------------- src/year_2016/day_24.rs | 11 +-- 5 files changed, 94 insertions(+), 89 deletions(-) diff --git a/src/bfs.rs b/src/bfs.rs index e2ac2ff..46e94c6 100644 --- a/src/bfs.rs +++ b/src/bfs.rs @@ -62,7 +62,7 @@ where } pub fn shortest_path_to(&mut self, target_position: POS) -> usize { - self.traverse_until_position(target_position.clone()); + self.traverse_until_position(target_position); self.depth } diff --git a/src/common.rs b/src/common.rs index 98b8c42..7fe4d9e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -24,7 +24,7 @@ mod tests { #[test] fn fetch_input_from_inexisting_file() { let path: Option = Some("foo.txt".into()); - let error = fetch_input(path.clone()).unwrap_err(); + let error = fetch_input(path).unwrap_err(); assert_eq!(error.kind(), ErrorKind::NotFound); } } diff --git a/src/year_2015/day_13.rs b/src/year_2015/day_13.rs index ec611c3..db7b259 100644 --- a/src/year_2015/day_13.rs +++ b/src/year_2015/day_13.rs @@ -60,8 +60,8 @@ fn parse_input(input: &str) -> (Vec, HashMap<(u8, u8), i16>) { (users_ids, paths) } -fn remove_user_id_from_vec(users: Vec, needle: &u8) -> Vec { - let mut new_vec = users.clone(); +fn remove_user_id_from_vec(users: &[u8], needle: &u8) -> Vec { + let mut new_vec = users.to_owned(); new_vec.retain(|elt| elt != needle); new_vec } @@ -87,7 +87,7 @@ fn calculate_happiness( } let mut best_happiness = 0; for user_id in friends_left.iter() { - let friends_left = remove_user_id_from_vec(friends_left.clone(), user_id); + let friends_left = remove_user_id_from_vec(&friends_left, user_id); let add_hap = cur_hap + get_happiness(paths, current_friend, user_id); let nex_hap = calculate_happiness(paths, user_id, friends_left, add_hap); best_happiness = std::cmp::max(best_happiness, nex_hap); @@ -97,7 +97,7 @@ fn calculate_happiness( pub fn day_13_v1(input: impl Into) -> i16 { let (users_ids, paths) = parse_input(&input.into()); - let friends_left = remove_user_id_from_vec(users_ids.clone(), &0); + let friends_left = remove_user_id_from_vec(&users_ids, &0); calculate_happiness(&paths, &0, friends_left, 0) } @@ -108,7 +108,7 @@ pub fn day_13_v2(input: impl Into) -> i16 { paths.insert((lhp, my_user_id), 0); } users_ids.push(my_user_id); - let friends_left = remove_user_id_from_vec(users_ids.clone(), &0); + let friends_left = remove_user_id_from_vec(&users_ids, &0); calculate_happiness(&paths, &0, friends_left, 0) } diff --git a/src/year_2016/day_14.rs b/src/year_2016/day_14.rs index e5abd56..93279b6 100644 --- a/src/year_2016/day_14.rs +++ b/src/year_2016/day_14.rs @@ -3,46 +3,30 @@ use std::collections::VecDeque; use itertools::Itertools; use md5::{digest::core_api::CoreWrapper, Digest, Md5, Md5Core}; -fn multi_hash(input: &str) -> String { +#[inline] +fn multi_hash(hasher_base: &CoreWrapper, input: &str) -> String { let mut digest: String = input.to_string(); for _ in 1..=2016 { - let mut hasher = Md5::new(); + let mut hasher = hasher_base.clone(); hasher.update(digest); digest = format!("{:x}", hasher.finalize()); } digest } -fn generate_hashes_v2( - hasher: CoreWrapper, - starter: usize, - ending: usize, -) -> VecDeque { - let mut hashes: Vec = Vec::new(); - for idx in starter..=ending { - let mut hasher_num = hasher.clone(); - hasher_num.update(&idx.to_string()); - hashes.push(multi_hash(&format!("{:x}", hasher_num.finalize()))); +fn fill_hashes_v2(md5: &CoreWrapper, start: usize, end: usize) -> VecDeque { + let mut hashes: VecDeque = VecDeque::new(); + for idx in start..=end { + let mut md5_num = md5.clone(); + md5_num.update(&idx.to_string()); + let md5_str = Md5::new(); + hashes.push_back(multi_hash(&md5_str, &format!("{:x}", md5_num.finalize()))); } - VecDeque::from(hashes) -} - -fn generate_hashes( - hasher: CoreWrapper, - starter: usize, - ending: usize, -) -> VecDeque { - let mut hashes: Vec = Vec::new(); - for idx in starter..=ending { - let mut hasher_num = hasher.clone(); - hasher_num.update(&idx.to_string()); - hashes.push(format!("{:x}", hasher_num.finalize())); - } - - VecDeque::from(hashes) + hashes } +#[inline] fn build_hasher(input: &str) -> CoreWrapper { let mut hasher = Md5::new(); let data = input; @@ -59,7 +43,7 @@ fn find_triplet(input: &str) -> Option { .map(|letters| letters[0]) } -fn got_quintuplet(input: &str, needle: char) -> bool { +fn quintuplet(input: &str, needle: char) -> bool { input.chars().collect_vec().windows(5).any(|letters| { letters[0] == needle && letters[1] == needle @@ -69,74 +53,94 @@ fn got_quintuplet(input: &str, needle: char) -> bool { }) } +#[inline] +fn chr_to_chars(chr: &u8) -> [u8; 2] { + [ + (chr & 0xF0) >> 4, + chr & 0x0F, + ] +} + +fn find_triplet_u8(input: &[u8]) -> Option { + input + .iter() + .flat_map(chr_to_chars) + .collect_vec() + .windows(3) + .find(|chars| chars[0] == chars[1] && chars[0] == chars[2]) + .map(|chars| chars[0]) +} + +fn got_quintuplet_u8(input: &[u8], needle: u8) -> bool { + input + .iter() + .flat_map(chr_to_chars) + .collect_vec() + .windows(5) + .any(|chars| chars.iter().all(|chr| *chr == needle)) +} + +fn fill_hashes(md5: &CoreWrapper, counter: usize, hashes: usize) -> VecDeque> { + let start = counter + 1 + hashes; + let end = start + (counter + 1000) - hashes; + let mut hashes: VecDeque> = VecDeque::new(); + for idx in start..=end { + let mut md5_num = md5.clone(); + md5_num.update(&idx.to_string()); + hashes.push_back(md5_num.finalize().to_vec()); + } + + hashes +} + pub fn day_14_v1(input: impl Into) -> usize { let hasher = build_hasher(input.into().trim_end()); - let mut starter: usize = 0; - - let mut hash_queue: VecDeque = VecDeque::new(); - hash_queue.append(&mut generate_hashes(hasher.clone(), 0, 1000)); + let mut counter: usize = 0; + let mut hash_queue: VecDeque> = fill_hashes(&hasher, 0, 0); let mut keys_count = 0; - loop { - starter += 1; - if hash_queue.is_empty() { - hash_queue.append(&mut generate_hashes( - hasher.clone(), - starter, - starter + 1000, - )); - } - let digest = hash_queue.pop_front().unwrap(); - if let Some(triplet) = find_triplet(&digest) { - let from = starter + 1 + hash_queue.len(); - let to = from + (starter + 1000) - hash_queue.len(); - hash_queue.append(&mut generate_hashes(hasher.clone(), from, to)); - for hash in hash_queue.iter().take(1000) { - if got_quintuplet(hash, triplet) { - if keys_count == 63 { - return starter; + while keys_count < 64 { + if let Some(digest) = hash_queue.pop_front() { + counter += 1; + if let Some(triplet) = find_triplet_u8(&digest) { + hash_queue.append(&mut fill_hashes(&hasher, counter, hash_queue.len())); + for hash in hash_queue.iter().take(1000) { + if got_quintuplet_u8(hash, triplet) { + keys_count += 1; } - keys_count += 1; - break; } } + } else { + hash_queue.append(&mut fill_hashes(&hasher, counter, 0)); } } + counter } pub fn day_14_v2(input: impl Into) -> usize { let hasher = build_hasher(input.into().trim_end()); - let mut starter: usize = 0; - - let mut hash_queue: VecDeque = VecDeque::new(); - hash_queue.append(&mut generate_hashes_v2(hasher.clone(), 0, 1000)); + let mut counter: usize = 0; + let mut hash_queue: VecDeque = fill_hashes_v2(&hasher, 0, 1000); let mut keys_count = 0; - loop { - starter += 1; - if hash_queue.is_empty() { - hash_queue.append(&mut generate_hashes_v2( - hasher.clone(), - starter, - starter + 1000, - )); - } - let digest = hash_queue.pop_front().unwrap(); - if let Some(triplet) = find_triplet(&digest) { - let from = starter + 1 + hash_queue.len(); - let to = from + (starter + 1000) - hash_queue.len(); - hash_queue.append(&mut generate_hashes_v2(hasher.clone(), from, to)); - for hash in hash_queue.iter().take(1000) { - if got_quintuplet(hash, triplet) { - if keys_count == 63 { - return starter; + while keys_count < 64 { + if let Some(digest) = hash_queue.pop_front() { + counter += 1; + if let Some(triplet) = find_triplet(&digest) { + let from = counter + 1 + hash_queue.len(); + let to = from + (counter + 1000) - hash_queue.len(); + hash_queue.append(&mut fill_hashes_v2(&hasher, from, to)); + for hash in hash_queue.iter().take(1000) { + if quintuplet(hash, triplet) { + keys_count += 1; } - keys_count += 1; - break; } } + } else { + hash_queue.append(&mut fill_hashes_v2(&hasher, counter, counter + 1000)); } } + counter } solvable!(day_14, day_14_v1, day_14_v2, usize); diff --git a/src/year_2016/day_24.rs b/src/year_2016/day_24.rs index 5fc7941..2757642 100644 --- a/src/year_2016/day_24.rs +++ b/src/year_2016/day_24.rs @@ -63,9 +63,10 @@ fn get_distance(distances: &HashMap<(&usize, &usize), usize>, from: usize, to: u } #[inline] -fn remove_position_from_vec(mut positions: Vec, needle: &usize) -> Vec { - positions.retain(|elt| elt != needle); - positions +fn remove_position_from_vec(positions: &[usize], needle: &usize) -> Vec { + let mut new_positions = positions.to_owned(); + new_positions.retain(|elt| elt != needle); + new_positions } fn best_path_v1( @@ -82,7 +83,7 @@ fn best_path_v1( return path; } for next_position in positions_left.iter() { - let next_positions_left = remove_position_from_vec(positions_left.clone(), next_position); + let next_positions_left = remove_position_from_vec(&positions_left, next_position); let next_path = path + get_distance(distances, position, *next_position); let next_distance = best_path_v1( distances, @@ -134,7 +135,7 @@ fn best_path_v2( return path + get_distance(distances, position, 0); } for next_position in positions_left.iter() { - let next_positions_left = remove_position_from_vec(positions_left.clone(), next_position); + let next_positions_left = remove_position_from_vec(&positions_left, next_position); let next_path = path + get_distance(distances, position, *next_position); let next_distance = best_path_v2( distances,