Advent of Code solutions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Day 2 Clean Up, Util

Ben C db70ca7f 3bd7bac8

+67 -33
+4 -4
advent_core/src/day.rs
··· 74 74 _ => panic!("Invalid part number"), 75 75 }; 76 76 println!( 77 - "Day {} Part {}: {} ({}ms)", 77 + "Day {} Part {}: {} ({:?}ms)", 78 78 Self::DAY, 79 79 part, 80 80 solution.as_ref().unwrap_or(&"Not implemented".to_string()), 81 - instant.elapsed().as_millis() 81 + instant.elapsed() 82 82 ); 83 83 solution 84 84 } ··· 97 97 _ => panic!("Invalid part number"), 98 98 }; 99 99 println!( 100 - "{extra_indent} Part {}: {} ({}ms)", 100 + "{extra_indent} Part {}: {} ({:?}ms)", 101 101 part, 102 102 solution.as_ref().unwrap_or(&"Not implemented".to_string()), 103 - part_time.elapsed().as_millis() 103 + part_time.elapsed() 104 104 ); 105 105 } 106 106 }
+51
utils/src/misc.rs
··· 1 + use core::ops::Range; 1 2 use std::{collections::HashMap, hash::Hash}; 2 3 3 4 pub fn counts<T: Hash + Eq + PartialEq>(l: impl Iterator<Item = T>) -> HashMap<T, u64> { ··· 10 11 }, 11 12 ) 12 13 } 14 + 15 + #[derive(Debug, Eq, PartialEq, Clone, Copy)] 16 + pub enum FollowRangeResult { 17 + InvalidPair(i64, i64), 18 + Increasing, 19 + Decreasing, 20 + Fluctuates, 21 + ListTooShort 22 + } 23 + 24 + pub fn follows_diff_range(l: &[i64], diff_range: Range<i64>, enforce_one_way: bool, allow_eq: bool) -> FollowRangeResult { 25 + if l.len() < 2 { 26 + FollowRangeResult::ListTooShort 27 + } else { 28 + let first_diff = l[1] - l[0]; 29 + if diff_range.contains(&first_diff) { 30 + let mut ordering = FollowRangeResult::Fluctuates; 31 + 32 + let failing_pair = l.windows(2).skip(1).find_map(|w| { 33 + let (x, y) = (w[0], w[1]); 34 + let diff = y - x; 35 + if diff_range.contains(&diff) && (allow_eq || diff != 0) { 36 + if ordering == FollowRangeResult::Fluctuates && diff != 0 { 37 + ordering = if diff < 0 { FollowRangeResult::Decreasing } else { FollowRangeResult::Increasing }; 38 + None 39 + } else if enforce_one_way && (ordering == FollowRangeResult::Increasing && diff < 0) || (ordering == FollowRangeResult::Decreasing && diff > 0) { 40 + Some((x, y)) 41 + } else { 42 + None 43 + } 44 + } else { 45 + Some((x, y)) 46 + } 47 + }); 48 + 49 + match failing_pair { 50 + Some((x, y)) => FollowRangeResult::InvalidPair(x, y), 51 + None => ordering 52 + } 53 + } else { 54 + FollowRangeResult::InvalidPair(l[0], l[1]) 55 + } 56 + } 57 + } 58 + 59 + pub fn all_combos_remove_one<T>(l: &[T]) -> impl Iterator<Item = impl Iterator<Item = &T>> { 60 + (0..l.len()).map(|exclude| { 61 + l.iter().enumerate().filter_map(move |(i, e)| Some(e).filter(|_| i != exclude)) 62 + }) 63 + }
+12 -29
years/2024/src/day_2.rs
··· 1 1 2 2 use advent_core::{Day, day_stuff, ex_for_day}; 3 + use utils::misc::{all_combos_remove_one, follows_diff_range, FollowRangeResult}; 3 4 4 5 pub struct Day2; 5 6 6 - fn line_valid(line: &[u64]) -> bool { 7 - let mut increasing: Option<bool> = None; 8 - line.windows(2).all(|w| { 9 - let (x, y) = (w[0], w[1]); 10 - if x == y || x.abs_diff(y) > 3 { 11 - false 12 - } else if let Some(increasing) = increasing { 13 - !((increasing && y <= x) || (!increasing && x <= y)) 14 - } else { 15 - increasing = Some(x < y); 16 - true 17 - } 18 - }) 7 + fn line_valid(line: &[i64]) -> bool { 8 + let res = follows_diff_range(line, -3..4, true, false); 9 + matches!(res, FollowRangeResult::Increasing | FollowRangeResult::Decreasing) 19 10 } 20 11 21 12 impl Day for Day2 { 22 13 23 - day_stuff!(2, "2", "4", Vec<Vec<u64>>); 14 + day_stuff!(2, "2", "4", Vec<Vec<i64>>); 24 15 25 16 fn part_1(input: Self::Input) -> Option<String> { 26 17 Some(input.into_iter().filter(|v| line_valid(&v)).count().to_string()) ··· 28 19 29 20 fn part_2(input: Self::Input) -> Option<String> { 30 21 Some(input.into_iter().filter(|line| { 31 - let valid = line_valid(&line); 32 - if valid { 33 - true 34 - } else { 35 - (0..line.len()).any(|ie| { 36 - let v = line.iter() 37 - .enumerate() 38 - .filter(|(i, _)| *i != ie) 39 - .map(|(_, e)| *e) 40 - .collect::<Vec<_>>(); 41 - 42 - line_valid(&v) 43 - }) 44 - } 22 + line_valid(&line) || 23 + all_combos_remove_one(line) 24 + .any(|combo| { 25 + let v = combo.map(|x| *x).collect::<Vec<_>>(); 26 + line_valid(&v) 27 + }) 45 28 }).count().to_string()) 46 29 } 47 30 48 31 fn parse_input(input: &str) -> Self::Input { 49 - input.split('\n').map(|l| l.split_ascii_whitespace().map(|x| x.parse::<u64>().unwrap()).collect()).collect() 32 + input.split('\n').map(|l| l.split_ascii_whitespace().map(|x| x.parse::<i64>().unwrap()).collect()).collect() 50 33 } 51 34 }