feat: day 8
This commit is contained in:
parent
e01ba930ff
commit
1e9030960d
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7"]
|
full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8"]
|
||||||
default = ["full"]
|
default = ["full"]
|
||||||
day1 = []
|
day1 = []
|
||||||
day2 = []
|
day2 = []
|
||||||
|
@ -13,6 +13,7 @@ day4 = []
|
||||||
day5 = []
|
day5 = []
|
||||||
day6 = []
|
day6 = []
|
||||||
day7 = []
|
day7 = []
|
||||||
|
day8 = []
|
||||||
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
12
inputs/day08/example.txt
Normal file
12
inputs/day08/example.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
............
|
||||||
|
........0...
|
||||||
|
.....0......
|
||||||
|
.......0....
|
||||||
|
....0.......
|
||||||
|
......A.....
|
||||||
|
............
|
||||||
|
............
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
............
|
||||||
|
............
|
188
src/day08.rs
Normal file
188
src/day08.rs
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
#![allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
|
pub fn pt1(input: &str) -> usize {
|
||||||
|
let char_positions = input
|
||||||
|
.lines()
|
||||||
|
.map(str::chars)
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(y, line)| line.enumerate().map(move |(x, char)| (char, x, y)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let dims = (input.lines().next().unwrap().len(), input.lines().count());
|
||||||
|
debug!("dims: {dims:?}");
|
||||||
|
let node_positions = char_positions
|
||||||
|
.iter()
|
||||||
|
.filter(|(c, _, _)| *c != '.')
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let unique_nodes = node_positions
|
||||||
|
.iter()
|
||||||
|
.map(|(c, _, _)| *c)
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
let mut antinode_positions = HashSet::<(usize, usize)>::new();
|
||||||
|
for node in unique_nodes {
|
||||||
|
let matching_node_positions = node_positions
|
||||||
|
.iter()
|
||||||
|
.filter(|(c, _, _)| *c == node)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter();
|
||||||
|
for (_, node_x, node_y) in matching_node_positions.clone() {
|
||||||
|
for (_, other_node_x, other_node_y) in matching_node_positions.clone() {
|
||||||
|
trace!(
|
||||||
|
"comparing ({node_x}, {node_y}) with ({other_node_x}, {other_node_y}): {:?}, {:?}",
|
||||||
|
node_x.cmp(other_node_x), node_y.cmp(other_node_y)
|
||||||
|
);
|
||||||
|
if node_x == other_node_x && node_y == other_node_y {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let dx = *node_x as isize - *other_node_x as isize;
|
||||||
|
let dy = *node_y as isize - *other_node_y as isize;
|
||||||
|
let prev_x = *node_x as isize + dx;
|
||||||
|
let prev_y = *node_y as isize + dy;
|
||||||
|
let post_x = *other_node_x as isize - dx;
|
||||||
|
let post_y = *other_node_y as isize - dy;
|
||||||
|
if prev_x >= 0
|
||||||
|
&& (prev_x as usize) < dims.0
|
||||||
|
&& prev_y >= 0
|
||||||
|
&& (prev_y as usize) < dims.1
|
||||||
|
{
|
||||||
|
antinode_positions.insert((prev_x as usize, prev_y as usize));
|
||||||
|
}
|
||||||
|
if post_x >= 0
|
||||||
|
&& (post_x as usize) < dims.0
|
||||||
|
&& post_y >= 0
|
||||||
|
&& (post_y as usize) < dims.1
|
||||||
|
{
|
||||||
|
antinode_positions.insert((post_x as usize, post_y as usize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("antinodes for {node}: {antinode_positions:?}");
|
||||||
|
}
|
||||||
|
let new_map = input
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(y, line)| {
|
||||||
|
line.chars()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(x, c)| {
|
||||||
|
if c != '.' || !antinode_positions.contains(&(x, y)) {
|
||||||
|
c
|
||||||
|
} else {
|
||||||
|
'#'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
debug!("new Map: \n{new_map}");
|
||||||
|
antinode_positions.len()
|
||||||
|
}
|
||||||
|
// 225 is too high
|
||||||
|
pub fn pt2(input: &str) -> usize {
|
||||||
|
let char_positions = input
|
||||||
|
.lines()
|
||||||
|
.map(str::chars)
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(y, line)| line.enumerate().map(move |(x, char)| (char, x, y)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let dims = (input.lines().next().unwrap().len(), input.lines().count());
|
||||||
|
debug!("dims: {dims:?}");
|
||||||
|
let node_positions = char_positions
|
||||||
|
.iter()
|
||||||
|
.filter(|(c, _, _)| *c != '.')
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let unique_nodes = node_positions
|
||||||
|
.iter()
|
||||||
|
.map(|(c, _, _)| *c)
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
let mut antinode_positions = HashSet::<(usize, usize)>::new();
|
||||||
|
for node in unique_nodes {
|
||||||
|
let matching_node_positions = node_positions
|
||||||
|
.iter()
|
||||||
|
.filter(|(c, _, _)| *c == node)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter();
|
||||||
|
for (_, node_x, node_y) in matching_node_positions.clone() {
|
||||||
|
for (_, other_node_x, other_node_y) in matching_node_positions.clone() {
|
||||||
|
trace!(
|
||||||
|
"comparing ({node_x}, {node_y}) with ({other_node_x}, {other_node_y}): {:?}, {:?}",
|
||||||
|
node_x.cmp(other_node_x), node_y.cmp(other_node_y)
|
||||||
|
);
|
||||||
|
if node_x == other_node_x && node_y == other_node_y {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let dx = *node_x as isize - *other_node_x as isize;
|
||||||
|
let dy = *node_y as isize - *other_node_y as isize;
|
||||||
|
let mut prev_x = *node_x as isize;
|
||||||
|
let mut prev_y = *node_y as isize;
|
||||||
|
while prev_x >= 0
|
||||||
|
&& (prev_x as usize) < dims.0
|
||||||
|
&& prev_y >= 0
|
||||||
|
&& (prev_y as usize) < dims.1
|
||||||
|
{
|
||||||
|
antinode_positions.insert((prev_x as usize, prev_y as usize));
|
||||||
|
prev_x += dx;
|
||||||
|
prev_y += dy;
|
||||||
|
}
|
||||||
|
let mut post_x = *other_node_x as isize;
|
||||||
|
let mut post_y = *other_node_y as isize;
|
||||||
|
while post_x >= 0
|
||||||
|
&& (post_x as usize) < dims.0
|
||||||
|
&& post_y >= 0
|
||||||
|
&& (post_y as usize) < dims.1
|
||||||
|
{
|
||||||
|
antinode_positions.insert((post_x as usize, post_y as usize));
|
||||||
|
post_x -= dx;
|
||||||
|
post_y -= dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("antinodes for {node}: {antinode_positions:?}");
|
||||||
|
}
|
||||||
|
let new_map = input
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(y, line)| {
|
||||||
|
line.chars()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(x, c)| {
|
||||||
|
if c != '.' || !antinode_positions.contains(&(x, y)) {
|
||||||
|
c
|
||||||
|
} else {
|
||||||
|
'#'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
debug!("new Map: \n{new_map}");
|
||||||
|
antinode_positions.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use tracing_test::traced_test;
|
||||||
|
|
||||||
|
use super::{pt1, pt2};
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
|
||||||
|
#[traced_test]
|
||||||
|
#[test]
|
||||||
|
pub fn test_pt1() {
|
||||||
|
let input =
|
||||||
|
read_to_string("./inputs/day08/example.txt").expect("Missing example.txt for day08");
|
||||||
|
assert_eq!(pt1(&input), 14)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[traced_test]
|
||||||
|
#[test]
|
||||||
|
pub fn test_pt2() {
|
||||||
|
let input =
|
||||||
|
read_to_string("./inputs/day08/example.txt").expect("Missing example.txt for day08");
|
||||||
|
|
||||||
|
assert_eq!(pt2(&input), 34)
|
||||||
|
}
|
||||||
|
}
|
18
src/main.rs
18
src/main.rs
|
@ -1,5 +1,8 @@
|
||||||
use std::{fmt::Display, fs::read_to_string, time::Instant};
|
use std::{fmt::Display, fs::read_to_string, time::Instant};
|
||||||
|
|
||||||
|
use color_eyre::eyre;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
#[cfg(feature = "day1")]
|
#[cfg(feature = "day1")]
|
||||||
mod day01;
|
mod day01;
|
||||||
#[cfg(feature = "day2")]
|
#[cfg(feature = "day2")]
|
||||||
|
@ -14,10 +17,14 @@ mod day05;
|
||||||
mod day06;
|
mod day06;
|
||||||
#[cfg(feature = "day7")]
|
#[cfg(feature = "day7")]
|
||||||
mod day07;
|
mod day07;
|
||||||
|
#[cfg(feature = "day8")]
|
||||||
|
mod day08;
|
||||||
|
|
||||||
fn main() {
|
fn main() -> eyre::Result<()> {
|
||||||
color_eyre::install().unwrap();
|
color_eyre::install()?;
|
||||||
tracing_subscriber::fmt().init();
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
|
.init();
|
||||||
#[cfg(feature = "day1")]
|
#[cfg(feature = "day1")]
|
||||||
solve_day(1, day01::pt1, day01::pt2);
|
solve_day(1, day01::pt1, day01::pt2);
|
||||||
#[cfg(feature = "day2")]
|
#[cfg(feature = "day2")]
|
||||||
|
@ -32,6 +39,9 @@ fn main() {
|
||||||
solve_day(6, day06::pt1, day06::pt2);
|
solve_day(6, day06::pt1, day06::pt2);
|
||||||
#[cfg(feature = "day7")]
|
#[cfg(feature = "day7")]
|
||||||
solve_day(7, day07::pt1, day07::pt2);
|
solve_day(7, day07::pt1, day07::pt2);
|
||||||
|
#[cfg(feature = "day8")]
|
||||||
|
solve_day(8, day08::pt1, day08::pt2);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve_day<Fa, Fb, Ta, Tb>(day: u8, part_a: Fa, part_b: Fb)
|
fn solve_day<Fa, Fb, Ta, Tb>(day: u8, part_a: Fa, part_b: Fb)
|
||||||
|
@ -52,6 +62,6 @@ where
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
tracing::warn!("could not open ./inputs/day{day:02}/input.txt");
|
tracing::warn!("could not open ./inputs/day{day:02}/input.txt");
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue