From ee1a97f61a95c579cb002120068fdea981bd2b6b Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 4 Dec 2022 17:56:26 -0500 Subject: [PATCH] update macro api --- 2022/src/day_1.rs | 35 +++++++++----- 2022/src/day_2.rs | 47 ++++++++++++------- 2022/src/day_3.rs | 67 +++++++++++++------------- 2022/src/day_4.rs | 83 ++++++++++++++++++--------------- advent_of_code_macro/Cargo.toml | 2 +- advent_of_code_macro/src/lib.rs | 43 ++++++----------- 6 files changed, 147 insertions(+), 130 deletions(-) diff --git a/2022/src/day_1.rs b/2022/src/day_1.rs index c9cecd7..d2fbc7b 100644 --- a/2022/src/day_1.rs +++ b/2022/src/day_1.rs @@ -1,16 +1,27 @@ -advent_of_code_macro::solve_problem!( +type Input = Vec>; + +fn parse(input: &str) -> Input { + input + .split("\n\n") + .map(|lines| lines.lines().map(|line| line.parse().unwrap()).collect()) + .collect() +} + +fn part_one(data: Input) -> i32 { + data.iter().map(|cals| cals.iter().sum()).max().unwrap() +} + +fn part_two(data: Input) -> i32 { + let mut cals: std::collections::BinaryHeap = + data.iter().map(|cals| cals.iter().sum()).collect(); + cals.pop().unwrap() + cals.pop().unwrap() + cals.pop().unwrap() +} + +advent_of_code_macro::generate_tests!( day 1, - Input Vec>, - parse |input: &str| { - input.split("\n\n").map(|lines| lines.lines().map(|line| line.parse().unwrap()).collect()).collect() - }, - part one |data: Input| { - data.iter().map(|cals| cals.iter().sum()).max().unwrap() - }, - part two |data: Input| { - let mut cals: std::collections::BinaryHeap = data.iter().map(|cals| cals.iter().sum()).collect(); - cals.pop().unwrap() + cals.pop().unwrap() + cals.pop().unwrap() - }, + parse, + part_one, + part_two, sample tests [24_000, 45_000], star tests [68_923, 200_044] ); diff --git a/2022/src/day_2.rs b/2022/src/day_2.rs index 3a9c661..3c29c3b 100644 --- a/2022/src/day_2.rs +++ b/2022/src/day_2.rs @@ -1,5 +1,7 @@ use Shape::*; +type Input = Vec>; + #[derive(Debug, PartialEq, Eq)] enum Shape { Rock, @@ -37,15 +39,15 @@ impl Shape { } } } - -advent_of_code_macro::solve_problem!( - day 2, - Input Vec>, - parse |input: &str| { - input.lines().map(|line| line.split(' ').map(|s| s.chars().next().unwrap()).collect()).collect() - }, - part one |data: Input| { - data.iter().map(|round| { +fn parse(input: &str) -> Input { + input + .lines() + .map(|line| line.split(' ').map(|s| s.chars().next().unwrap()).collect()) + .collect() +} +fn part_one(data: Input) -> i32 { + data.iter() + .map(|round| { let my_move = Shape::from_char(round[1]); let other_move = Shape::from_char(round[0]); let round_result = if my_move == other_move { @@ -56,16 +58,25 @@ advent_of_code_macro::solve_problem!( 6 }; round_result + my_move.as_int() - }).sum() - }, - part two |data: Input| { - data.iter().map(|round| match round[1] { - 'X' => Shape::from_char(round[0]).wins_to().as_int(), - 'Y' => Shape::from_char(round[0]).as_int() + 3, - 'Z' => Shape::from_char(round[0]).loses_to().as_int() + 6, + }) + .sum() +} +fn part_two(data: Input) -> i32 { + data.iter() + .map(|round| match round[1] { + 'X' => Shape::from_char(round[0]).wins_to().as_int(), + 'Y' => Shape::from_char(round[0]).as_int() + 3, + 'Z' => Shape::from_char(round[0]).loses_to().as_int() + 6, _ => panic!("expected X, Y, or Z"), - }).sum() - }, + }) + .sum() +} + +advent_of_code_macro::generate_tests!( + day 2, + parse, + part_one, + part_two, sample tests [15, 12], star tests [11063, 10349] ); diff --git a/2022/src/day_3.rs b/2022/src/day_3.rs index 12fc8a9..4424f3a 100644 --- a/2022/src/day_3.rs +++ b/2022/src/day_3.rs @@ -1,3 +1,5 @@ +type Input = Vec; + fn get_priority(c: char) -> i32 { match c { 'a'..='z' => c as i32 - 'a' as i32 + 1, @@ -5,41 +7,40 @@ fn get_priority(c: char) -> i32 { _ => panic!("expected letter"), } } +fn parse(input: &str) -> Input { + input.lines().map(str::to_owned).collect() +} +fn part_one(data: Input) -> i32 { + data.iter() + .map(|s| { + use std::collections::HashSet; + let (left, right) = s.split_at(s.len() / 2); + let right_set: HashSet = right.chars().collect(); + get_priority(left.chars().find(|c| right_set.contains(c)).unwrap()) + }) + .sum() +} +fn part_two(data: Input) -> i32 { + data.as_slice() + .chunks(3) + .map(|c| { + use std::collections::HashSet; + let second_set: HashSet = c[1].chars().collect(); + let third_set: HashSet = c[2].chars().collect(); + get_priority( + c[0].chars() + .find(|c| second_set.contains(c) && third_set.contains(c)) + .unwrap(), + ) + }) + .sum() +} -advent_of_code_macro::solve_problem!( +advent_of_code_macro::generate_tests!( day 3, - Input Vec, - parse |input: &str| { - input.lines().map(str::to_owned).collect() - }, - part one |data: Input| { - data.iter() - .map(|s| { - use std::collections::HashSet; - let (left, right) = s.split_at(s.len() / 2); - let right_set: HashSet = right.chars().collect(); - get_priority( - left.chars() - .find(|c| right_set.contains(c)) - .unwrap(), - ) - }).sum() - }, - part two |data: Input| { - data.as_slice() - .chunks(3) - .map(|c| { - use std::collections::HashSet; - let second_set: HashSet = c[1].chars().collect(); - let third_set: HashSet = c[2].chars().collect(); - get_priority( - c[0].chars() - .find(|c| second_set.contains(c) && third_set.contains(c)) - .unwrap(), - ) - }) - .sum() - }, + parse, + part_one, + part_two, sample tests [157, 70], star tests [7908, 2838] ); diff --git a/2022/src/day_4.rs b/2022/src/day_4.rs index b93b338..8d21125 100644 --- a/2022/src/day_4.rs +++ b/2022/src/day_4.rs @@ -1,42 +1,49 @@ -advent_of_code_macro::solve_problem!( +type Input = Vec>; + +fn parse(input: &str) -> Input { + input + .lines() + .map(|line| { + let (a, rest) = line.split_once('-').unwrap(); + let (b, rest) = rest.split_once(',').unwrap(); + let (c, d) = rest.split_once('-').unwrap(); + [a, b, c, d] + .into_iter() + .map(str::parse) + .map(Result::unwrap) + .collect() + }) + .collect() +} +fn part_one(data: Input) -> i32 { + data.into_iter().fold(0, |acc, curr| { + if (curr[0] <= curr[2] && curr[1] >= curr[3]) || (curr[2] <= curr[0] && curr[3] >= curr[1]) + { + acc + 1 + } else { + acc + } + }) +} +fn part_two(data: Input) -> i32 { + data.into_iter().fold(0, |acc, curr| { + if (curr[0] >= curr[2] && curr[0] <= curr[3]) + || (curr[1] >= curr[2] && curr[1] <= curr[3]) + || (curr[2] >= curr[0] && curr[2] <= curr[1]) + || (curr[3] >= curr[0] && curr[3] <= curr[1]) + { + acc + 1 + } else { + acc + } + }) +} + +advent_of_code_macro::generate_tests!( day 4, - Input Vec>, - parse |input: &str| { - input.lines() - .map(|line| { - let (a, rest) = line.split_once('-').unwrap(); - let (b, rest) = rest.split_once(',').unwrap(); - let (c, d) = rest.split_once('-').unwrap(); - [a, b, c, d].into_iter() - .map(str::parse) - .map(Result::unwrap) - .collect() - }).collect() - }, - part one |data: Input| { - data.into_iter() - .fold(0, |acc, curr| - if (curr[0] <= curr[2] && curr[1] >= curr[3]) - || (curr[2] <= curr[0] && curr[3] >= curr[1]) { - acc + 1 - } else { - acc - } - ) - }, - part two |data: Input| { - data.into_iter() - .fold(0, |acc, curr| - if (curr[0] >= curr[2] && curr[0] <= curr[3]) - || (curr[1] >= curr[2] && curr[1] <= curr[3]) - || (curr[2] >= curr[0] && curr[2] <= curr[1]) - || (curr[3] >= curr[0] && curr[3] <= curr[1]) { - acc + 1 - } else { - acc - } - ) - }, + parse, + part_one, + part_two, sample tests [2, 4], star tests [450, 837] ); diff --git a/advent_of_code_macro/Cargo.toml b/advent_of_code_macro/Cargo.toml index 325a951..163f0fd 100644 --- a/advent_of_code_macro/Cargo.toml +++ b/advent_of_code_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "advent_of_code_macro" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "An test generating macro for advent of code" license = "MIT" diff --git a/advent_of_code_macro/src/lib.rs b/advent_of_code_macro/src/lib.rs index 6d24e29..58bca15 100644 --- a/advent_of_code_macro/src/lib.rs +++ b/advent_of_code_macro/src/lib.rs @@ -1,55 +1,42 @@ #[macro_export] -macro_rules! solve_problem { +macro_rules! generate_tests { (day $day:literal, - Input $input_type:ty, - parse $parse_input:expr, - part one $part_one:expr, - part two $part_two:expr, + $parse_input:ident, + $part_one:ident, + $part_two:ident, sample tests [$part_one_sample_ans:literal, $part_two_sample_ans:literal], star tests [$part_one_ans:literal, $part_two_ans:literal]) => { #[cfg(test)] paste::paste! { mod [] { - use super::*; - type Input = $input_type; - fn parse_input(s: &str) -> Input { - $parse_input(s) - } - - fn part_one_solution(data: Input) -> i32 { - $part_one(data) - } - - fn part_two_solution(data: Input) -> i32 { - $part_two(data) - } + use super::{$parse_input, $part_one, $part_two}; #[test] fn part_one_sample() { let input = include_str!(concat!("../input/day_", $day, "_sample.txt")); - let data = parse_input(input); - assert_eq!($part_one_sample_ans, part_one_solution(data)); + let data = $parse_input(input); + assert_eq!($part_one_sample_ans, $part_one(data)); } #[test] - fn part_one() { + fn part_one_star() { let input = include_str!(concat!("../input/day_", $day, ".txt")); - let data = parse_input(input); - assert_eq!($part_one_ans, part_one_solution(data)); + let data = $parse_input(input); + assert_eq!($part_one_ans, $part_one(data)); } #[test] fn part_two_sample() { let input = include_str!(concat!("../input/day_", $day, "_sample.txt")); - let data = parse_input(input); - assert_eq!($part_two_sample_ans, part_two_solution(data)); + let data = $parse_input(input); + assert_eq!($part_two_sample_ans, $part_two(data)); } #[test] - fn part_two() { + fn part_two_star() { let input = include_str!(concat!("../input/day_", $day, ".txt")); - let data = parse_input(input); - assert_eq!($part_two_ans, part_two_solution(data)); + let data = $parse_input(input); + assert_eq!($part_two_ans, $part_two(data)); } } }