2022 - Day 23
This commit is contained in:
parent
9504479316
commit
b1e04efaf9
71
2022/input/23/input
Normal file
71
2022/input/23/input
Normal file
|
@ -0,0 +1,71 @@
|
|||
...####..#.#.#....###..#....#..#..#...##..###..##.#...######.##....####
|
||||
..#.##..#.#...###..###.##....#..##......#.###..###....#.#.#....#...#.#.
|
||||
.##...#...####..####....#....#####.##.#.....#.#.#.#..#..#...####....###
|
||||
.####..#.##...#.##..#.#...#..#..##.######.#######.###.##.....####.#.##.
|
||||
##.##.#..######.####..##...##.#.##...###.###..#.#..####..##...###.##.#.
|
||||
...###.#.###..####..###.##..#..###..#..##.###.##.##....##...##.#.#..##.
|
||||
###.##...#...#.#..####..##.#..###.##..#..##.#...#...##..##..##.##.###.#
|
||||
..##....###.##.#...#####.#.#.###.#.#.#.##.#...#####.#####.....###.....#
|
||||
#.####.#...#.#...##..#..#.#...###.#.####.#..##..##.#.###...#.####....##
|
||||
#.##...#.#####...##....##..###..#...##.###..#.#.##.##.....#####....#...
|
||||
#...#..#..#.#...##..#####.#.###......##..##.##.##...###..###...#..###..
|
||||
..#.##.#..##.##.####.....#.###..#..#..#...###.###..#.#.##.##..#####..##
|
||||
.##.#...#.....####......#.#..#..#.#....#.#...####...##.#.#.....#.#.....
|
||||
#..#.##..###..#.....#.###..#.#..........##.......##.##.#..######...###.
|
||||
.#...##.#.#...##.####..######.###.#.#.#.####.##.###..#...###.#..#..##.#
|
||||
#.#.##.#.###..##.###.##.....###.#.#...#...###.##.#.#.##.##.#####.....#.
|
||||
.#...###.##...#.##.#.###.###.##......##...##.#.###..#..#.#.##...####.#.
|
||||
.#.#.##..#...#.##..#..##.....#....#....#.###....#########..#.#.########
|
||||
.#.##..###..##..#.......##.##..#..###.#.##.####....#..#.#...##..##.#...
|
||||
#####.##.#.....#.##...#.#...#.#.####..####....#.#...#.....###...##.....
|
||||
..###....#....##...#.#...###....##.###.#.#...##..##.#..#.##....#.#.#.##
|
||||
########..####...#.#..##.###...##.#...#...#.######...#..#..#..#...#..##
|
||||
#.#....##...##..#...#....#.##....#.###.##.#...###.#..#.#.#...###..#.#.#
|
||||
#.##........#..##...#...##.##.###.#.##...##...#####.#.#.....####.#.#..#
|
||||
##.##...####.##.#...#....#...###.#...#....#.#.#.####...#.#....#.####.#.
|
||||
.###....#..#.#..#..####..###.#.#..#.#..#.####..#####..#.#.#..#.....##.#
|
||||
.#####.#.##.###......#..##.#.....#######..##.##.#####....#..#.#..####.#
|
||||
.#....###....#.##..##.#.#.#.....#####..#.#.#.##...#.#....#.##..##....#.
|
||||
####....####...#.#...#..##....#.#.#.###..#.######.##..##..######...#.#.
|
||||
.#..####..#####.###..#..##.#.####.##.##..#.###..#...##.#...#.#.#.#.#.##
|
||||
#.###########.####.....###.#..#...###.#######...#.#...##..###....#....#
|
||||
#..#.####...###..####.#.##.#.#.#.#####.###.####...#...#....########..#.
|
||||
#######.#..#.#..####.##.##..##.#...##..#######..#.#..#...#..##..#.###.#
|
||||
##.#.....###.#..####.##..#.#######.#.#..#.##.#..###.##..##.##.#...#.#.#
|
||||
#.#######.#.##.#.###.##.##...##..#.#....#.#.#..#.#..###..##.#.#.....##.
|
||||
.##.##.#...####.#####.####.####.....#..####..#..##..###...#.#.###.#...#
|
||||
.####...#..#.#.#.#........#..###...#####..####..##..######.###...#####.
|
||||
###....#..##.##..#####....##.#..#...##.#####..#..###.#####..###.#..##.#
|
||||
..#.#...#.##..#.##.####.####..#######....##....#.#....#.#.#..##.#.#..##
|
||||
.#..#.########.........###.#.....###.######..#.######...####..#..#.#.##
|
||||
.#.#...###...#.#.#.#..#...##.###.#.#.##.##.....####......##.#.#....##.#
|
||||
..##..##...#.#######.#.##.####.###.#..#.....#.#..#...#..####..##..#.###
|
||||
.#...####.##....###..#.###...###.##...###..######.#.#.#.#.#.#.#....#.##
|
||||
.###..#.###.###..##.#..##..#.#.#...#..#.#..#...##..#..#...###...#####.#
|
||||
#.#..#.#.#.....##..#.##..##.#.....#..###..#.#.#.#.#.#.##..#.####..##...
|
||||
..#.#.####...#.##..##.##.####..##.#.#..##.#.###.#.######..#.######.#...
|
||||
###.#.#.#.####..##.######.#.#...##......###..###.#..#...#...#.#..######
|
||||
.###.#..#..######..##.####.###..##.#...#.#.#......###..##.#.#....#.#.#.
|
||||
.##..#...#....#..###.##.#..#####.#.#....######..#....#..######.....#...
|
||||
#.#...#..#.##...#..#..###.......####...#.####...#.#.#....#####.##...#.#
|
||||
....#.####.#...#..#####.#..###..######.###.....#..#.#.#.#.#.##.#.##....
|
||||
#.......#####.#.###..##.###..#####..#.###..#.....#.###.###..###..#.##.#
|
||||
##.#.#....##.#.#..#..#...###.#..#.....###...###...#..#.######.#.#...##.
|
||||
#....####.##.###....#....#....#...#..####...#.#.#.###..##.#.#..##.#..##
|
||||
#.....#.##....###..####..##.#.......#..#.#.#.....#....####.#...#....###
|
||||
###.#..####....#.....#..####....######.....#.#....#..###.#.#..#.#..###.
|
||||
#..#.#.#...##....##.##....##.....#..####.###..##.#.#.##..#.##.###...###
|
||||
....###.#.#.#..###.#.##.#.#.#.#####.#####..#..##...##.##.#...####.#.###
|
||||
#####.....#.#.#.#.#.#.###.#####.#...#.##..#.#.##..##..###...#...#..##..
|
||||
##.####.#.#.##..##.##.###....##.#..###.####..#######.#...##....#..##.##
|
||||
##..#.####.##..#..#.#.#####.#.#.....#####..##..#.##.....##..#.#....##.#
|
||||
.#..####...####.#####.##..#.##.....###.###.#.#.######..####.#...#..#.#.
|
||||
##.####..##..#.....##.#.####..#..#....##...#....#####..##########.###.#
|
||||
#...#.#.....#####.......###.#.#.#.###....#.#..#..#.##..#..#..#.####.###
|
||||
##.###..#..##......##########....###..#######..#....#.#..###.##........
|
||||
####.........#.#...##.#.#.#..#.#.####.#####....##...#.#.##.###..#.##.##
|
||||
.####.#...#..#.##.####..##..#..#...##...........##..###.####..##..#.#..
|
||||
.#####.##....##.#..####.##..##.#.###.....##.#..#..#.#.#...#.#...####...
|
||||
#...####........#.##.####..##.....#####.#.#####.#####..#.##.#..##...##.
|
||||
.###..###.####..###..##..##.#..##.###.#...#..#...#..#...#..#######.#.##
|
||||
.#..#..##...##....##....####..#....#.##.....#.##..#.#..#...#..##.#..#.#
|
6
2022/input/23/test-1
Normal file
6
2022/input/23/test-1
Normal file
|
@ -0,0 +1,6 @@
|
|||
.....
|
||||
..##.
|
||||
..#..
|
||||
.....
|
||||
..##.
|
||||
.....
|
7
2022/input/23/test-2
Normal file
7
2022/input/23/test-2
Normal file
|
@ -0,0 +1,7 @@
|
|||
....#..
|
||||
..###.#
|
||||
#...#.#
|
||||
.#...##
|
||||
#.###..
|
||||
##.#.##
|
||||
.#..#..
|
257
2022/src/bin/day23.rs
Normal file
257
2022/src/bin/day23.rs
Normal file
|
@ -0,0 +1,257 @@
|
|||
#![feature(test)]
|
||||
use std::{collections::HashMap, str::FromStr};
|
||||
|
||||
use anyhow::Result;
|
||||
use aoc::Solver;
|
||||
|
||||
// -- Runners --
|
||||
fn main() -> Result<()> {
|
||||
Day::solve()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_test1() -> Result<()> {
|
||||
Day::test(Day::part1, "test-1", 25)
|
||||
}
|
||||
#[test]
|
||||
fn part1_test2() -> Result<()> {
|
||||
Day::test(Day::part1, "test-2", 110)
|
||||
}
|
||||
#[test]
|
||||
fn part1_solution() -> Result<()> {
|
||||
Day::test(Day::part1, "input", 3849)
|
||||
}
|
||||
#[test]
|
||||
fn part2_test1() -> Result<()> {
|
||||
Day::test(Day::part2, "test-1", 4)
|
||||
}
|
||||
#[test]
|
||||
fn part2_test2() -> Result<()> {
|
||||
Day::test(Day::part2, "test-2", 20)
|
||||
}
|
||||
|
||||
// Benchmarks
|
||||
extern crate test;
|
||||
#[bench]
|
||||
#[ignore]
|
||||
fn part1_bench(b: &mut test::Bencher) {
|
||||
Day::benchmark(Day::part1, b)
|
||||
}
|
||||
#[bench]
|
||||
#[ignore]
|
||||
fn part2_bench(b: &mut test::Bencher) {
|
||||
Day::benchmark(Day::part2, b)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
|
||||
struct Vec2 {
|
||||
x: isize,
|
||||
y: isize,
|
||||
}
|
||||
|
||||
impl Vec2 {
|
||||
fn new(x: isize, y: isize) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
fn offset(&self, other: &Vec2) -> Self {
|
||||
Self { x: self.x+other.x, y: self.y+other.y }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Elf {
|
||||
considering: Vec2,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl Elf {
|
||||
fn new() -> Self {
|
||||
Self { considering: Vec2::new(0, 0), offset: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Map {
|
||||
elves: HashMap<Vec2, Elf>,
|
||||
considered: HashMap<Vec2, usize>,
|
||||
}
|
||||
|
||||
impl FromStr for Map {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
let elves = input
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
line
|
||||
.chars()
|
||||
.enumerate()
|
||||
.filter(|(_, c)| *c == '#')
|
||||
.map(move |(x, _)| {
|
||||
(Vec2::new(x as isize, y as isize), Elf::new())
|
||||
})
|
||||
}).collect();
|
||||
|
||||
Ok(Self { elves, considered: HashMap::new()})
|
||||
}
|
||||
}
|
||||
|
||||
impl Map {
|
||||
fn consider(&mut self) {
|
||||
let north = ([Vec2::new(-1, -1), Vec2::new(0, -1), Vec2::new(1, -1)], Vec2::new(0, -1));
|
||||
let south = ([Vec2::new(-1, 1), Vec2::new(0, 1), Vec2::new(1, 1)], Vec2::new(0, 1));
|
||||
let west = ([Vec2::new(-1, -1), Vec2::new(-1, 0), Vec2::new(-1, 1)], Vec2::new(-1, 0));
|
||||
let east = ([Vec2::new(1, -1), Vec2::new(1, 0), Vec2::new(1, 1)], Vec2::new(1, 0));
|
||||
|
||||
let moves = [north, south, west, east];
|
||||
|
||||
for (pos, elf) in self.elves.clone() {
|
||||
// Default action is to stay in place
|
||||
let mut next = pos;
|
||||
|
||||
if self.need_to_move(&pos) {
|
||||
for m in moves.iter().cycle().skip(elf.offset).take(4) {
|
||||
if !self.occupied(pos.offset(&m.0[0])) && !self.occupied(pos.offset(&m.0[1])) && !self.occupied(pos.offset(&m.0[2])) {
|
||||
next = pos.offset(&m.1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The offset is updated every round for all elves
|
||||
self.elves.get_mut(&pos).unwrap().offset += 1;
|
||||
|
||||
// Set the position that the elf is considering
|
||||
self.elves.get_mut(&pos).unwrap().considering = next;
|
||||
|
||||
// Increment counter for that position
|
||||
*self.considered.entry(next).or_default() += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn occupied(&self, pos: Vec2) -> bool {
|
||||
self.elves.contains_key(&pos)
|
||||
}
|
||||
|
||||
fn need_to_move(&self, pos: &Vec2) -> bool {
|
||||
for y in -1..2 {
|
||||
for x in -1..2 {
|
||||
if x == 0 && y == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if self.elves.contains_key(&pos.offset(&Vec2::new(x, y))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn make_moves(&mut self) -> bool {
|
||||
// New hashmap that is going to contain the updated values
|
||||
let mut elves = HashMap::new();
|
||||
|
||||
let mut moved = false;
|
||||
|
||||
for (pos, elf) in &self.elves {
|
||||
if *self.considered.get(&elf.considering).unwrap() == 1 {
|
||||
if elf.considering.x != pos.x || elf.considering.y != pos.y {
|
||||
moved = true;
|
||||
}
|
||||
// If only one elf is considering the new location, insert the elf into the new
|
||||
// HashMap at the new location
|
||||
elves.insert(elf.considering, *elf);
|
||||
} else {
|
||||
// Otherwise the elf will not move and stay at its old position
|
||||
elves.insert(*pos, *elf);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the hashmap
|
||||
self.elves = elves;
|
||||
// Clear the map tracking considered moves
|
||||
self.considered.clear();
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (Vec2, Vec2) {
|
||||
let mut min = Vec2::new(isize::MAX, isize::MAX);
|
||||
let mut max = Vec2::new(0, 0);
|
||||
|
||||
for pos in self.elves.keys() {
|
||||
min.x = min.x.min(pos.x);
|
||||
min.y = min.y.min(pos.y);
|
||||
|
||||
max.x = max.x.max(pos.x+1);
|
||||
max.y = max.y.max(pos.y+1);
|
||||
}
|
||||
|
||||
(min, max)
|
||||
}
|
||||
|
||||
fn empty_tiles(&self) -> isize {
|
||||
let (min, max) = self.get_size();
|
||||
(max.x - min.x) * (max.y - min.y) - self.elves.len() as isize
|
||||
}
|
||||
|
||||
fn print(&self) {
|
||||
let (min, max) = self.get_size();
|
||||
for y in min.y..max.y {
|
||||
for x in min.x..max.x {
|
||||
if self.elves.contains_key(&Vec2::new(x, y)) {
|
||||
print!("#");
|
||||
} else {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
|
||||
// -- Solution --
|
||||
pub struct Day;
|
||||
impl aoc::Solver for Day {
|
||||
type Output1 = isize;
|
||||
type Output2 = isize;
|
||||
|
||||
fn day() -> u8 {
|
||||
23
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> Self::Output1 {
|
||||
let mut map = Map::from_str(input).unwrap();
|
||||
|
||||
for _ in 0..10 {
|
||||
map.consider();
|
||||
map.make_moves();
|
||||
}
|
||||
|
||||
map.empty_tiles()
|
||||
}
|
||||
|
||||
fn part2(input: &str) -> Self::Output2 {
|
||||
let mut map = Map::from_str(input).unwrap();
|
||||
|
||||
let mut counter = 0;
|
||||
loop {
|
||||
counter += 1;
|
||||
|
||||
map.consider();
|
||||
if !map.make_moves() {
|
||||
return counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user