1
0
Fork 0

refactor: use generated boilerplate from lib

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2022-12-08 22:43:34 +01:00
parent f53be47327
commit cb82cbb433
Signed by: mfocko
GPG key ID: 7C47D46246790496
8 changed files with 204 additions and 399 deletions

View file

@ -1,8 +1,4 @@
use aoc_2022::file_to_lines;
use color_eyre::eyre::Result;
use tracing::*;
use tracing_subscriber::EnvFilter;
use aoc_2022::*;
type Input = Vec<i32>;
type Output = i32;
@ -24,53 +20,26 @@ fn n_biggest(n: usize, input: &Input) -> Output {
calories.iter().rev().take(n).sum()
}
fn part_1(input: &Input) -> Output {
n_biggest(1_usize, input)
}
struct Day01;
impl Solution<Input, Output> for Day01 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_lines(pathname)
.iter()
.map(|s| if s.is_empty() { -1 } else { s.parse().unwrap() })
.collect()
}
fn part_2(input: &Input) -> Output {
n_biggest(3_usize, input)
}
fn part_1(input: &Input) -> Output {
n_biggest(1_usize, input)
}
fn parse_input(pathname: &str) -> Input {
file_to_lines(pathname)
.iter()
.map(|s| if s.is_empty() { -1 } else { s.parse().unwrap() })
.collect()
fn part_2(input: &Input) -> Output {
n_biggest(3_usize, input)
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day01.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day01::main()
}
#[cfg(test)]
mod day_01 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day01.txt");
assert_eq!(part_1(&sample), 24000);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day01.txt");
assert_eq!(part_2(&sample), 45000);
}
}
test_sample!(day_01, Day01, 24000, 45000);

View file

@ -2,10 +2,14 @@ use std::str::FromStr;
use aoc_2022::*;
use color_eyre::{eyre::{eyre, Result}, Report};
use color_eyre::{
eyre::eyre,
Report,
};
use itertools::Itertools;
use tracing::*;
use tracing_subscriber::EnvFilter;
type Input = Vec<Round>;
type Output = i32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Shape {
@ -133,53 +137,23 @@ impl Round {
}
}
type Input = Vec<Round>;
type Output = i32;
struct Day02;
impl Solution<Input, Output> for Day02 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_structs(pathname)
}
fn part_1(input: &Input) -> Output {
input.iter().map(Round::score).sum()
}
fn part_1(input: &Input) -> Output {
input.iter().map(Round::score).sum()
}
fn part_2(input: &Input) -> Output {
input.iter().map(Round::expected_score).sum()
}
fn parse_input(pathname: &str) -> Input {
file_to_structs(pathname)
fn part_2(input: &Input) -> Output {
input.iter().map(Round::expected_score).sum()
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day02.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day02::main()
}
#[cfg(test)]
mod day_02 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day02.txt");
assert_eq!(part_1(&sample), 15);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day02.txt");
assert_eq!(part_2(&sample), 12);
}
}
test_sample!(day_02, Day02, 15, 12);

View file

@ -3,15 +3,13 @@ use std::str::FromStr;
use aoc_2022::*;
use color_eyre::eyre::{Report, Result};
use tracing::*;
use tracing_subscriber::EnvFilter;
struct Backpack(HashSet<i32>, HashSet<i32>);
use color_eyre::eyre::Report;
type Input = Vec<Backpack>;
type Output = i32;
struct Backpack(HashSet<i32>, HashSet<i32>);
impl FromStr for Backpack {
type Err = Report;
@ -49,13 +47,6 @@ impl Backpack {
}
}
fn part_1(input: &Input) -> Output {
input
.iter()
.map(|b| b.common_items().iter().sum::<i32>())
.sum()
}
fn common_items(backpacks: &[Backpack]) -> HashSet<i32> {
backpacks
.iter()
@ -65,49 +56,29 @@ fn common_items(backpacks: &[Backpack]) -> HashSet<i32> {
})
}
fn part_2(input: &Input) -> Output {
input
.chunks(3)
.map(|backpacks| common_items(backpacks).iter().sum::<i32>())
.sum()
}
struct Day03;
impl Solution<Input, Output> for Day03 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_structs(pathname)
}
fn parse_input(pathname: &str) -> Input {
file_to_structs(pathname)
fn part_1(input: &Input) -> Output {
input
.iter()
.map(|b| b.common_items().iter().sum::<i32>())
.sum()
}
fn part_2(input: &Input) -> Output {
input
.chunks(3)
.map(|backpacks| common_items(backpacks).iter().sum::<i32>())
.sum()
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day03.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day03::main()
}
#[cfg(test)]
mod day_03 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day03.txt");
assert_eq!(part_1(&sample), 157);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day03.txt");
assert_eq!(part_2(&sample), 70);
}
}
test_sample!(day_03, Day03, 157, 70);

