2022 rust day 15 wip
This commit is contained in:
parent
25c441bbf4
commit
0a53a19147
137
2022/rust/src/solutions/day15.rs
Normal file
137
2022/rust/src/solutions/day15.rs
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use regex::Regex;
|
||||||
|
use crate::utils;
|
||||||
|
use crate::utils::matrix::Matrix;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn run() -> () {
|
||||||
|
let data = parse_data(&utils::read_lines(utils::Source::Day(-1)));
|
||||||
|
|
||||||
|
println!("Day 15");
|
||||||
|
println!("Part 1: {}", solve1(&data));
|
||||||
|
println!("Part 2: {}", solve2(&data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Data = [((usize, usize), (isize, isize))];
|
||||||
|
|
||||||
|
|
||||||
|
fn distance(a: (usize, usize), b: (isize, isize)) -> usize {
|
||||||
|
(a.0 as isize).abs_diff(b.0) + (a.1 as isize).abs_diff(b.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_ranges(data: &Data) -> HashMap<(usize, usize), usize> {
|
||||||
|
data.iter()
|
||||||
|
.map(|&(sensor, beacon)|
|
||||||
|
(sensor, distance(sensor, beacon))
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn find_bounds(data: &Data) -> (usize, usize) {
|
||||||
|
data.iter()
|
||||||
|
.fold((0, 0), |acc, &(sensor, beacon)| {
|
||||||
|
(
|
||||||
|
acc.0.max(sensor.0.max(beacon.0.max(0) as usize)),
|
||||||
|
acc.1.max(sensor.0.max(beacon.1.max(0) as usize)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve1(data: &Data) -> usize {
|
||||||
|
let ranges = find_ranges(data);
|
||||||
|
let (rows, cols) = find_bounds(data);
|
||||||
|
let max_range = *ranges.values().max().unwrap();
|
||||||
|
let buffer = 2 * max_range;
|
||||||
|
|
||||||
|
let mut grid = Matrix::with_bounds(
|
||||||
|
(0, 0),
|
||||||
|
(rows + buffer, cols + buffer),
|
||||||
|
'.'
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut view = grid.view_translated((-(max_range as isize), -(max_range as isize)));
|
||||||
|
|
||||||
|
for index in view.cell_indices().collect::<Vec<_>>() {
|
||||||
|
for (&sensor, &max_dist) in ranges.iter() {
|
||||||
|
if distance(sensor, index) <= max_dist {
|
||||||
|
view[index] = '#';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.iter_rows().for_each(|row| {
|
||||||
|
let xd = row.iter().filter(|&&x| x == '#').count();
|
||||||
|
println!("{xd}");
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("{grid}");
|
||||||
|
|
||||||
|
grid.slice_row(max_range + 10).iter().filter(|&&x| x == '#').count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(data: &Data) -> i32 {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn parse_data<T: AsRef<str>>(data: &[T]) -> Vec<((usize, usize), (isize, isize))> {
|
||||||
|
let re = Regex::new(r#"x=(-?\d+), y=(-?\d+)"#).unwrap();
|
||||||
|
data.iter()
|
||||||
|
.map(|line| {
|
||||||
|
let mut iter = re.captures_iter(line.as_ref());
|
||||||
|
let sensor = iter.next()
|
||||||
|
.map(|c| {
|
||||||
|
let mut cap = c.iter();
|
||||||
|
let x = cap.nth(1).unwrap().unwrap().as_str().parse::<usize>().unwrap();
|
||||||
|
let y = cap.next().unwrap().unwrap().as_str().parse::<usize>().unwrap();
|
||||||
|
(y, x)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let beacon = iter.next()
|
||||||
|
.map(|c| {
|
||||||
|
let mut cap = c.iter();
|
||||||
|
let x = cap.nth(1).unwrap().unwrap().as_str().parse::<isize>().unwrap();
|
||||||
|
let y = cap.next().unwrap().unwrap().as_str().parse::<isize>().unwrap();
|
||||||
|
(y, x)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
(sensor, beacon)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static DATA: &[&str] = &[
|
||||||
|
// "Sensor at x=2, y=18: closest beacon is at x=-2, y=15",
|
||||||
|
// "Sensor at x=9, y=16: closest beacon is at x=10, y=16",
|
||||||
|
// "Sensor at x=13, y=2: closest beacon is at x=15, y=3",
|
||||||
|
// "Sensor at x=12, y=14: closest beacon is at x=10, y=16",
|
||||||
|
// "Sensor at x=10, y=20: closest beacon is at x=10, y=16",
|
||||||
|
// "Sensor at x=14, y=17: closest beacon is at x=10, y=16",
|
||||||
|
"Sensor at x=8, y=7: closest beacon is at x=2, y=10",
|
||||||
|
// "Sensor at x=2, y=0: closest beacon is at x=2, y=10",
|
||||||
|
// "Sensor at x=0, y=11: closest beacon is at x=2, y=10",
|
||||||
|
// "Sensor at x=20, y=14: closest beacon is at x=25, y=17",
|
||||||
|
// "Sensor at x=17, y=20: closest beacon is at x=21, y=22",
|
||||||
|
// "Sensor at x=16, y=7: closest beacon is at x=15, y=3",
|
||||||
|
// "Sensor at x=14, y=3: closest beacon is at x=15, y=3",
|
||||||
|
// "Sensor at x=20, y=1: closest beacon is at x=15, y=3",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1() {
|
||||||
|
assert_eq!(26, solve1(&parse_data(DATA)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2() {
|
||||||
|
let data = parse_data(DATA);
|
||||||
|
assert_eq!(2, solve2(&data));
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,3 +12,4 @@ pub mod day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day13;
|
pub mod day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
|
pub mod day15;
|
||||||
|
|
|
@ -85,6 +85,12 @@ impl<T> Matrix<T> {
|
||||||
.flat_map(move |row| col_range.clone().into_iter().map(move |col| (row, col)))
|
.flat_map(move |row| col_range.clone().into_iter().map(move |col| (row, col)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn slice_row(&self, row: usize) -> &[T] {
|
||||||
|
let start = row * self.cols;
|
||||||
|
let end = start + self.cols;
|
||||||
|
&self.array[start..end]
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn get_offset(&self, row: usize, col: usize) -> usize {
|
fn get_offset(&self, row: usize, col: usize) -> usize {
|
||||||
(row - self.offset_r) * self.cols + (col - self.offset_c)
|
(row - self.offset_r) * self.cols + (col - self.offset_c)
|
||||||
|
@ -155,3 +161,54 @@ impl<T> fmt::Display for Matrix<T> where T: fmt::Display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct TranslatedViewMut<'a, T> {
|
||||||
|
matrix: &'a mut Matrix<T>,
|
||||||
|
tl_row: isize,
|
||||||
|
tl_col: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Matrix<T> {
|
||||||
|
pub fn view_translated(&mut self, (rows, cols): (isize, isize)) -> TranslatedViewMut<'_, T> {
|
||||||
|
TranslatedViewMut { matrix: self, tl_row: rows, tl_col: cols }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> TranslatedViewMut<'a, T> {
|
||||||
|
fn tl(&self, (row, col): (usize, usize)) -> (isize, isize) {
|
||||||
|
let row = row as isize + self.tl_row;
|
||||||
|
let col = col as isize + self.tl_col;
|
||||||
|
(row, col)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn undo_tl(&self, (row, col): (isize, isize)) -> (usize, usize) {
|
||||||
|
let row = (row - self.tl_row) as usize;
|
||||||
|
let col = (col - self.tl_col) as usize;
|
||||||
|
(row, col)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cell_indices(&self) -> impl Iterator<Item = (isize, isize)> + '_ {
|
||||||
|
self.matrix.cell_indices().map(|index| self.tl(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slice_row(&self, row: isize) -> &[T] {
|
||||||
|
let row = row - self.tl_row;
|
||||||
|
self.slice_row(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Index<(isize, isize)> for TranslatedViewMut<'a, T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, index: (isize, isize)) -> &Self::Output {
|
||||||
|
let index = self.undo_tl(index);
|
||||||
|
&self.matrix[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> IndexMut<(isize, isize)> for TranslatedViewMut<'a, T> {
|
||||||
|
fn index_mut(&mut self, index: (isize, isize)) -> &mut Self::Output {
|
||||||
|
let index = self.undo_tl(index);
|
||||||
|
&mut self.matrix[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue