1
0
Fork 0
advent-of-code/2023/src/bin/11.rs

171 lines
4.4 KiB
Rust

advent_of_code::solution!(11);
struct Galaxy(Vec<Coord>);
impl Galaxy {
fn galaxy_pairs(&self) -> Vec<(Coord, Coord)> {
let mut result: Vec<(Coord, Coord)> = vec![];
for i in 0..self.0.len() {
let one = &self.0[i];
for j in i..self.0.len() {
if i == j {
continue;
}
let two = &self.0[j];
result.push((*one, *two));
}
}
result
}
fn sum_shortest_paths(&self) -> u32 {
let mut result: usize = 0;
for (src, dest) in self.galaxy_pairs().iter() {
result += src.path_len(&dest);
}
result as u32
}
}
#[derive(Eq, PartialEq, Copy, Clone)]
struct Coord(usize, usize);
impl Coord {
fn hdist(&self, other: &Self) -> usize {
((self.0 as i64) - (other.0 as i64))
.abs()
.try_into()
.unwrap()
}
fn vdist(&self, other: &Self) -> usize {
((self.1 as i64) - (other.1 as i64))
.abs()
.try_into()
.unwrap()
}
fn path_len(&self, other: &Self) -> usize {
self.hdist(other) + self.vdist(other)
}
}
fn parse(input: &str, empty_space: usize) -> Galaxy {
let mut map = [[false; 141]; 141];
let mut galaxies: Vec<Coord> = vec![];
let mut row: usize = 0;
for line in input.lines() {
if !line.is_empty() {
let mut col = 0;
for cur in line.split("") {
if cur.is_empty() {
continue;
}
if cur != "." {
map[row][col] = true;
}
col += 1;
}
row += 1;
}
}
let mut empty_rows: Vec<usize> = vec![];
let mut empty_cols: Vec<usize> = vec![];
for i in 0..141 {
let mut found_row = false;
let mut found_col = false;
for j in 0..141 {
if map[i][j] {
found_row = true;
}
if map[j][i] {
found_col = true;
}
}
if !found_row {
empty_rows.push(i);
}
if !found_col {
empty_cols.push(i);
}
}
let mut prior_rows: Vec<usize> = vec![];
let mut prior_cols: Vec<usize> = vec![];
for row in 0..141 {
prior_rows.push(
empty_rows
.iter()
.filter(|t| **t < row)
.collect::<Vec<_>>()
.len(),
);
for col in 0..141 {
if row == 0 {
prior_cols.push(
empty_cols
.iter()
.filter(|t| **t < col)
.collect::<Vec<_>>()
.len(),
);
}
if !map[row][col] {
continue;
}
let calcrow = row + prior_rows[row] * empty_space;
let calccol = col + prior_cols[col] * empty_space;
galaxies.push(Coord(calcrow, calccol));
}
}
Galaxy(galaxies)
}
pub fn part_one(input: &str) -> Option<u32> {
Some(parse(&input, 1).sum_shortest_paths())
}
pub fn part_two(input: &str) -> Option<u32> {
Some(parse(&input, 999999).sum_shortest_paths())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let input_str = advent_of_code::template::read_file("examples", DAY);
let input = parse(&input_str, 1);
assert_eq!(input.0.len(), 9);
assert_eq!(input.galaxy_pairs().len(), 36);
assert_eq!(input.0[4].path_len(&input.0[8]), 9);
assert_eq!(input.0[0].path_len(&input.0[6]), 15);
assert_eq!(input.0[2].path_len(&input.0[5]), 17);
assert_eq!(input.0[7].path_len(&input.0[8]), 5);
assert_eq!(input.sum_shortest_paths(), 374);
assert_eq!(part_one(&input_str), Some(374));
}
#[test]
fn shortest_path() {
let src: Coord = Coord(6, 1);
let dest: Coord = Coord(11, 5);
assert_eq!(src.path_len(&dest), 9);
}
#[test]
fn test_part_two() {
assert_eq!(
parse(&advent_of_code::template::read_file("examples", DAY), 9).sum_shortest_paths(),
1030
);
assert_eq!(
parse(&advent_of_code::template::read_file("examples", DAY), 99).sum_shortest_paths(),
8410
);
}
}