update macro api

This commit is contained in:
Adam Jeniski 2022-12-04 17:56:26 -05:00
parent cad101cf54
commit ee1a97f61a
6 changed files with 147 additions and 130 deletions

View File

@ -1,16 +1,27 @@
advent_of_code_macro::solve_problem!( type Input = Vec<Vec<i32>>;
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<i32> =
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, day 1,
Input Vec<Vec<i32>>, parse,
parse |input: &str| { part_one,
input.split("\n\n").map(|lines| lines.lines().map(|line| line.parse().unwrap()).collect()).collect() part_two,
},
part one |data: Input| {
data.iter().map(|cals| cals.iter().sum()).max().unwrap()
},
part two |data: Input| {
let mut cals: std::collections::BinaryHeap<i32> = data.iter().map(|cals| cals.iter().sum()).collect();
cals.pop().unwrap() + cals.pop().unwrap() + cals.pop().unwrap()
},
sample tests [24_000, 45_000], sample tests [24_000, 45_000],
star tests [68_923, 200_044] star tests [68_923, 200_044]
); );

View File

@ -1,5 +1,7 @@
use Shape::*; use Shape::*;
type Input = Vec<Vec<char>>;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
enum Shape { enum Shape {
Rock, Rock,
@ -37,15 +39,15 @@ impl Shape {
} }
} }
} }
fn parse(input: &str) -> Input {
advent_of_code_macro::solve_problem!( input
day 2, .lines()
Input Vec<Vec<char>>, .map(|line| line.split(' ').map(|s| s.chars().next().unwrap()).collect())
parse |input: &str| { .collect()
input.lines().map(|line| line.split(' ').map(|s| s.chars().next().unwrap()).collect()).collect() }
}, fn part_one(data: Input) -> i32 {
part one |data: Input| { data.iter()
data.iter().map(|round| { .map(|round| {
let my_move = Shape::from_char(round[1]); let my_move = Shape::from_char(round[1]);
let other_move = Shape::from_char(round[0]); let other_move = Shape::from_char(round[0]);
let round_result = if my_move == other_move { let round_result = if my_move == other_move {
@ -56,16 +58,25 @@ advent_of_code_macro::solve_problem!(
6 6
}; };
round_result + my_move.as_int() round_result + my_move.as_int()
}).sum() })
}, .sum()
part two |data: Input| { }
data.iter().map(|round| match round[1] { fn part_two(data: Input) -> i32 {
'X' => Shape::from_char(round[0]).wins_to().as_int(), data.iter()
'Y' => Shape::from_char(round[0]).as_int() + 3, .map(|round| match round[1] {
'Z' => Shape::from_char(round[0]).loses_to().as_int() + 6, '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"), _ => 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], sample tests [15, 12],
star tests [11063, 10349] star tests [11063, 10349]
); );

View File

@ -1,3 +1,5 @@
type Input = Vec<String>;
fn get_priority(c: char) -> i32 { fn get_priority(c: char) -> i32 {
match c { match c {
'a'..='z' => c as i32 - 'a' as i32 + 1, 'a'..='z' => c as i32 - 'a' as i32 + 1,
@ -5,41 +7,40 @@ fn get_priority(c: char) -> i32 {
_ => panic!("expected letter"), _ => 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<char> = 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<char> = c[1].chars().collect();
let third_set: HashSet<char> = 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, day 3,
Input Vec<String>, parse,
parse |input: &str| { part_one,
input.lines().map(str::to_owned).collect() part_two,
},
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<char> = 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<char> = c[1].chars().collect();
let third_set: HashSet<char> = c[2].chars().collect();
get_priority(
c[0].chars()
.find(|c| second_set.contains(c) && third_set.contains(c))
.unwrap(),
)
})
.sum()
},
sample tests [157, 70], sample tests [157, 70],
star tests [7908, 2838] star tests [7908, 2838]
); );

View File

@ -1,42 +1,49 @@
advent_of_code_macro::solve_problem!( type Input = Vec<Vec<i32>>;
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, day 4,
Input Vec<Vec<i32>>, parse,
parse |input: &str| { part_one,
input.lines() part_two,
.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
}
)
},
sample tests [2, 4], sample tests [2, 4],
star tests [450, 837] star tests [450, 837]
); );

View File

@ -1,6 +1,6 @@
[package] [package]
name = "advent_of_code_macro" name = "advent_of_code_macro"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
description = "An test generating macro for advent of code" description = "An test generating macro for advent of code"
license = "MIT" license = "MIT"

View File

@ -1,55 +1,42 @@
#[macro_export] #[macro_export]
macro_rules! solve_problem { macro_rules! generate_tests {
(day $day:literal, (day $day:literal,
Input $input_type:ty, $parse_input:ident,
parse $parse_input:expr, $part_one:ident,
part one $part_one:expr, $part_two:ident,
part two $part_two:expr,
sample tests [$part_one_sample_ans:literal, $part_two_sample_ans:literal], sample tests [$part_one_sample_ans:literal, $part_two_sample_ans:literal],
star tests [$part_one_ans:literal, $part_two_ans:literal]) => { star tests [$part_one_ans:literal, $part_two_ans:literal]) => {
#[cfg(test)] #[cfg(test)]
paste::paste! { paste::paste! {
mod [<day_ $day _tests>] { mod [<day_ $day _tests>] {
use super::*; use super::{$parse_input, $part_one, $part_two};
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)
}
#[test] #[test]
fn part_one_sample() { fn part_one_sample() {
let input = include_str!(concat!("../input/day_", $day, "_sample.txt")); let input = include_str!(concat!("../input/day_", $day, "_sample.txt"));
let data = parse_input(input); let data = $parse_input(input);
assert_eq!($part_one_sample_ans, part_one_solution(data)); assert_eq!($part_one_sample_ans, $part_one(data));
} }
#[test] #[test]
fn part_one() { fn part_one_star() {
let input = include_str!(concat!("../input/day_", $day, ".txt")); let input = include_str!(concat!("../input/day_", $day, ".txt"));
let data = parse_input(input); let data = $parse_input(input);
assert_eq!($part_one_ans, part_one_solution(data)); assert_eq!($part_one_ans, $part_one(data));
} }
#[test] #[test]
fn part_two_sample() { fn part_two_sample() {
let input = include_str!(concat!("../input/day_", $day, "_sample.txt")); let input = include_str!(concat!("../input/day_", $day, "_sample.txt"));
let data = parse_input(input); let data = $parse_input(input);
assert_eq!($part_two_sample_ans, part_two_solution(data)); assert_eq!($part_two_sample_ans, $part_two(data));
} }
#[test] #[test]
fn part_two() { fn part_two_star() {
let input = include_str!(concat!("../input/day_", $day, ".txt")); let input = include_str!(concat!("../input/day_", $day, ".txt"));
let data = parse_input(input); let data = $parse_input(input);
assert_eq!($part_two_ans, part_two_solution(data)); assert_eq!($part_two_ans, $part_two(data));
} }
} }
} }