programming puzzle solutions
2
fork

Configure Feed

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

cleanup; add tests; functional style

+55 -72
+55 -72
src/2024/day2/rust/mod.rs
··· 1 - pub fn validate_report(report: &Vec<i32>) -> bool { 2 - let mut valid = true; 3 - let direction = { 4 - if report[1] > report[0] { 5 - 1 6 - } else { 7 - -1 8 - } 9 - }; 10 - let mut diff = 0; 1 + pub fn validate_report(report: &[i32]) -> bool { 2 + let direction = if report[1] > report[0] { 1 } else { -1 }; 11 3 for i in 1..report.len() { 12 - if report[i] > report[i - 1] { 13 - if direction != 1 { 14 - valid = false; 15 - break; 16 - } 17 - } else { 18 - if direction != -1 { 19 - valid = false; 20 - break; 21 - } 22 - } 23 - diff = (report[i] - report[i - 1]).abs(); 24 - if diff < 1 || diff > 3 { 25 - valid = false; 26 - break; 4 + let diff = report[i] - report[i - 1]; 5 + if diff.abs() < 1 6 + || diff.abs() > 3 7 + || (direction == 1 && diff < 0) 8 + || (direction == -1 && diff > 0) 9 + { 10 + return false; 27 11 } 28 12 } 29 - if valid { 30 - return true; 31 - } else { 32 - return false; 33 - } 13 + true 34 14 } 35 15 36 - pub fn part_a(input: &str) -> i32 { 37 - let reports: Vec<Vec<i32>> = input 16 + fn parse_reports(input: &str) -> Vec<Vec<i32>> { 17 + input 38 18 .lines() 39 19 .map(|line| { 40 20 line.split_whitespace() 41 - .map(|num| num.parse().unwrap()) 21 + .map(|num| num.parse().expect("should be a number")) 42 22 .collect() 43 23 }) 44 - .collect(); 45 - let mut safe_reports = 0; 46 - for report in reports.iter() { 47 - if validate_report(report) { 48 - safe_reports += 1; 49 - } 50 - } 51 - safe_reports 24 + .collect() 25 + } 26 + 27 + pub fn part_a(input: &str) -> i32 { 28 + parse_reports(input) 29 + .iter() 30 + .filter(|report| validate_report(report)) 31 + .count() as i32 52 32 } 53 33 54 34 pub fn part_b(input: &str) -> i32 { 55 - let reports: Vec<Vec<i32>> = input 56 - .lines() 57 - .map(|line| { 58 - line.split_whitespace() 59 - .map(|num| num.parse().unwrap()) 60 - .collect() 61 - }) 62 - .collect(); 63 - let mut safe_reports = 0; 64 - for report in reports.iter() { 65 - if validate_report(report) { 66 - safe_reports += 1; 67 - } else { 68 - let mut new_reports: Vec<Vec<i32>> = Vec::new(); 69 - for i in 0..report.len() { 70 - let mut new_report = report.clone(); 35 + parse_reports(input) 36 + .iter() 37 + .filter(|report| { 38 + (0..report.len()).any(|i| { 39 + let mut new_report = report.to_vec(); 71 40 new_report.remove(i); 72 - new_reports.push(new_report); 73 - } 74 - for new_report in new_reports.iter() { 75 - if validate_report(new_report) { 76 - safe_reports += 1; 77 - break; 78 - } 79 - } 80 - } 81 - } 82 - safe_reports 41 + validate_report(&new_report) 42 + }) 43 + }) 44 + .count() as i32 83 45 } 84 46 85 47 pub fn main() { 86 48 let input = include_str!("../input.txt"); 87 49 let example_input = include_str!("../input_example.txt"); 88 50 // let example_input_b = include_str!("../input_example_b.txt"); 89 - let day: u8 = 1; 51 + let day: u8 = 2; 90 52 println!("Day {} Example Part A: {}", day, part_a(example_input)); 91 53 println!("Day {} Part A: {}", day, part_a(input)); 92 54 println!("Day {} Example Part B: {}", day, part_b(example_input)); 93 55 println!("Day {} Part B: {}", day, part_b(input)); 94 56 } 95 57 96 - // #[cfg(test)] 97 - // mod tests { 98 - // } 58 + #[cfg(test)] 59 + mod tests { 60 + use super::*; 61 + #[test] 62 + fn test_part_a_example() { 63 + let example_input = include_str!("../input_example.txt"); 64 + assert_eq!(part_a(example_input), 2); 65 + } 66 + #[test] 67 + fn test_part_a() { 68 + let input = include_str!("../input.txt"); 69 + assert_eq!(part_a(input), 502); 70 + } 71 + #[test] 72 + fn test_part_b_example() { 73 + let example_input_b = include_str!("../input_example.txt"); 74 + assert_eq!(part_b(example_input_b), 4); 75 + } 76 + #[test] 77 + fn test_part_b() { 78 + let input = include_str!("../input.txt"); 79 + assert_eq!(part_b(input), 544); 80 + } 81 + }