View file

@ -3,9 +3,10 @@ use std::str::FromStr;
use aoc_2022::*;
use color_eyre::eyre::{Report, Result};
use tracing::*;
use tracing_subscriber::EnvFilter;
use color_eyre::eyre::Report;
type Input = Vec<Assignment>;
type Output = usize;
struct Assignment(RangeInclusive<i32>, RangeInclusive<i32>);
@ -48,53 +49,23 @@ impl Assignment {
}
}
type Input = Vec<Assignment>;
type Output = usize;
struct Day04;
impl Solution<Input, Output> for Day04 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_structs(pathname)
}
fn part_1(input: &Input) -> Output {
input.iter().filter(|a| a.fully_overlap()).count()
}
fn part_1(input: &Input) -> Output {
input.iter().filter(|a| a.fully_overlap()).count()
}
fn part_2(input: &Input) -> Output {
input.iter().filter(|a| a.overlap()).count()
}
fn parse_input(pathname: &str) -> Input {
file_to_structs(pathname)
fn part_2(input: &Input) -> Output {
input.iter().filter(|a| a.overlap()).count()
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day04.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day04::main()
}
#[cfg(test)]
mod day_04 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day04.txt");
assert_eq!(part_1(&sample), 2);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day04.txt");
assert_eq!(part_2(&sample), 4);
}
}
test_sample!(day_04, Day04, 2, 4);

View file

