Add trait and macro to automamte some day setup

This commit is contained in:
HoLLy 2021-12-04 15:54:11 +01:00
Родитель e311b0cbdf
Коммит 44021d0b1e
11 изменённых файлов: 300 добавлений и 305 удалений

9
Cargo.lock сгенерированный
Просмотреть файл

@ -5,6 +5,9 @@ version = 3
[[package]]
name = "aoc-lib"
version = "0.1.0"
dependencies = [
"paste",
]
[[package]]
name = "atty"
@ -314,6 +317,12 @@ version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "paste"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
[[package]]
name = "plotters"
version = "0.3.1"

Просмотреть файл

@ -6,3 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
paste = "1.0.6"

Просмотреть файл

@ -1,3 +1,63 @@
pub use paste::paste;
use std::fmt::Display;
#[macro_export]
macro_rules! aoc_setup {
($type:ident $(, test $index:literal: $test_result:expr)*) => {
// TODO: pub use another macro that creates benchmarks?
fn main() {
aoc_lib::run($type);
}
$(
aoc_lib::paste! {
#[test]
fn [<solve_sample_part_ $index>]() {
let input = include_str!("../sample.txt");
let parsed = $type::parse_input(input);
assert_eq!($test_result, $type::[< solve_ $index >](&parsed));
}
}
)*
};
}
pub trait AdventOfCode {
type Input;
type Output;
fn parse_input(s: &str) -> Self::Input;
fn solve_1(input: &Self::Input) -> Self::Output;
fn solve_2(input: &Self::Input) -> Self::Output;
}
/// Run and time just part 1 of a. AdventOfCode solution.
pub fn run_part_1<T: AdventOfCode<Output = impl Display>>(_: T) {
let input = read_stdin();
let (parsed, parsed_time) = time(|| T::parse_input(&input));
let (solve_1, solve_1_time) = time(|| T::solve_1(&parsed));
println!("Solution to part 1: {}", solve_1);
println!("Parsing took: {:?}", parsed_time);
println!("Solving part 1 took: {:?}", solve_1_time);
}
pub fn run<T: AdventOfCode<Output = impl Display>>(_: T) {
let input = read_stdin();
let (parsed, parsed_time) = time(|| T::parse_input(&input));
let (solve_1, solve_1_time) = time(|| T::solve_1(&parsed));
let (solve_2, solve_2_time) = time(|| T::solve_2(&parsed));
println!("Solution to part 1: {}", solve_1);
println!("Solution to part 2: {}", solve_2);
println!("Parsing took: {:?}", parsed_time);
println!("Solving part 1 took: {:?}", solve_1_time);
println!("Solving part 2 took: {:?}", solve_2_time);
}
/// Executes some code and records the time it took to run
pub fn time<T, F>(fun: F) -> (T, std::time::Duration)
where

Просмотреть файл

@ -1,5 +1,6 @@
#![allow(dead_code)]
use aoc_lib::AdventOfCode;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[path = "../src/main.rs"]
@ -8,32 +9,32 @@ mod main;
fn bench_main(c: &mut Criterion) {
c.bench_function("parse input", |b| {
let input = include_str!("../input.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day1::parse_input(black_box(input)))
});
c.bench_function("solve 1", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day1::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day1::solve_1(black_box(&input)))
});
c.bench_function("solve 2", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day1::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day1::solve_2(black_box(&input)))
});
c.bench_function("parse sample input", |b| {
let input = include_str!("../sample.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day1::parse_input(black_box(input)))
});
c.bench_function("solve 1 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day1::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day1::solve_1(black_box(&input)))
});
c.bench_function("solve 2 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day1::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day1::solve_2(black_box(&input)))
});
}

Просмотреть файл

