mirror of
https://github.com/kristoferssolo/Advent-of-Code.git
synced 2025-10-21 18:00:35 +00:00
Last changes
This commit is contained in:
parent
d9596becdf
commit
20d6c6bff0
15
2024/Cargo.lock
generated
15
2024/Cargo.lock
generated
@ -220,6 +220,21 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "day-08"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"divan",
|
||||||
|
"itertools",
|
||||||
|
"miette",
|
||||||
|
"nom",
|
||||||
|
"rstest",
|
||||||
|
"test-log",
|
||||||
|
"thiserror 2.0.3",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "divan"
|
name = "divan"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
|
|||||||
@ -6,16 +6,10 @@ fn main() {
|
|||||||
|
|
||||||
#[divan::bench]
|
#[divan::bench]
|
||||||
fn part1() {
|
fn part1() {
|
||||||
part1::process(divan::black_box(include_str!(
|
part1::process(divan::black_box(include_str!("../input1.txt",))).unwrap();
|
||||||
"../input1.txt",
|
|
||||||
)))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[divan::bench]
|
#[divan::bench]
|
||||||
fn part2() {
|
fn part2() {
|
||||||
part2::process(divan::black_box(include_str!(
|
part2::process(divan::black_box(include_str!("../input2.txt",))).unwrap();
|
||||||
"../input2.txt",
|
|
||||||
)))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,118 +0,0 @@
|
|||||||
use miette::{Diagnostic, Result};
|
|
||||||
use regex::Regex;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Diagnostic)]
|
|
||||||
pub enum MultiplicationError {
|
|
||||||
#[error("Failed to parse first value: {0}")]
|
|
||||||
#[diagnostic(code(calculator::parse_error::first_value))]
|
|
||||||
FirstValueParseError(String),
|
|
||||||
|
|
||||||
#[error("Failed to parse second value: {0}")]
|
|
||||||
#[diagnostic(code(calculator::parse_error::second_value))]
|
|
||||||
SecondValueParseError(String),
|
|
||||||
|
|
||||||
#[error("Invalid multiplication format")]
|
|
||||||
#[diagnostic(code(calculator::parse_error::format))]
|
|
||||||
InvalidFormat,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Multiplication(usize, usize);
|
|
||||||
|
|
||||||
impl Multiplication {
|
|
||||||
fn calculate(&self) -> usize {
|
|
||||||
self.0 * self.1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, U> TryFrom<(T, U)> for Multiplication
|
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
U: AsRef<str>,
|
|
||||||
{
|
|
||||||
type Error = MultiplicationError;
|
|
||||||
fn try_from(value: (T, U)) -> std::result::Result<Self, Self::Error> {
|
|
||||||
let first =
|
|
||||||
value.0.as_ref().parse().map_err(|_| {
|
|
||||||
MultiplicationError::FirstValueParseError(value.0.as_ref().to_string())
|
|
||||||
});
|
|
||||||
let second =
|
|
||||||
value.1.as_ref().parse().map_err(|_| {
|
|
||||||
MultiplicationError::SecondValueParseError(value.1.as_ref().to_string())
|
|
||||||
});
|
|
||||||
Ok(Self(first?, second?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Diagnostic)]
|
|
||||||
pub enum CalculatorError {
|
|
||||||
#[error("Failed to compile regex: {0}")]
|
|
||||||
#[diagnostic(code(calculator::regex_error))]
|
|
||||||
RegexError(#[from] regex::Error),
|
|
||||||
|
|
||||||
#[diagnostic(code(calculator::multiplication_error))]
|
|
||||||
#[error("Failed to parse multiplication: {0}")]
|
|
||||||
MultiplicationError(#[from] MultiplicationError),
|
|
||||||
|
|
||||||
#[error("Failed to process input: {0}")]
|
|
||||||
#[diagnostic(code(calculator::process_error))]
|
|
||||||
ProcessError(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Calculator {
|
|
||||||
do_re: Regex,
|
|
||||||
mult_re: Regex,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Calculator {
|
|
||||||
fn new() -> Result<Self, CalculatorError> {
|
|
||||||
Ok(Self {
|
|
||||||
do_re: Regex::new(r"^.*?don't\(\)|do\(\)(.*?)don't\(\)|do\(\).*$")?,
|
|
||||||
mult_re: Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)")?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_multiplications<'a>(
|
|
||||||
&'a self,
|
|
||||||
line: &'a str,
|
|
||||||
) -> impl Iterator<Item = Multiplication> + 'a {
|
|
||||||
self.mult_re.captures_iter(line).filter_map(|caps| {
|
|
||||||
Multiplication::try_from((caps.get(1)?.as_str(), caps.get(2)?.as_str())).ok()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_do<'a>(&'a self, line: &'a str) -> impl Iterator<Item = &'a str> + 'a {
|
|
||||||
self.do_re
|
|
||||||
.captures_iter(line)
|
|
||||||
.filter_map(|caps| caps.get(0).map(|m| m.as_str()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process(&self, input: &str) -> usize {
|
|
||||||
let value = input.lines().collect::<String>();
|
|
||||||
self.extract_do(&value)
|
|
||||||
.flat_map(|line| self.extract_multiplications(line))
|
|
||||||
.map(|mult| mult.calculate())
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
pub fn process(input: &str) -> Result<usize> {
|
|
||||||
let calculator = Calculator::new()?;
|
|
||||||
Ok(calculator.process(input))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_process() -> Result<()> {
|
|
||||||
let input = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))";
|
|
||||||
let result = 48;
|
|
||||||
assert_eq!(process(input)?, result);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
2024/day-08/Cargo.toml
Normal file
28
2024/day-08/Cargo.toml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[package]
|
||||||
|
name = "day-08"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
itertools.workspace = true
|
||||||
|
nom.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
miette.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
divan.workspace = true
|
||||||
|
rstest.workspace = true
|
||||||
|
test-log.workspace = true
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "day-08-bench"
|
||||||
|
path = "benches/benchmarks.rs"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[lints.clippy]
|
||||||
|
pedantic = "warn"
|
||||||
|
nursery = "warn"
|
||||||
21
2024/day-08/benches/benchmarks.rs
Normal file
21
2024/day-08/benches/benchmarks.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use day_08::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
divan::main();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[divan::bench]
|
||||||
|
fn part1() {
|
||||||
|
part1::process(divan::black_box(include_str!(
|
||||||
|
"../input1.txt",
|
||||||
|
)))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[divan::bench]
|
||||||
|
fn part2() {
|
||||||
|
part2::process(divan::black_box(include_str!(
|
||||||
|
"../input2.txt",
|
||||||
|
)))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
12
2024/day-08/src/bin/part1.rs
Normal file
12
2024/day-08/src/bin/part1.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use day_08::part1::process;
|
||||||
|
use miette::{Context, Result};
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let file = include_str!("../../input1.txt");
|
||||||
|
let result = process(file).context("process part 1")?;
|
||||||
|
println!("{result}");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
12
2024/day-08/src/bin/part2.rs
Normal file
12
2024/day-08/src/bin/part2.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use day_08::part2::process;
|
||||||
|
use miette::{Context, Result};
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let file = include_str!("../../input2.txt");
|
||||||
|
let result = process(file).context("process part 2")?;
|
||||||
|
println!("{result}");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
2
2024/day-08/src/lib.rs
Normal file
2
2024/day-08/src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod part1;
|
||||||
|
pub mod part2;
|
||||||
341
2024/day-08/src/part1.rs
Normal file
341
2024/day-08/src/part1.rs
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::Display,
|
||||||
|
ops::{Add, Sub},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
use miette::{Diagnostic, Result};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
struct Vec2 {
|
||||||
|
row: usize,
|
||||||
|
col: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vec2 {
|
||||||
|
const fn abs_diff(self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
row: self.row.abs_diff(other.row),
|
||||||
|
col: self.col.abs_diff(other.col),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn manhattan_distance(self, other: Self) -> usize {
|
||||||
|
let diff = self.abs_diff(other);
|
||||||
|
diff.row + diff.col
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec2> for (usize, usize) {
|
||||||
|
fn from(value: Vec2) -> Self {
|
||||||
|
(value.row, value.col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Vec2 {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
row: self.row + rhs.row,
|
||||||
|
col: self.col + rhs.col,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for Vec2 {
|
||||||
|
type Output = Self;
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Vec2 {
|
||||||
|
row: self.row.saturating_sub(rhs.row),
|
||||||
|
col: self.col.saturating_sub(rhs.col),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
enum Location {
|
||||||
|
Antenna(char),
|
||||||
|
Antinode,
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<char> for Location {
|
||||||
|
fn from(value: char) -> Self {
|
||||||
|
match value {
|
||||||
|
'.' => Self::Empty,
|
||||||
|
'#' => Self::Antinode,
|
||||||
|
ch => Self::Antenna(ch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Location {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let ch = match self {
|
||||||
|
Self::Antenna(ch) => *ch,
|
||||||
|
Self::Antinode => '#',
|
||||||
|
Self::Empty => '.',
|
||||||
|
};
|
||||||
|
write!(f, "{}", ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
|
enum RoofError {
|
||||||
|
#[error("Failed to parse roof")]
|
||||||
|
ParseError,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_diffs(positions: &[Vec2]) -> Vec<Vec2> {
|
||||||
|
positions
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(idx, &pos1)| {
|
||||||
|
positions[idx + 1..]
|
||||||
|
.iter()
|
||||||
|
.map(move |&pos2| pos1.abs_diff(pos2))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
struct Roof(Vec<Vec<Location>>);
|
||||||
|
|
||||||
|
impl Roof {
|
||||||
|
fn place_antinodes(&mut self) {
|
||||||
|
let antenna_positions = self.antenna_positions();
|
||||||
|
for (_, pos) in antenna_positions.iter() {
|
||||||
|
for i in 0..pos.len() {
|
||||||
|
for j in (i + 1)..pos.len() {
|
||||||
|
let (pos1, pos2) = (pos[i], pos[j]);
|
||||||
|
|
||||||
|
if let Some(antinode_pos) = self.find_antinode_position(pos1, pos2) {
|
||||||
|
self.0[antinode_pos.row][antinode_pos.col] = Location::Antinode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_antinode_position(&self, pos1: Vec2, pos2: Vec2) -> Option<Vec2> {
|
||||||
|
let diff = pos1.abs_diff(pos2);
|
||||||
|
let total_dist = diff.row + diff.col;
|
||||||
|
|
||||||
|
// Try each step between the antennas
|
||||||
|
for step in 0..=total_dist {
|
||||||
|
let row = if pos1.row < pos2.row {
|
||||||
|
pos1.row + step.min(diff.row)
|
||||||
|
} else {
|
||||||
|
pos1.row - step.min(diff.row)
|
||||||
|
};
|
||||||
|
|
||||||
|
let col = if pos1.col < pos2.col {
|
||||||
|
pos1.col + step.min(diff.col)
|
||||||
|
} else {
|
||||||
|
pos1.col - step.min(diff.col)
|
||||||
|
};
|
||||||
|
|
||||||
|
let candidate = Vec2 { row, col };
|
||||||
|
|
||||||
|
// Check if position is valid and equidistant
|
||||||
|
if row < self.0.len()
|
||||||
|
&& col < self.0[0].len()
|
||||||
|
&& matches!(self.0[row][col], Location::Empty)
|
||||||
|
{
|
||||||
|
let dist1 = pos1.manhattan_distance(candidate);
|
||||||
|
let dist2 = pos2.manhattan_distance(candidate);
|
||||||
|
if dist1 == dist2 {
|
||||||
|
return Some(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn antenna_positions(&self) -> HashMap<char, Vec<Vec2>> {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(row_idx, row)| {
|
||||||
|
row.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(move |(col_idx, col)| match col {
|
||||||
|
Location::Antenna(ch) => Some((
|
||||||
|
*ch,
|
||||||
|
Vec2 {
|
||||||
|
row: row_idx,
|
||||||
|
col: col_idx,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.fold(HashMap::new(), |mut acc, (key, pos)| {
|
||||||
|
acc.entry(key).or_default().push(pos);
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count(&self) -> usize {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(|row| {
|
||||||
|
row.iter()
|
||||||
|
.filter(|pos| matches!(pos, Location::Antinode))
|
||||||
|
.count()
|
||||||
|
})
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn row_len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn col_len(&self) -> usize {
|
||||||
|
self.0[0].len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_within_bounds(&self, pos: &Vec2) -> bool {
|
||||||
|
pos.row < self.row_len() && pos.col < self.col_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Roof {
|
||||||
|
type Err = RoofError;
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
let roof = s
|
||||||
|
.lines()
|
||||||
|
.map(|line| line.chars().map(Location::from).collect::<Vec<_>>())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
Ok(Self(roof))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Roof {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
for (idx, row) in self.0.iter().enumerate() {
|
||||||
|
for pos in row {
|
||||||
|
write!(f, "{}", pos)?;
|
||||||
|
}
|
||||||
|
if idx < self.0.len() - 1 {
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub fn process(input: &str) -> Result<usize> {
|
||||||
|
let mut roof = Roof::from_str(input)?;
|
||||||
|
roof.place_antinodes();
|
||||||
|
println!("{roof}");
|
||||||
|
Ok(roof.count())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process() -> Result<()> {
|
||||||
|
let input = "............
|
||||||
|
........0...
|
||||||
|
.....0......
|
||||||
|
.......0....
|
||||||
|
....0.......
|
||||||
|
......A.....
|
||||||
|
............
|
||||||
|
............
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
............
|
||||||
|
............";
|
||||||
|
let result = 14;
|
||||||
|
assert_eq!(process(input)?, result);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(
|
||||||
|
"..........
|
||||||
|
..........
|
||||||
|
..........
|
||||||
|
....a.....
|
||||||
|
..........
|
||||||
|
.....a....
|
||||||
|
..........
|
||||||
|
..........
|
||||||
|
..........
|
||||||
|
..........",
|
||||||
|
"..........
|
||||||
|
...#......
|
||||||
|
..........
|
||||||
|
....a.....
|
||||||
|
..........
|
||||||
|
.....a....
|
||||||
|
..........
|
||||||
|
......#...
|
||||||
|
..........
|
||||||
|
.........."
|
||||||
|
)]
|
||||||
|
/* #[case(
|
||||||
|
"..........
|
||||||
|
..........
|
||||||
|
..........
|
||||||
|
....a.....
|
||||||
|
........a.
|
||||||
|
.....a....
|
||||||
|
..........
|
||||||
|
..........
|
||||||
|
..........
|
||||||
|
..........",
|
||||||
|
"..........
|
||||||
|
...#......
|
||||||
|
#.........
|
||||||
|
....a.....
|
||||||
|
........a.
|
||||||
|
.....a....
|
||||||
|
..#.......
|
||||||
|
......#...
|
||||||
|
..........
|
||||||
|
.........."
|
||||||
|
)]
|
||||||
|
#[case(
|
||||||
|
"............
|
||||||
|
........0...
|
||||||
|
.....0......
|
||||||
|
.......0....
|
||||||
|
....0.......
|
||||||
|
......A.....
|
||||||
|
............
|
||||||
|
............
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
............
|
||||||
|
............",
|
||||||
|
"......#....#
|
||||||
|
...#....0...
|
||||||
|
....#0....#.
|
||||||
|
..#....0....
|
||||||
|
....0....#..
|
||||||
|
.#....A.....
|
||||||
|
...#........
|
||||||
|
#......#....
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
..........#.
|
||||||
|
..........#."
|
||||||
|
)] */
|
||||||
|
fn test_layout(#[case] input_str: &str, #[case] output_str: &str) -> Result<()> {
|
||||||
|
let mut input = Roof::from_str(input_str)?;
|
||||||
|
input.place_antinodes();
|
||||||
|
let output = Roof::from_str(output_str)?;
|
||||||
|
assert_eq!(input, output);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
21
2024/day-08/src/part2.rs
Normal file
21
2024/day-08/src/part2.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use miette::Result;
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub fn process(input: &str) -> Result<usize> {
|
||||||
|
todo!("day xx - part 2");
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process() -> Result<()> {
|
||||||
|
let input = "";
|
||||||
|
todo!("haven't built test yet");
|
||||||
|
let result = 0;
|
||||||
|
assert_eq!(process(input)?, result);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user