2022 day 23 rust

This commit is contained in:
Maciej Jur 2022-12-23 21:38:17 +01:00
parent 03c7d0a04c
commit 2f381d6158
2 changed files with 226 additions and 19 deletions

View file

@ -0,0 +1,73 @@
.#....#...##....##.#.###..##..#..#.#.###....#.###.###.##..###......#..##.
...#.##.#..#.#.######...##..#.#...#########.#.######..#.#.#.#...###.#.#.#
###.#.####.#.##.##....##..###.##..##..#.###.#.#.##...#######...###.##...#
.#...#####.##......##.#..###....###..#..#...###..##..##.#.##.###.#.######
.#...#...#.###.....##.##.########.#.##...##..##..#....#.####.###.##......
#####.......###..##..##...#..#.....#..#..##.##...##..........#.#.##.#.###
##..###.#.###.###.#....#...###....#...#.###..##.##.###.#.#.#..###..##.##.
#......#..###....#..###.###.#.#..##..##.###.#.#..#.#.###..###..#..##.##.#
#..####....#.#..#.#.....#...#.##.##.##...#.##.#.#..#.##.#####..##.#.##.#.
.#######..#####.#.#.#...##.#.####.#.#.##....##.##..####..####.#..##..###.
.#.##.###.#######.#...#.##...###........#.###..#.###....#..#....#.##.##..
.#.#.####..##.#.#####.#.....##.###.#..##.##...##.###....####...##.#.#####
#..#..#.##.#....#.#.#.##.##...##..##.####..#..##......##.####..#.##.#.##.
#.#.#.##....##..####.###....####...####..#..##..#.#..........#.##..###..#
.#....###.#.#.#.####...######.#.##.......##..#..##.#...#...##.....####.#.
#.....#.#.###.##..##....##.##.##.#.##..##.##...###...#..#....#.#.##.#....
.##.#.#####.#......#..##.###..#..#..###.#........####.#.####.#.##.#####.#
..##.#.#..........#..#.##..#.#.#.....##.#.#.#######..#.##.###.#..#.#####.
.##..#.####.....#.#..#..###.##..###.##.##.#####..#.#.###...#.##.#.####.##
###.#.######...###...#..#..##.#####..#.#..#...##.#.#.#.##......#.##..#.##
#..#...#...#.##########.###..#.#.##..#.#..#####..######.###....##.##....#
##...#######..#######.#......###..##.#.##.####..###.###.#####..######.#.#
.###.####.#.#.##..####...##.##..#....#.#.#.#...#....#.##..#..#.....##.#.#
##..........#....##...#######.#.#####.##....##..#.#.##.#.#..#...##.##..##
##.......##..#.##...#..#..###.#.##......##...#.#...###..#....#..##.#.#...
#####.###....######.#.######.####..##..#..#.#....#######....##.###..##..#
##..#..#..##.#...##.#####.#.##..##...#..##.....#.#.#....##.##.#..#....###
..###.##.....#....###.#..#####.#.###.#.#..###.########....#.#.##........#
##.#...#...###..###.####..###.#######..######...##.#...#.#.#.###..##.#...
...#.#...####...###.##.##.##..#.#..##.#.#.####...#.#.....#...#..##....#..
####...#.#.#.......####.#..#..####.#..###.#......#..###...#.#.##...#....#
##......##...#.##..#.#...#####...#.#####....#....###.#..#...#....##.#..#.
...#####...#.....##.#.##.##..#.#..###.#.##.#####...##..#.#.##.##...###.#.
..#...##..####...##.###..#...#......##...##.#.#.###.#.#...#..#...#...####
.##.###.#.#.#.###.##...#.#.#...#.#...##..#.#....####.##...###..##..#...#.
.##.#####.#..##.##....##.##.#..##.#..##.#..#.##.###.....#..##.###.##...##
#.#...####..#.#....##...##..#...##...##.##.##.#..#.#.......####.#.###..#.
##.#.##...#.#.#..#.#..##.#.#.##..#....#..###.##.##.##.....#..#..###.##.#.
...#...#.#......########.###.#.#.###.####.#.#.####...#.#.#.....#...###...
....###.#.#..##..#.#.#.##.###.###.....###.##.##.##.#.##..#...#.####..##.#
#....###.........#.##..#..#.##.##....#.##..#.#.##......#.##.#..##..##....
#....####.#....####.##.#.#...#.####.#.#.##..#.##.####...#..##.##.##.#.##.
...##..#..#...##.#.#.#.####...#.#...#.#.#.###..#.###..#..##.#.#..#####...
..#####..######.##.##..#.####.#.#..#...#....#.#..#########..##.#.####.##.
#..#.#...#.####...#......#.#...#.#.###..#..#.#....#..#..##..#..##.#......
#.####...#######..###.#.#..##...##.#...#####...##....#.##.#.#.###..##.###
####..###...##..######..#####..#...#####...#.#.####.##.....##....#.#...##
.#####.#..##.###.......###.######.#######.#.##..###.###...#.#...#..#####.
.##.###...##..##..#.###.#.##.###...###...##.#...#..##.##...####.###...##.
#..#..#..##..#.#.#.##....##..#...##.##....##.###.##.#....#...#....#####..
.#..#..######...#.#.##.###.###.#.#...#.#....#..#..##.##..#..####...#.###.
##.##.#####..###.##.#.#.###......###.#.##....###..#..####.###......##....
#.#.###..#..###.#....#.#....##.#...#.##.####.#.##......#.#..##.#....#..##
####..##.#..#...###....#.##...#..#.#...#.####....##..#..##...#..#.....#..
..#..###.#..#.##....#######..##......#.##...##.##.##.##..#.#..##.##......
.##.#.#.###....####.#.#.###..#.###....#..#..###..##..###.#..#.##.#..####.
..###..##.##...#..#...#...#.#.##..####.#..#..#.#..######.##.#.##....#.#..
..###.......##.#.##.####.##...##.#######.#..#..###..#.#.##.#...##.###.##.
##.#..#.##.#.###.####..#.##.......###.########.#.#....#.#...###.#.#.#..##
#.#..#..##...####...#...#.###.##...##.....#...#..#.####.#.#.##.#####.....
.######.#..#..#...#..#..#..##.##.##...#....##.#.#.##.###..##....#########
##....#...#.###...########.#####.#######.#...#.##.#..#..#.###.#.######.##
.###.#....##.#.#.#.#.##..#####.####.###.#..#.##..##..##..##.....#.#.#####
#.#.###.#..##...###.#.....###.##..##.....##.###.####..###.#...#..##.###.#
#####.#####.#...##.######.#..#.####.##.#.#..#.....####.#...#.#.....##..##
.#.#.#.###.#.#.##.##...#####...#.....##.##.#######..#####.#.##..##...##..
#.#...##.#.###...##.#.#.##.#....####....#.#.#..#..##.####.##..#.#.....##.
.##.#.##..#####..#..#.#.###..##.#....######..##...###.#...##..##.#....###
.##...#..#.#######.#.#...##.##.##.#...##....#.###.#....#.#..##.###..#.###
####.#....#.#..#.#...#..#..#..##....##..####.#.####.#..#..#..#.#..#.#.##.
.####..#.##..#.#.###...########.##.##...#.##....##..##.#.####...#..#.##..
###.#.#...#.#...##.#.###......##...###.#..#.##.########.###......###.####
##..#####..#.#.##.#######.######....#.###..#.#...#...#.###.#.##..#...##..