@ -1,41 +1,22 @@
use aoc_lib::*;
fn main() {
let input = read_stdin();
let (parsed, parsed_time) = time(|| parse_input(&input));
let (solve_1, solve_1_time) = time(|| solve_1(&parsed));
let (solve_2, solve_2_time) = time(|| solve_2(&parsed));
aoc_setup!(Day1, test 1: 7, test 2: 5);
println!("Solution to part 1: {}", solve_1);
println!("Solution to part 2: {}", solve_2);
pub struct Day1;
println!("Parsing took: {:?}", parsed_time);
println!("Solving part 1 took: {:?}", solve_1_time);
println!("Solving part 2 took: {:?}", solve_2_time);
}
pub fn parse_input(s: &str) -> Vec<usize> {
s.lines().map(|l| l.parse().unwrap()).collect()
}
pub fn solve_1(input: &[usize]) -> usize {
input.windows(2).filter(|w| w[0] < w[1]).count()
}
pub fn solve_2(input: &[usize]) -> usize {
input.windows(4).filter(|w| w[0] < w[3]).count()
}
#[test]
fn test_solve_1() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(7, solve_1(&parsed));
}
#[test]
fn test_solve_2() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(5, solve_2(&parsed));
impl AdventOfCode for Day1 {
type Input = Vec<usize>;
type Output = usize;
fn parse_input(s: &str) -> Self::Input {
s.lines().map(|l| l.parse().unwrap()).collect()
}
fn solve_1(input: &Self::Input) -> Self::Output {
input.windows(2).filter(|w| w[0] < w[1]).count()
}
fn solve_2(input: &Self::Input) -> Self::Output {
input.windows(4).filter(|w| w[0] < w[3]).count()
}
}

Просмотреть файл

@ -1,5 +1,6 @@
#![allow(dead_code)]
use aoc_lib::*;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[path = "../src/main.rs"]
@ -8,32 +9,32 @@ mod main;
fn bench_main(c: &mut Criterion) {
c.bench_function("parse input", |b| {
let input = include_str!("../input.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day2::parse_input(black_box(input)))
});
c.bench_function("solve 1", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day2::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day2::solve_1(black_box(&input)))
});
c.bench_function("solve 2", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day2::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day2::solve_2(black_box(&input)))
});
c.bench_function("parse sample input", |b| {
let input = include_str!("../sample.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day2::parse_input(black_box(input)))
});
c.bench_function("solve 1 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day2::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day2::solve_1(black_box(&input)))
});
c.bench_function("solve 2 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day2::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day2::solve_2(black_box(&input)))
});
}

Просмотреть файл

@ -1,5 +1,7 @@
use aoc_lib::*;
aoc_setup!(Day2, test 1: 150, test 2: 900);
#[derive(Clone, Copy)]
pub enum Direction {
Forward,
@ -7,69 +9,48 @@ pub enum Direction {
Up,
}
fn main() {
let input = read_stdin();
let (parsed, parsed_time) = time(|| parse_input(&input));
let (solve_1, solve_1_time) = time(|| solve_1(&parsed));
let (solve_2, solve_2_time) = time(|| solve_2(&parsed));
pub struct Day2;
println!("Solution to part 1: {}", solve_1);
println!("Solution to part 2: {}", solve_2);
impl AdventOfCode for Day2 {
type Input = Vec<(Direction, isize)>;
type Output = isize;
println!("Parsing took: {:?}", parsed_time);
println!("Solving part 1 took: {:?}", solve_1_time);
println!("Solving part 2 took: {:?}", solve_2_time);
}
pub fn parse_input(s: &str) -> Vec<(Direction, isize)> {
s.lines()
.map(|line| {
let mut split = line.split(' ');
(
match split.next().unwrap() {
"forward" => Direction::Forward,
"down" => Direction::Down,
"up" => Direction::Up,
_ => unreachable!(),
},
split.next().unwrap().parse().unwrap(),
)
})
.collect()
}
pub fn solve_1(input: &[(Direction, isize)]) -> isize {
let sub = input
.into_iter()
.fold((0, 0), |sub, &(dir, dist)| match dir {
Direction::Forward => (sub.0 + dist, sub.1),
Direction::Down => (sub.0, sub.1 + dist),
Direction::Up => (sub.0, sub.1 - dist),
});
sub.0 * sub.1
}
pub fn solve_2(input: &[(Direction, isize)]) -> isize {
let sub = input
.into_iter()
.fold((0, 0, 0), |sub, &(dir, dist)| match dir {
Direction::Forward => (sub.0 + dist, sub.1 + sub.2 * dist, sub.2),
Direction::Down => (sub.0, sub.1, sub.2 + dist),
Direction::Up => (sub.0, sub.1, sub.2 - dist),
});
sub.0 * sub.1
}
#[test]
fn test_solve_1() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(150, solve_1(&parsed));
}
#[test]
fn test_solve_2() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(900, solve_2(&parsed));
fn parse_input(s: &str) -> Self::Input {
s.lines()
.map(|line| {
let mut split = line.split(' ');
(
match split.next().unwrap() {
"forward" => Direction::Forward,
"down" => Direction::Down,
"up" => Direction::Up,
_ => unreachable!(),
},
split.next().unwrap().parse().unwrap(),
)
})
.collect()
}
fn solve_1(input: &Self::Input) -> Self::Output {
let sub = input
.into_iter()
.fold((0, 0), |sub, &(dir, dist)| match dir {
Direction::Forward => (sub.0 + dist, sub.1),
Direction::Down => (sub.0, sub.1 + dist),
Direction::Up => (sub.0, sub.1 - dist),
});
sub.0 * sub.1
}
fn solve_2(input: &Self::Input) -> Self::Output {
let sub = input
.into_iter()
.fold((0, 0, 0), |sub, &(dir, dist)| match dir {
Direction::Forward => (sub.0 + dist, sub.1 + sub.2 * dist, sub.2),
Direction::Down => (sub.0, sub.1, sub.2 + dist),
Direction::Up => (sub.0, sub.1, sub.2 - dist),
});
sub.0 * sub.1
}
}