@ -3,10 +3,11 @@ use std::str::FromStr;
use aoc_2022::*;
use color_eyre::eyre::{Report, Result};
use color_eyre::eyre::Report;
use itertools::Itertools;
use tracing::*;
use tracing_subscriber::EnvFilter;
type Input = Ship;
type Output = String;
#[derive(Debug)]
struct Move {
@ -65,9 +66,6 @@ impl FromStr for Ship {
}
}
type Input = Ship;
type Output = String;
fn stacks_to_string(stacks: &[Vec<char>]) -> String {
stacks.iter().fold(String::new(), |acc, stack| {
if let Some(c) = stack.last() {
@ -96,50 +94,23 @@ fn move_crates(input: &Input, one_by_one: bool) -> Output {
stacks_to_string(&stacks)
}
fn part_1(input: &Input) -> Output {
move_crates(input, true)
}
struct Day05;
impl Solution<Input, Output> for Day05 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_string(pathname).parse().unwrap()
}
fn part_2(input: &Input) -> Output {
move_crates(input, false)
}
fn part_1(input: &Input) -> Output {
move_crates(input, true)
}
fn parse_input(pathname: &str) -> Input {
file_to_string(pathname).parse::<Input>().unwrap()
fn part_2(input: &Input) -> Output {
move_crates(input, false)
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day05.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day05::main()
}
#[cfg(test)]
mod day_05 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day05.txt");
assert_eq!(part_1(&sample), "CMZ".to_string());
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day05.txt");
assert_eq!(part_2(&sample), "MCD".to_string());
}
}
test_sample!(day_05, Day05, "CMZ".to_string(), "MCD".to_string());

View file

@ -2,10 +2,7 @@ use std::collections::HashSet;
use aoc_2022::*;
use color_eyre::eyre::Result;
use itertools::Itertools;
use tracing::*;
use tracing_subscriber::EnvFilter;
type Input = String;
type Output = usize;
@ -23,90 +20,92 @@ fn unique_marker_index(buffer: &Input, n: usize) -> Output {
+ n
}
fn part_1(input: &Input) -> Output {
unique_marker_index(input, 4)
}
struct Day06;
impl Solution<Input, Output> for Day06 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_string(pathname)
}
fn part_2(input: &Input) -> Output {
unique_marker_index(input, 14)
}
fn part_1(input: &Input) -> Output {
unique_marker_index(input, 4)
}
fn parse_input(pathname: &str) -> Input {
file_to_string(pathname)
fn part_2(input: &Input) -> Output {
unique_marker_index(input, 14)
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day06.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day06::main()
}
test_sample!(day_06, Day06, 7, 19);
#[cfg(test)]
mod day_06 {
mod day_06_extended {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day06.txt");
assert_eq!(part_1(&sample), 7);
}
#[test]
fn test_part_1_example_1() {
assert_eq!(part_1(&"bvwbjplbgvbhsrlpgdmjqwftvncz".to_string()), 5);
assert_eq!(
Day06::part_1(&"bvwbjplbgvbhsrlpgdmjqwftvncz".to_string()),
5
);
}
#[test]
fn test_part_1_example_2() {
assert_eq!(part_1(&"nppdvjthqldpwncqszvftbrmjlhg".to_string()), 6);
assert_eq!(
Day06::part_1(&"nppdvjthqldpwncqszvftbrmjlhg".to_string()),
6
);
}
#[test]
fn test_part_1_example_3() {
assert_eq!(part_1(&"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg".to_string()), 10);
assert_eq!(
Day06::part_1(&"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg".to_string()),
10
);
}
#[test]
fn test_part_1_example_4() {
assert_eq!(part_1(&"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw".to_string()), 11);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day06.txt");
assert_eq!(part_2(&sample), 19);
assert_eq!(
Day06::part_1(&"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw".to_string()),
11
);
}
#[test]
fn test_part_2_example_1() {
assert_eq!(part_2(&"bvwbjplbgvbhsrlpgdmjqwftvncz".to_string()), 23);
assert_eq!(
Day06::part_2(&"bvwbjplbgvbhsrlpgdmjqwftvncz".to_string()),
23
);
}
#[test]
fn test_part_2_example_2() {
assert_eq!(part_2(&"nppdvjthqldpwncqszvftbrmjlhg".to_string()), 23);
assert_eq!(
Day06::part_2(&"nppdvjthqldpwncqszvftbrmjlhg".to_string()),
23
);
}
#[test]
fn test_part_2_example_3() {
assert_eq!(part_2(&"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg".to_string()), 29);
assert_eq!(
Day06::part_2(&"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg".to_string()),
29
);
}
#[test]
fn test_part_2_example_4() {
assert_eq!(part_2(&"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw".to_string()), 26);
assert_eq!(
Day06::part_2(&"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw".to_string()),
26
);
}
}

View file

@ -2,10 +2,11 @@ use std::{cell::RefCell, cmp::min, collections::BTreeMap, rc::Rc, str::FromStr};
use aoc_2022::*;
use color_eyre::{eyre::Result, Report};
use color_eyre::Report;
use itertools::Itertools;
use tracing::*;
use tracing_subscriber::EnvFilter;
type Input = Filesystem;
type Output = usize;
type FileHandle = Rc<RefCell<AocFile>>;
@ -47,15 +48,15 @@ impl AocFile {
panic!("cannot cd in file")
}
fn size_under_100000(&self) -> (bool, usize, usize) {
fn size_under(&self, max_size: usize) -> (bool, usize, usize) {
match self {
AocFile::File(s) => (false, 0, *s),
AocFile::Directory(files) => {
let (running_total, size) = files
.values()
.map(|f| f.borrow().size_under_100000())
.map(|f| f.borrow().size_under(max_size))
.fold((0_usize, 0_usize), |(mut running, size), (dir, r, s)| {
if dir && s <= 100000 {
if dir && s <= max_size {
running += s;
}
@ -112,6 +113,8 @@ impl Filesystem {
}
}
// [MARK] Helper functions for FromStr trait
fn cd(&mut self, dir: &str) {
match dir {
".." => {
@ -143,15 +146,28 @@ impl Filesystem {
for file in command.lines().skip(1) {
let parts = file.split_ascii_whitespace().collect_vec();
if parts[0] == "dir" {
/* no-op */
} else {
if parts[0] != "dir" {
let name = parts[1];
let size: usize = parts[0].parse().unwrap();
self.touch(name, size);
}
}
}
// [MARK] Helper functions for FromStr trait
fn size_under(&self, max_size: usize) -> usize {
self.root.borrow().size_under(max_size).1
}
fn purge(&self, total: usize, needed: usize) -> usize {
let used = self.root.borrow().size_under(0).2;
// to_be_freed >= needed - (total - used)
let to_be_freed = needed - (total - used);
self.root.borrow().smallest_bigger(to_be_freed).1
}
}
impl FromStr for Filesystem {
@ -168,59 +184,23 @@ impl FromStr for Filesystem {
}
}
type Input = Filesystem;
type Output = usize;
struct Day07;
impl Solution<Input, Output> for Day07 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_string(pathname).parse().unwrap()
}
fn part_1(input: &Input) -> Output {
input.root.borrow().size_under_100000().1
}
fn part_1(input: &Input) -> Output {
input.size_under(100000)
}
fn part_2(input: &Input) -> Output {
let (total, needed) = (70000000, 30000000);
let used = input.root.borrow().size_under_100000().2;
// to_be_freed >= needed - (total - used)
let to_be_freed = needed - (total - used);
input.root.borrow().smallest_bigger(to_be_freed).1
}
fn parse_input(pathname: &str) -> Input {
file_to_string(pathname).parse().unwrap()
fn part_2(input: &Input) -> Output {
input.purge(70000000, 30000000)
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day07.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day07::main()
}
#[cfg(test)]
mod day_07 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day07.txt");
assert_eq!(part_1(&sample), 95437);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day07.txt");
assert_eq!(part_2(&sample), 24933642);
}
}
test_sample!(day_07, Day07, 95437, 24933642);

View file

@ -2,10 +2,7 @@ use std::{cmp::max, collections::BTreeSet};
use aoc_2022::*;
use color_eyre::eyre::Result;
use itertools::Itertools;
use tracing::*;
use tracing_subscriber::EnvFilter;
type Input = Vec<Vec<i8>>;
type Output = usize;
@ -51,15 +48,6 @@ fn count_in_columns(trees: &Input, counted: &mut Visited) {
count_in(trees, counted, true)
}
fn part_1(input: &Input) -> Output {
let mut counted = Visited::new();
count_in_rows(input, &mut counted);
count_in_columns(input, &mut counted);
counted.len()
}
fn count_visible(trees: &Input, position: SignedPosition, diff: SignedPosition) -> usize {
let max_height = *index(trees, &position);
let mut visible = 0;
@ -91,17 +79,10 @@ fn compute_scenic_score(trees: &Input, x: isize, y: isize) -> usize {
.product()
}
fn part_2(input: &Input) -> Output {
(0..input.len())
.flat_map(|y| {
(0..input[y].len()).map(move |x| compute_scenic_score(input, x as isize, y as isize))
})
.max()
.unwrap()
}
fn parse_input(pathname: &str) -> Input {
file_to_string(pathname)
struct Day08;
impl Solution<Input, Output> for Day08 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_string(pathname)
.lines()
.map(|line| {
line.chars()
@ -109,40 +90,29 @@ fn parse_input(pathname: &str) -> Input {
.collect_vec()
})
.collect_vec()
}
fn part_1(input: &Input) -> Output {
let mut counted = Visited::new();
count_in_rows(input, &mut counted);
count_in_columns(input, &mut counted);
counted.len()
}
fn part_2(input: &Input) -> Output {
(0..input.len())
.flat_map(|y| {
(0..input[y].len()).map(move |x| compute_scenic_score(input, x as isize, y as isize))
})
.max()
.unwrap()
}
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.with_file(true)
.with_line_number(true)
.without_time()
.compact()
.init();
color_eyre::install()?;
let input = parse_input("inputs/day08.txt");
info!("Part 1: {}", part_1(&input));
info!("Part 2: {}", part_2(&input));
Ok(())
Day08::main()
}
#[cfg(test)]
mod day_08 {
use super::*;
#[test]
fn test_part_1() {
let sample = parse_input("samples/day08.txt");
assert_eq!(part_1(&sample), 21);
}
#[test]
fn test_part_2() {
let sample = parse_input("samples/day08.txt");
assert_eq!(part_2(&sample), 8);
}
}
test_sample!(day_08, Day08, 21, 8);