From 11776c6f7e47d58dc1c3b6ac370baa6c04e5a83f Mon Sep 17 00:00:00 2001 From: Jack Kinsey Date: Wed, 11 Dec 2024 03:04:22 -0500 Subject: [PATCH] Improve solution runner --- src/day00.rs | 26 ++++++++++++------- src/day01.rs | 28 +++++++++++--------- src/day02.rs | 36 ++++++++++++++++---------- src/day03.rs | 28 +++++++++++--------- src/day04.rs | 24 ++++++++++------- src/day05.rs | 34 ++++++++++++++---------- src/day06.rs | 35 +++++++++++++++---------- src/day07.rs | 28 +++++++++++--------- src/day08.rs | 36 ++++++++++++++++---------- src/day09.rs | 28 +++++++++++--------- src/day10.rs | 34 ++++++++++++------------ src/day11.rs | 33 +++++++++++++++--------- src/main.rs | 73 ++++++++++++++++++++++++++++++---------------------- 13 files changed, 261 insertions(+), 182 deletions(-) diff --git a/src/day00.rs b/src/day00.rs index 9025154..479edc4 100644 --- a/src/day00.rs +++ b/src/day00.rs @@ -1,19 +1,13 @@ -fn input() -> &'static str { - include_str!("../input/day00.txt") -} - fn parse(input: &str) -> () { todo!() } -pub fn part1() { - let n = 0; - println!("Day 0 Part 1: {}", n); +pub fn part1(input: &str) -> u64 { + 0 } -pub fn part2() { - let n = 0; - println!("Day 0 Part 2: {}", n); +pub fn part2(input: &str) -> u64 { + 0 } #[cfg(test)] @@ -26,4 +20,16 @@ mod test { fn test_parse() { assert_eq!(parse(INPUT_STR), parse(INPUT_STR)) } + + #[test] + #[ignore] + fn test_part1() { + assert_eq!(part1(&crate::input(0).unwrap()), 0) + } + + #[test] + #[ignore] + fn test_part2() { + assert_eq!(part2(&crate::input(0).unwrap()), 0) + } } diff --git a/src/day01.rs b/src/day01.rs index b022310..2fb2732 100644 --- a/src/day01.rs +++ b/src/day01.rs @@ -1,9 +1,5 @@ use std::collections::HashMap; -fn input() -> &'static str { - include_str!("../input/day01.txt") -} - fn parse(input: &str) -> (Vec, Vec) { let mut left = vec![]; let mut right = vec![]; @@ -35,16 +31,14 @@ fn similarity(left: &mut [u32], right: &mut [u32]) -> u32 { left.iter().map(|n| n * counts.get(n).unwrap_or(&0)).sum() } -pub fn part1() { - let (mut left, mut right) = parse(input()); - let d = distance(&mut left, &mut right); - println!("Day 1 Part 1: {}", d); +pub fn part1(input: &str) -> u64 { + let (mut left, mut right) = parse(input); + distance(&mut left, &mut right).into() } -pub fn part2() { - let (mut left, mut right) = parse(input()); - let d = similarity(&mut left, &mut right); - println!("Day 1 Part 2: {}", d); +pub fn part2(input: &str) -> u64 { + let (mut left, mut right) = parse(input); + similarity(&mut left, &mut right).into() } #[cfg(test)] @@ -72,4 +66,14 @@ mod test { let (mut left, mut right) = parse(INPUT_STR); assert_eq!(similarity(&mut left, &mut right), 31) } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(1).unwrap()), 1151792) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(1).unwrap()), 21790168) + } } diff --git a/src/day02.rs b/src/day02.rs index 39148fd..75c6243 100644 --- a/src/day02.rs +++ b/src/day02.rs @@ -1,7 +1,3 @@ -fn input() -> &'static str { - include_str!("../input/day02.txt") -} - fn parse(input: &str) -> Vec> { input .split_terminator('\n') @@ -46,20 +42,24 @@ fn is_safe_dampened(d: &[i32]) -> bool { .any(|x| x) } -pub fn part1() { - let vecs = parse(input()); - let n = vecs.iter().map(|v| is_safe(v)).filter(|&x| x).count(); - println!("Day 2 Part 1: {}", n); +pub fn part1(input: &str) -> u64 { + parse(input) + .iter() + .map(|v| is_safe(v)) + .filter(|&x| x) + .count() + .try_into() + .unwrap() } -pub fn part2() { - let vecs = parse(input()); - let n = vecs +pub fn part2(input: &str) -> u64 { + parse(input) .iter() .map(|v| is_safe_dampened(v)) .filter(|&x| x) - .count(); - println!("Day 2 Part 2: {}", n); + .count() + .try_into() + .unwrap() } #[cfg(test)] @@ -116,4 +116,14 @@ mod test { vec![true, false, false, true, true, true] ) } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(2).unwrap()), 202) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(2).unwrap()), 271) + } } diff --git a/src/day03.rs b/src/day03.rs index e0bf43c..136e1cb 100644 --- a/src/day03.rs +++ b/src/day03.rs @@ -1,9 +1,5 @@ use regex::Regex; -fn input() -> &'static str { - include_str!("../input/day03.txt") -} - #[derive(Debug, Eq, PartialEq, Copy, Clone)] enum Op { Do, @@ -48,16 +44,14 @@ fn exec(prog: &[Op]) -> u32 { .1 } -pub fn part1() { - let ops = parse(input()); - let n: u32 = ops.iter().map(|o| eval(true, o).1).sum(); - println!("Day 3 Part 1: {}", n); +pub fn part1(input: &str) -> u64 { + let ops = parse(input); + ops.iter().map(|o| eval(true, o).1).sum::().into() } -pub fn part2() { - let ops = parse(input()); - let n: u32 = exec(&ops); - println!("Day 3 Part 2: {}", n); +pub fn part2(input: &str) -> u64 { + let ops = parse(input); + exec(&ops).into() } #[cfg(test)] @@ -97,4 +91,14 @@ mod test { fn test_exec() { assert_eq!(exec(&parse(INPUT_STR2)), 48); } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(3).unwrap()), 184122457) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(3).unwrap()), 107862689) + } } diff --git a/src/day04.rs b/src/day04.rs index 1e47365..8711642 100644 --- a/src/day04.rs +++ b/src/day04.rs @@ -1,7 +1,3 @@ -fn input() -> &'static str { - include_str!("../input/day04.txt") -} - #[derive(Debug, Eq, PartialEq, Copy, Clone)] enum Char { X, @@ -132,14 +128,12 @@ fn check_as_for_xmas(chars: &[Vec]) -> usize { .sum() } -pub fn part1() { - let n = check_xs_for_xmas(&parse(input())); - println!("Day 4 Part 1: {}", n); +pub fn part1(input: &str) -> u64 { + check_xs_for_xmas(&parse(input)).try_into().unwrap() } -pub fn part2() { - let n = check_as_for_xmas(&parse(input())); - println!("Day 4 Part 2: {}", n); +pub fn part2(input: &str) -> u64 { + check_as_for_xmas(&parse(input)).try_into().unwrap() } #[cfg(test)] @@ -231,4 +225,14 @@ mod test { fn test_check_as() { assert_eq!(check_as_for_xmas(&parse(INPUT_STR)), 9) } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(4).unwrap()), 2406) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(4).unwrap()), 1807) + } } diff --git a/src/day05.rs b/src/day05.rs index efbb7b2..aa59dc1 100644 --- a/src/day05.rs +++ b/src/day05.rs @@ -1,10 +1,6 @@ use std::collections::{HashMap, HashSet}; use std::rc::Rc; -fn input() -> &'static str { - include_str!("../input/day05.txt") -} - type PageSet = HashSet; type PageRel = HashMap; @@ -84,27 +80,27 @@ fn get_middle(run: &[Page]) -> u8 { run[(run.len() + 1) / 2].num } -pub fn part1() { - let pages = parse(input()); - let n: u32 = pages +pub fn part1(input: &str) -> u64 { + let pages = parse(input); + pages .iter() .filter(|p| p.is_sorted()) .map(|p| -> u32 { get_middle(p).into() }) - .sum(); - println!("Day 5 Part 1: {}", n); + .sum::() + .into() } -pub fn part2() { - let mut pages = parse(input()); - let n: u32 = pages +pub fn part2(input: &str) -> u64 { + let mut pages = parse(input); + pages .iter_mut() .filter(|p| !p.is_sorted()) .map(|p| -> u32 { p.sort(); get_middle(p).into() }) - .sum(); - println!("Day 5 Part 2: {}", n); + .sum::() + .into() } #[cfg(test)] @@ -152,4 +148,14 @@ mod test { assert!(!&pages[4].is_sorted()); assert!(!&pages[5].is_sorted()); } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(5).unwrap()), 6251) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(5).unwrap()), 7314) + } } diff --git a/src/day06.rs b/src/day06.rs index be0daea..6948f99 100644 --- a/src/day06.rs +++ b/src/day06.rs @@ -1,9 +1,5 @@ use std::collections::HashSet; -fn input() -> &'static str { - include_str!("../input/day06.txt") -} - #[derive(Debug, Eq, PartialEq, Copy, Clone)] enum Dir { N, @@ -163,23 +159,24 @@ impl Iterator for GuardWalk<'_> { } } -pub fn part1() { - let n = GuardWalk::new(&parse(input())) +pub fn part1(input: &str) -> u64 { + GuardWalk::new(&parse(input)) .collect::>() - .len(); - println!("Day 6 Part 1: {}", n); + .len() + .try_into() + .unwrap() } -pub fn part2() { - let map = parse(input()); +pub fn part2(input: &str) -> u64 { + let map = parse(input); let walk = GuardWalk::new(&map); let guard_pos = walk.find_guard(); - let n = walk - .collect::>() + walk.collect::>() .iter() .filter(|&&p| GuardWalk::new_blocked(&map, p, guard_pos).has_cycle()) - .count(); - println!("Day 6 Part 2: {}", n); + .count() + .try_into() + .unwrap() } #[cfg(test)] @@ -262,4 +259,14 @@ mod test { 6 ) } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(6).unwrap()), 5516) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(6).unwrap()), 2008) + } } diff --git a/src/day07.rs b/src/day07.rs index d8e3d9d..271579b 100644 --- a/src/day07.rs +++ b/src/day07.rs @@ -1,7 +1,3 @@ -fn input() -> &'static str { - include_str!("../input/day07.txt") -} - fn parse(input: &str) -> Vec<(u64, Vec)> { input .lines() @@ -100,22 +96,20 @@ fn check_ops_with_cat(&(lhs, rhs): &&(u64, Vec)) -> bool { OpString::new_with_cat(rhs.len()).any(|ops| *lhs == op_eval(rhs, &ops)) } -pub fn part1() { - let n: u64 = parse(input()) +pub fn part1(input: &str) -> u64 { + parse(input) .iter() .filter(check_ops) .map(|&(lhs, _)| lhs) - .sum(); - println!("Day 7 Part 1: {}", n); + .sum() } -pub fn part2() { - let n: u64 = parse(input()) +pub fn part2(input: &str) -> u64 { + parse(input) .iter() .filter(check_ops_with_cat) .map(|&(lhs, _)| lhs) - .sum(); - println!("Day 7 Part 2: {}", n); + .sum() } #[cfg(test)] @@ -211,4 +205,14 @@ mod test { [190, 3267, 156, 7290, 192, 292] ) } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(7).unwrap()), 7885693428401) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(7).unwrap()), 8398052607990) + } } diff --git a/src/day08.rs b/src/day08.rs index 77b7930..fad6fab 100644 --- a/src/day08.rs +++ b/src/day08.rs @@ -1,10 +1,6 @@ use std::collections::{HashMap, HashSet}; use std::ops::{Add, Sub}; -fn input() -> &'static str { - include_str!("../input/day08.txt") -} - #[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)] struct Point(i32, i32); @@ -84,24 +80,26 @@ fn find_antinodes(bound: i32, pos: &[Point]) -> impl Iterator + us .flat_map(move |(a, b)| get_colinear_points(bound, *a, *b)) } -pub fn part1() { - let size: i32 = input().lines().count().try_into().unwrap(); - let n = parse(input()) +pub fn part1(input: &str) -> u64 { + let size: i32 = input.lines().count().try_into().unwrap(); + parse(input) .iter() .flat_map(|(_, pos)| find_nearby_antinodes(size, pos)) .collect::>() - .len(); - println!("Day 8 Part 1: {}", n); + .len() + .try_into() + .unwrap() } -pub fn part2() { - let size: i32 = input().lines().count().try_into().unwrap(); - let n = parse(input()) +pub fn part2(input: &str) -> u64 { + let size: i32 = input.lines().count().try_into().unwrap(); + parse(input) .iter() .flat_map(|(_, pos)| find_antinodes(size, pos)) .collect::>() - .len(); - println!("Day 8 Part 2: {}", n); + .len() + .try_into() + .unwrap() } #[cfg(test)] @@ -225,4 +223,14 @@ mod test { 34 ); } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(8).unwrap()), 336) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(8).unwrap()), 1131) + } } diff --git a/src/day09.rs b/src/day09.rs index 34f4202..612dace 100644 --- a/src/day09.rs +++ b/src/day09.rs @@ -1,7 +1,3 @@ -fn input() -> &'static str { - include_str!("../input/day09.txt") -} - type DiskMap = Option; fn parse(input: &str) -> Vec { @@ -95,18 +91,16 @@ fn checksum(disk: &[DiskMap]) -> u64 { .sum() } -pub fn part1() { - let mut map = parse(input()); +pub fn part1(input: &str) -> u64 { + let mut map = parse(input); fragment(&mut map); - let n = checksum(&map); - println!("Day 9 Part 1: {}", n); + checksum(&map) } -pub fn part2() { - let mut disk = parse(input()); +pub fn part2(input: &str) -> u64 { + let mut disk = parse(input); compact(&mut disk); - let n = checksum(&disk); - println!("Day 9 Part 2: {}", n); + checksum(&disk) } #[cfg(test)] @@ -262,4 +256,14 @@ mod test { compact(&mut disk); assert_eq!(checksum(&disk), 2858); } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(9).unwrap()), 6225730762521) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(9).unwrap()), 6250605700557) + } } diff --git a/src/day10.rs b/src/day10.rs index d61cf65..9efffe7 100644 --- a/src/day10.rs +++ b/src/day10.rs @@ -1,10 +1,6 @@ use std::collections::HashSet; use std::ops::{Add, Index, Sub}; -fn input() -> &'static str { - include_str!("../input/day10.txt") -} - #[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)] struct Point(i32, i32); @@ -106,22 +102,18 @@ fn parse(input: &str) -> Map { .collect()) } -pub fn part1() { - let map = parse(input()); - let n: u64 = map - .find_height(0) +pub fn part1(input: &str) -> u64 { + let map = parse(input); + map.find_height(0) .map(|p| map.count_reachable_heights(&p)) - .sum(); - println!("Day 10 Part 1: {}", n); + .sum() } -pub fn part2() { - let map = parse(input()); - let n: u64 = map - .find_height(0) +pub fn part2(input: &str) -> u64 { + let map = parse(input); + map.find_height(0) .map(|p| map.count_unique_trails(&p)) - .sum(); - println!("Day 10 Part 2: {}", n); + .sum() } #[cfg(test)] @@ -191,4 +183,14 @@ mod test { assert_eq!(map.count_unique_trails(&Point(6, 6)), 8); assert_eq!(map.count_unique_trails(&Point(7, 1)), 5); } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(10).unwrap()), 617) + } + + #[test] + fn test_part2() { + assert_eq!(part2(&crate::input(10).unwrap()), 1477) + } } diff --git a/src/day11.rs b/src/day11.rs index d63dcf1..52a88ce 100644 --- a/src/day11.rs +++ b/src/day11.rs @@ -1,7 +1,3 @@ -fn input() -> &'static str { - include_str!("../input/day11.txt") -} - fn parse(input: &str) -> Vec { input .split_whitespace() @@ -28,23 +24,25 @@ fn iterate(stones: &[u64]) -> Vec { .collect() } -pub fn part1() { - let n = std::iter::successors(Some(parse(input())), |v| Some(iterate(v))) +pub fn part1(input: &str) -> u64 { + std::iter::successors(Some(parse(input)), |v| Some(iterate(v))) .take(26) .last() .unwrap() - .len(); - println!("Day 11 Part 1: {}", n); + .len() + .try_into() + .unwrap() } -pub fn part2() { +pub fn part2(input: &str) -> u64 { // lol no - let n = std::iter::successors(Some(parse(input())), |v| Some(iterate(v))) + std::iter::successors(Some(parse(input)), |v| Some(iterate(v))) .take(76) .last() .unwrap() - .len(); - println!("Day 11 Part 2: {}", n); + .len() + .try_into() + .unwrap() } #[cfg(test)] @@ -79,4 +77,15 @@ mod test { ] ) } + + #[test] + fn test_part1() { + assert_eq!(part1(&crate::input(11).unwrap()), 212655) + } + + #[test] + #[ignore] + fn test_part2() { + assert_eq!(part2(&crate::input(11).unwrap()), 0) + } } diff --git a/src/main.rs b/src/main.rs index 1e16e0d..80cc634 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,50 +24,61 @@ pub mod day11; // pub mod day24; // pub mod day25; -type Part = fn(); +type Part = fn(&str) -> u64; const DAYS: &[(Part, Part)] = &[ - (day01::part1 as fn(), day01::part2 as fn()), - (day02::part1 as fn(), day02::part2 as fn()), - (day03::part1 as fn(), day03::part2 as fn()), - (day04::part1 as fn(), day04::part2 as fn()), - (day05::part1 as fn(), day05::part2 as fn()), - (day06::part1 as fn(), day06::part2 as fn()), - (day07::part1 as fn(), day07::part2 as fn()), - (day08::part1 as fn(), day08::part2 as fn()), - (day09::part1 as fn(), day09::part2 as fn()), - (day10::part1 as fn(), day10::part2 as fn()), - (day11::part1 as fn(), day11::part2 as fn()), - // (day12::part1 as fn(), day12::part2 as fn()), - // (day13::part1 as fn(), day13::part2 as fn()), - // (day14::part1 as fn(), day14::part2 as fn()), - // (day15::part1 as fn(), day15::part2 as fn()), - // (day16::part1 as fn(), day16::part2 as fn()), - // (day17::part1 as fn(), day17::part2 as fn()), - // (day18::part1 as fn(), day18::part2 as fn()), - // (day19::part1 as fn(), day19::part2 as fn()), - // (day20::part1 as fn(), day20::part2 as fn()), - // (day21::part1 as fn(), day21::part2 as fn()), - // (day22::part1 as fn(), day22::part2 as fn()), - // (day23::part1 as fn(), day23::part2 as fn()), - // (day24::part1 as fn(), day24::part2 as fn()), - // (day25::part1 as fn(), day25::part2 as fn()), + (day01::part1, day01::part2), + (day02::part1, day02::part2), + (day03::part1, day03::part2), + (day04::part1, day04::part2), + (day05::part1, day05::part2), + (day06::part1, day06::part2), + (day07::part1, day07::part2), + (day08::part1, day08::part2), + (day09::part1, day09::part2), + (day10::part1, day10::part2), + (day11::part1, day11::part2), + // (day12::part1, day12::part2), + // (day13::part1, day13::part2), + // (day14::part1, day14::part2), + // (day15::part1, day15::part2), + // (day16::part1, day16::part2), + // (day17::part1, day17::part2), + // (day18::part1, day18::part2), + // (day19::part1, day19::part2), + // (day20::part1, day20::part2), + // (day21::part1, day21::part2), + // (day22::part1, day22::part2), + // (day23::part1, day23::part2), + // (day24::part1, day24::part2), + // (day25::part1, day25::part2), ]; +fn input(day: usize) -> std::io::Result { + let file = std::fs::File::open(format!("input/day{:02}.txt", day))?; + std::io::read_to_string(file) +} + fn main() { let args: Vec = std::env::args().collect(); let arg = args.get(1).expect("Please provide a day."); if arg == "all" { - for day in DAYS { - day.0(); - day.1(); + for (day, i) in DAYS.iter().zip(1..) { + let input = input(i).unwrap().to_string(); + let p1 = day.0(&input); + println!("Day {} Part 1: {}", i, p1); + let p2 = day.1(&input); + println!("Day {} Part 2: {}", i, p2); } } else { let day: usize = arg.parse().expect("The day should be a number."); if day < 1 || day > DAYS.len() { panic!("That day hasn't been implemented yet!"); } - DAYS[day - 1].0(); - DAYS[day - 1].1(); + let input = input(day).unwrap().to_string(); + let p1 = DAYS[day - 1].0(&input); + println!("Day {} Part 1: {}", day, p1); + let p2 = DAYS[day - 1].1(&input); + println!("Day {} Part 2: {}", day, p2); } } -- 2.38.5