Просмотреть файл

@ -1,5 +1,6 @@
#![allow(dead_code)]
use aoc_lib::AdventOfCode;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[path = "../src/main.rs"]
@ -8,32 +9,32 @@ mod main;
fn bench_main(c: &mut Criterion) {
c.bench_function("parse input", |b| {
let input = include_str!("../input.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day3::parse_input(black_box(input)))
});
c.bench_function("solve 1", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day3::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day3::solve_1(black_box(&input)))
});
c.bench_function("solve 2", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day3::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day3::solve_2(black_box(&input)))
});
c.bench_function("parse sample input", |b| {
let input = include_str!("../sample.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day3::parse_input(black_box(input)))
});
c.bench_function("solve 1 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day3::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day3::solve_1(black_box(&input)))
});
c.bench_function("solve 2 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day3::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day3::solve_2(black_box(&input)))
});
}

Просмотреть файл

@ -1,51 +1,44 @@
use aoc_lib::*;
pub struct Input(usize, Vec<usize>);
aoc_setup!(Day3, test 1: 198, test 2: 230);
fn main() {
let input = read_stdin();
let (parsed, parsed_time) = time(|| parse_input(&input));
let (solve_1, solve_1_time) = time(|| solve_1(&parsed));
let (solve_2, solve_2_time) = time(|| solve_2(&parsed));
pub struct Day3;
println!("Solution to part 1: {}", solve_1);
println!("Solution to part 2: {}", solve_2);
impl AdventOfCode for Day3 {
type Input = (usize, Vec<usize>);
type Output = usize;
println!("Parsing took: {:?}", parsed_time);
println!("Solving part 1 took: {:?}", solve_1_time);
println!("Solving part 2 took: {:?}", solve_2_time);
fn parse_input(s: &str) -> Self::Input {
(
s.lines().next().unwrap().len(),
s.lines()
.map(|l| usize::from_str_radix(l, 2).unwrap())
.collect(),
)
}
fn solve_1(input: &Self::Input) -> Self::Output {
let mask = (1 << input.0) - 1;
let half_len = input.1.len() / 2;
let gamma = (0..input.0)
.map(|i| (i, get_one_count_at_location(input.1.iter(), i) > half_len))
.fold(0, |acc, (i, set)| if set { acc | (1 << i) } else { acc });
let epsilon = (!gamma) & mask;
gamma * epsilon
}
fn solve_2(input: &Self::Input) -> Self::Output {
let part1 = solve_2_sub(input, false);
let part2 = solve_2_sub(input, true);
part1 * part2
}
}
pub fn parse_input(s: &str) -> Input {
Input(
s.lines().next().unwrap().len(),
s.lines()
.map(|l| usize::from_str_radix(l, 2).unwrap())
.collect(),
)
}
pub fn solve_1(input: &Input) -> usize {
let mask = (1 << input.0) - 1;
let half_len = input.1.len() / 2;
let gamma = (0..input.0)
.map(|i| (i, get_one_count_at_location(input.1.iter(), i) > half_len))
.fold(0, |acc, (i, set)| if set { acc | (1 << i) } else { acc });
let epsilon = (!gamma) & mask;
gamma * epsilon
}
pub fn solve_2(input: &Input) -> usize {
let part1 = solve_2_sub(input, false);
let part2 = solve_2_sub(input, true);
part1 * part2
}
fn solve_2_sub(input: &Input, reverse: bool) -> usize {
fn solve_2_sub(input: &(usize, Vec<usize>), reverse: bool) -> usize {
let full_mask = (1 << input.0) - 1;
let mut pattern = 0;
let mut pattern_len = 0;
@ -91,17 +84,3 @@ fn solve_2_sub(input: &Input, reverse: bool) -> usize {
fn get_one_count_at_location<'a>(items: impl Iterator<Item = &'a usize>, i: usize) -> usize {
items.filter(|&&n| (n & (1 << i)) > 0).count()
}
#[test]
fn test_solve_1() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(198, solve_1(&parsed));
}
#[test]
fn test_solve_2() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(230, solve_2(&parsed));
}

Просмотреть файл

@ -1,5 +1,6 @@
#![allow(dead_code)]
use aoc_lib::AdventOfCode;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[path = "../src/main.rs"]
@ -8,32 +9,32 @@ mod main;
fn bench_main(c: &mut Criterion) {
c.bench_function("parse input", |b| {
let input = include_str!("../input.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day4::parse_input(black_box(input)))
});
c.bench_function("solve 1", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day4::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day4::solve_1(black_box(&input)))
});
c.bench_function("solve 2", |b| {
let input = main::parse_input(include_str!("../input.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day4::parse_input(include_str!("../input.txt"));
b.iter(|| main::Day4::solve_2(black_box(&input)))
});
c.bench_function("parse sample input", |b| {
let input = include_str!("../sample.txt");
b.iter(|| main::parse_input(black_box(input)))
b.iter(|| main::Day4::parse_input(black_box(input)))
});
c.bench_function("solve 1 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_1(black_box(&input)))
let input = main::Day4::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day4::solve_1(black_box(&input)))
});
c.bench_function("solve 2 (sample input)", |b| {
let input = main::parse_input(include_str!("../sample.txt"));
b.iter(|| main::solve_2(black_box(&input)))
let input = main::Day4::parse_input(include_str!("../sample.txt"));
b.iter(|| main::Day4::solve_2(black_box(&input)))
});
}

