171 lines
4.4 KiB
Rust
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
|
|
);
|
|
}
|
|
}
|