View file

@ -1,4 +1,4 @@
use std::collections::HashSet; use std::collections::{HashMap, HashSet, VecDeque};
use crate::utils; use crate::utils;
@ -11,26 +11,154 @@ pub fn run() -> () {
} }
type Location = (isize, isize); #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
struct Loc {
row: isize,
fn solve1(data: &HashSet<Location>) -> i32 { col: isize
println!("{:?}", data);
1
} }
fn solve2(data: &HashSet<Location>) -> i32 { impl Loc {
2 fn n(&self) -> Self { Self { row: self.row - 1, col: self.col } }
fn s(&self) -> Self { Self { row: self.row + 1, col: self.col } }
fn w(&self) -> Self { Self { row: self.row, col: self.col - 1 } }
fn e(&self) -> Self { Self { row: self.row, col: self.col + 1 } }
fn nw(&self) -> Self { Self { row: self.row - 1, col: self.col - 1 } }
fn ne(&self) -> Self { Self { row: self.row - 1, col: self.col + 1 } }
fn sw(&self) -> Self { Self { row: self.row + 1, col: self.col - 1 } }
fn se(&self) -> Self { Self { row: self.row + 1, col: self.col + 1 } }
}
fn has_neighbors(occupied: &HashSet<Loc>, loc: Loc) -> bool {
[loc.n(), loc.s(), loc.w(), loc.e(), loc.nw(), loc.ne(), loc.sw(), loc.se()].into_iter().any(|loc| occupied.contains(&loc))
}
fn move_n(occupied: &HashSet<Loc>, loc: Loc) -> Option<Loc> {
let nn = !occupied.contains(&loc.n());
let ne = !occupied.contains(&loc.ne());
let nw = !occupied.contains(&loc.nw());
(nn && ne && nw).then_some(loc.n())
}
fn move_s(occupied: &HashSet<Loc>, loc: Loc) -> Option<Loc> {
let ss = !occupied.contains(&loc.s());
let se = !occupied.contains(&loc.se());
let sw = !occupied.contains(&loc.sw());
(ss && se && sw).then_some(loc.s())
}
fn move_w(occupied: &HashSet<Loc>, loc: Loc) -> Option<Loc> {
let ww = !occupied.contains(&loc.w());
let nw = !occupied.contains(&loc.nw());
let sw = !occupied.contains(&loc.sw());
(ww && nw && sw).then_some(loc.w())
}
fn move_e(occupied: &HashSet<Loc>, loc: Loc) -> Option<Loc> {
let ee = !occupied.contains(&loc.e());
let ne = !occupied.contains(&loc.ne());
let se = !occupied.contains(&loc.se());
(ee && ne && se).then_some(loc.e())
}
fn find_bounds(locs: &HashSet<Loc>) -> ((isize, isize), (isize, isize)) {
locs.iter().fold(((isize::MAX, isize::MIN), (isize::MAX, isize::MIN)), |((r_min, r_max), (c_min, c_max)), loc| {
((r_min.min(loc.row), r_max.max(loc.row)), (c_min.min(loc.col), c_max.max(loc.col)))
})
}
fn draw(elves: &Vec<Loc>) {
let elves = HashSet::<Loc>::from_iter(elves.iter().copied());
let ((r_min, r_max), (c_min, c_max)) = find_bounds(&elves);
for row in r_min..=r_max {
for col in c_min..=c_max {
match elves.contains(&Loc { row, col }) {
true => print!("#"),
false => print!("."),
}
}
println!();
}
}
fn count_empty(elves: &Vec<Loc>) -> i32 {
let elves = HashSet::<Loc>::from_iter(elves.iter().copied());
let ((r_min, r_max), (c_min, c_max)) = find_bounds(&elves);
let mut sum = 0;
for row in r_min..=r_max {
for col in c_min..=c_max {
if !elves.contains(&Loc { row, col }) {
sum += 1;
}
}
}
sum
}
fn solve1(data: &HashSet<Loc>) -> i32 {
let mut elves = Vec::from_iter(data.iter().copied());
let mut moves = VecDeque::from([move_n, move_s, move_w, move_e]);
for _ in 0..10 {
let occupied = HashSet::<Loc>::from_iter(elves.iter().copied());
let mut planned = HashMap::<Loc, Vec<usize>>::new();
for (index, &loc) in elves.iter().enumerate().filter(|&(_, loc)| has_neighbors(&occupied, *loc)) {
if let Some(loc) = moves.iter().filter_map(|f| f(&occupied, loc)).next() {
planned.entry(loc)
.and_modify(|v| v.push(index))
.or_insert(vec![index]);
}
}
for (loc, planned) in planned.into_iter().filter(|(_, vec)| vec.len() == 1) {
elves[planned[0]] = loc;
}
moves.rotate_left(1);
}
count_empty(&elves)
}
fn solve2(data: &HashSet<Loc>) -> i32 {
let mut elves = Vec::from_iter(data.iter().copied());
let mut moves = VecDeque::from([move_n, move_s, move_w, move_e]);
for round in 1..i32::MAX {
let occupied = HashSet::<Loc>::from_iter(elves.iter().copied());
let mut planned = HashMap::<Loc, Vec<usize>>::new();
for (index, &loc) in elves.iter().enumerate().filter(|&(_, loc)| has_neighbors(&occupied, *loc)) {
if let Some(loc) = moves.iter().filter_map(|f| f(&occupied, loc)).next() {
planned.entry(loc)
.and_modify(|v| v.push(index))
.or_insert(vec![index]);
}
}
let changes = planned.into_iter().filter(|(_, vec)| vec.len() == 1).collect::<Vec<_>>();
if changes.len() == 0 { return round }
for (loc, planned) in changes {
elves[planned[0]] = loc;
}
moves.rotate_left(1);
};
panic!()
} }
fn parse_data<T: AsRef<str>>(data: &[T]) -> HashSet<Location> { fn parse_data<T: AsRef<str>>(data: &[T]) -> HashSet<Loc> {
data.iter() data.iter()
.enumerate() .enumerate()
.flat_map(|(row, line)| line.as_ref() .flat_map(|(row, line)| line.as_ref()
.char_indices() .char_indices()
.filter(|&(_, c)| c == '#') .filter(|&(_, c)| c == '#')
.map(move |(col, _)| (row as isize, col as isize)) .map(move |(col, _)| Loc {
row: row as isize,
col: col as isize,
})
) )
.collect() .collect()
} }
@ -41,21 +169,27 @@ mod tests {
use super::*; use super::*;
static DATA: &[&str] = &[ static DATA: &[&str] = &[
".....", "..............",
"..##.", "..............",
"..#..", ".......#......",
".....", ".....###.#....",
"..##.", "...#...#.#....",
".....", "....#...##....",
"...#.###......",
"...##.#.##....",
"....#..#......",
"..............",
"..............",
"..............",
]; ];
#[test] #[test]
fn part1() { fn part1() {
assert_eq!(1, solve1(&parse_data(DATA))); assert_eq!(110, solve1(&parse_data(DATA)));
} }
#[test] #[test]
fn part2() { fn part2() {
assert_eq!(2, solve2(&parse_data(DATA))); assert_eq!(20, solve2(&parse_data(DATA)));
} }
} }