day 11 done
This commit is contained in:
14
2023/day-11/Cargo.toml
Normal file
14
2023/day-11/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "day-11"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
nom = { workspace = true }
|
||||
itertools = {workspace = true }
|
||||
glam = {workspace = true}
|
||||
nom_locate = {workspace = true }
|
||||
4
2023/day-11/src/lib.rs
Normal file
4
2023/day-11/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod part1;
|
||||
pub use crate::part1::*;
|
||||
pub mod part2;
|
||||
pub use crate::part2::*;
|
||||
12
2023/day-11/src/main.rs
Normal file
12
2023/day-11/src/main.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
|
||||
use day_11::part1;
|
||||
use day_11::part2;
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("./input.txt");
|
||||
let part1_result = part1(input);
|
||||
println!("part 1: {part1_result}");
|
||||
let part2_result = part2(input, 1_000_000);
|
||||
println!("part 2: {part2_result}");
|
||||
}
|
||||
95
2023/day-11/src/part1.rs
Normal file
95
2023/day-11/src/part1.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
|
||||
use glam::IVec2;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[must_use]
|
||||
pub fn part1(input: &str) -> String {
|
||||
let points = parse_input(input);
|
||||
let ((min_x, min_y), (mut max_x, /*mut*/ max_y)) = points.iter().fold(
|
||||
((i32::MAX, i32::MAX), (i32::MIN, i32::MIN)),
|
||||
|((min_x, min_y), (max_x, max_y)), pos| {
|
||||
let min_x = min_x.min(pos.x);
|
||||
let min_y = min_y.min(pos.y);
|
||||
let max_x = max_x.max(pos.x);
|
||||
let max_y = max_y.max(pos.y);
|
||||
((min_x, min_y), (max_x, max_y))
|
||||
},
|
||||
);
|
||||
let mut modifier = 0;
|
||||
let mut adjusted_points = HashSet::new();
|
||||
for x in min_x..=max_x {
|
||||
let column = (min_y..=max_y)
|
||||
.filter_map(|y| points.get(&(x, y).into()))
|
||||
.collect::<Vec<_>>();
|
||||
if column.is_empty() {
|
||||
modifier += 1;
|
||||
}
|
||||
for point in column {
|
||||
adjusted_points.insert(*point + IVec2::new(modifier, 0));
|
||||
}
|
||||
}
|
||||
max_x += modifier;
|
||||
|
||||
let mut modifier = 0;
|
||||
let mut points = HashSet::new();
|
||||
for y in min_y..=max_y {
|
||||
let row = (min_x..=max_x)
|
||||
.filter_map(|x| adjusted_points.get(&(x, y).into()))
|
||||
.collect::<Vec<_>>();
|
||||
if row.is_empty() {
|
||||
modifier += 1;
|
||||
}
|
||||
for point in row {
|
||||
points.insert(*point + IVec2::new(0, modifier));
|
||||
}
|
||||
}
|
||||
//max_y += modifier;
|
||||
(points
|
||||
.iter()
|
||||
.cartesian_product(points.iter())
|
||||
.filter_map(|(a, b)| (a != b).then_some(*a - *b))
|
||||
.map(|pos| pos.x.abs() + pos.y.abs())
|
||||
.sum::<i32>()
|
||||
/ 2)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> HashSet<IVec2> {
|
||||
input
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
line.chars().enumerate().filter_map(move |(x, c)| {
|
||||
(c != '.').then_some(IVec2::new(
|
||||
i32::try_from(x).unwrap(),
|
||||
i32::try_from(y).unwrap(),
|
||||
))
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
const INPUT: &str = "...#......
|
||||
.......#..
|
||||
#.........
|
||||
..........
|
||||
......#...
|
||||
.#........
|
||||
.........#
|
||||
..........
|
||||
.......#..
|
||||
#...#.....";
|
||||
|
||||
#[test]
|
||||
fn part1_works() {
|
||||
let result = part1(INPUT);
|
||||
assert_eq!(result, "374".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
103
2023/day-11/src/part2.rs
Normal file
103
2023/day-11/src/part2.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
|
||||
use glam::I64Vec2;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// day 11 part 2 of aoc 2023
|
||||
///
|
||||
/// # Arguments
|
||||
/// - input the input for today's puzzle
|
||||
///
|
||||
/// # Panics
|
||||
/// panics whne it cannot parse the input OR when ever the number of game numbers is greater than
|
||||
/// usize
|
||||
#[must_use]
|
||||
pub fn part2(input: &str, modr: i64) -> String {
|
||||
let points = parse_input(input);
|
||||
let ((min_x, min_y), (mut max_x, /*mut*/ max_y)) = points.iter().fold(
|
||||
((i64::MAX, i64::MAX), (i64::MIN, i64::MIN)),
|
||||
|((min_x, min_y), (max_x, max_y)), pos| {
|
||||
let min_x = min_x.min(pos.x);
|
||||
let min_y = min_y.min(pos.y);
|
||||
let max_x = max_x.max(pos.x);
|
||||
let max_y = max_y.max(pos.y);
|
||||
((min_x, min_y), (max_x, max_y))
|
||||
},
|
||||
);
|
||||
let mut modifier = 0;
|
||||
let mut adjusted_points = HashSet::new();
|
||||
for x in min_x..=max_x {
|
||||
let column = (min_y..=max_y)
|
||||
.filter_map(|y| points.get(&(x, y).into()))
|
||||
.collect::<Vec<_>>();
|
||||
if column.is_empty() {
|
||||
modifier += modr-1;
|
||||
}
|
||||
for point in column {
|
||||
adjusted_points.insert(*point + I64Vec2::new(modifier, 0));
|
||||
}
|
||||
}
|
||||
max_x += modifier;
|
||||
|
||||
let mut modifier = 0;
|
||||
let mut points = HashSet::new();
|
||||
for y in min_y..=max_y {
|
||||
let row = (min_x..=max_x)
|
||||
.filter_map(|x| adjusted_points.get(&(x, y).into()))
|
||||
.collect::<Vec<_>>();
|
||||
if row.is_empty() {
|
||||
modifier += modr-1;
|
||||
}
|
||||
for point in row {
|
||||
points.insert(*point + I64Vec2::new(0, modifier));
|
||||
}
|
||||
}
|
||||
//max_y += modifier;
|
||||
(points
|
||||
.iter()
|
||||
.cartesian_product(points.iter())
|
||||
.filter_map(|(a, b)| (*a != *b).then_some(*a-*b))
|
||||
.map(|a| u64::try_from(a.x.abs()+a.y.abs()).unwrap())
|
||||
.sum::<u64>()
|
||||
/ 2)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> HashSet<I64Vec2> {
|
||||
input
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
line.chars().enumerate().filter_map(move |(x, c)| {
|
||||
(c != '.').then_some(I64Vec2::new(
|
||||
i64::try_from(x).unwrap(),
|
||||
i64::try_from(y).unwrap(),
|
||||
))
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
const INPUT: &str = "...#......
|
||||
.......#..
|
||||
#.........
|
||||
..........
|
||||
......#...
|
||||
.#........
|
||||
.........#
|
||||
..........
|
||||
.......#..
|
||||
#...#.....";
|
||||
|
||||
#[test]
|
||||
fn part2_works() {
|
||||
let result = part2(INPUT, 10);
|
||||
assert_eq!(result, "1030".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user