Просмотреть файл

@ -1,7 +1,8 @@
use std::ops::IndexMut;
use aoc_lib::*;
use itertools::Itertools;
use std::ops::IndexMut;
aoc_setup!(Day4, test 1: 4512, test 2: 1924);
#[derive(Debug)]
pub struct Input(Vec<u8>, Vec<Board>);
@ -43,130 +44,109 @@ impl Board {
}
}
fn main() {
let input = read_stdin();
let (parsed, parsed_time) = time(|| parse_input(&input));
let (solve_1, solve_1_time) = time(|| solve_1(&parsed));
let (solve_2, solve_2_time) = time(|| solve_2(&parsed));
pub struct Day4;
println!("Solution to part 1: {}", solve_1);
println!("Solution to part 2: {}", solve_2);
impl AdventOfCode for Day4 {
type Input = Input;
type Output = usize;
println!("Parsing took: {:?}", parsed_time);
println!("Solving part 1 took: {:?}", solve_1_time);
println!("Solving part 2 took: {:?}", solve_2_time);
}
fn parse_input(s: &str) -> Self::Input {
let mut iter = s.lines().filter(|line| line.len() > 0);
pub fn parse_input(s: &str) -> Input {
let mut iter = s.lines().filter(|line| line.len() > 0);
let x = iter
.next()
.unwrap()
.split(',')
.map(|s| s.parse::<u8>().unwrap())
.collect();
let x = iter
.next()
.unwrap()
.split(',')
.map(|s| s.parse::<u8>().unwrap())
.collect();
let boards = iter
.chunks(5)
.into_iter()
.map(|chunk| {
let mut numbers = [0; 5 * 5];
for (i, n) in chunk.into_iter().enumerate() {
n.split(' ')
.filter(|x| x.len() > 0)
.enumerate()
.for_each(|(j, s)| {
numbers[i * 5 + j] = s.parse::<u8>().unwrap();
});
}
Board(numbers)
})
.collect();
Input(x, boards)
}
pub fn solve_1(input: &Input) -> usize {
let mut solve_mask = vec![0u32; input.1.len()];
let mut last_num = 0;
let board_index = input
.0
.iter()
.find_map(|&num| {
input.1.iter().enumerate().find_map(|(i, board)| {
board.update_mask(num, solve_mask.index_mut(i));
if Board::is_solved(solve_mask[i]) {
last_num = num as usize;
Some(i)
} else {
None
let boards = iter
.chunks(5)
.into_iter()
.map(|chunk| {
let mut numbers = [0; 5 * 5];
for (i, n) in chunk.into_iter().enumerate() {
n.split(' ')
.filter(|x| x.len() > 0)
.enumerate()
.for_each(|(j, s)| {
numbers[i * 5 + j] = s.parse::<u8>().unwrap();
});
}
Board(numbers)
})
})
.unwrap();
.collect();
input.1[board_index].get_unmarked_sum(solve_mask[board_index]) * last_num
}
Input(x, boards)
}
pub fn solve_2(input: &Input) -> usize {
let mut solve_mask = vec![0u32; input.1.len()];
let mut last_num = 0;
let mut solved_list = vec![0usize; (input.1.len() / (usize::BITS as usize)) + 1];
let mut last_solved = 0;
let mut last_mask = 0;
let mut solved_count = 0; // i'm too lazy to write a check against solved_list
fn solve_1(input: &Self::Input) -> Self::Output {
let mut solve_mask = vec![0u32; input.1.len()];
let mut last_num = 0;
input
.0
.iter()
.filter_map(|&num| {
input
.1
.iter()
.enumerate()
.filter_map(|(i, board)| {
let board_index = input
.0
.iter()
.find_map(|&num| {
input.1.iter().enumerate().find_map(|(i, board)| {
board.update_mask(num, solve_mask.index_mut(i));
if Board::is_solved(solve_mask[i]) {
last_num = num as usize;
Some(i)
} else {
None
}
})
})
.unwrap();
let solved_ref = solved_list.index_mut(i / (usize::BITS as usize));
let solved_bit_idx = i % (usize::BITS as usize);
input.1[board_index].get_unmarked_sum(solve_mask[board_index]) * last_num
}
if ((*solved_ref) & (1 << solved_bit_idx)) == 0 {
if Board::is_solved(solve_mask[i]) {
last_num = num as usize;
last_solved = i;
last_mask = solve_mask[last_solved];
*solved_ref |= 1 << solved_bit_idx;
solved_count += 1;
fn solve_2(input: &Self::Input) -> Self::Output {
let mut solve_mask = vec![0u32; input.1.len()];
let mut last_num = 0;
let mut solved_list = vec![0usize; (input.1.len() / (usize::BITS as usize)) + 1];
let mut last_solved = 0;
let mut last_mask = 0;
let mut solved_count = 0; // i'm too lazy to write a check against solved_list
// check if everything is solved
if solved_count == input.1.len() {
return Some(());
input
.0
.iter()
.filter_map(|&num| {
input
.1
.iter()
.enumerate()
.filter_map(|(i, board)| {
board.update_mask(num, solve_mask.index_mut(i));
let solved_ref = solved_list.index_mut(i / (usize::BITS as usize));
let solved_bit_idx = i % (usize::BITS as usize);
if ((*solved_ref) & (1 << solved_bit_idx)) == 0 {
if Board::is_solved(solve_mask[i]) {
last_num = num as usize;
last_solved = i;
last_mask = solve_mask[last_solved];
*solved_ref |= 1 << solved_bit_idx;
solved_count += 1;
// check if everything is solved
if solved_count == input.1.len() {
return Some(());
}
}
}
}
None
})
.next()
})
.next()
.unwrap();
None
})
.next()
})
.next()
.unwrap();
input.1[last_solved].get_unmarked_sum(last_mask) * last_num
}
#[test]
fn test_solve_1() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(4512, solve_1(&parsed));
}
#[test]
fn test_solve_2() {
let input = include_str!("../sample.txt");
let parsed = parse_input(input);
assert_eq!(1924, solve_2(&parsed));
input.1[last_solved].get_unmarked_sum(last_mask) * last_num
}
}