Day 23, part 1
This commit is contained in:
parent
62c866abf9
commit
7abd632567
19
src/bin/d23p1.rs
Normal file
19
src/bin/d23p1.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use aoc22::{
|
||||||
|
day23::{self, empty_ground},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
|
const N_ROUNDS: usize = 10;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut elves = day23::parse_map(&util::parse_input());
|
||||||
|
|
||||||
|
for i in 0..N_ROUNDS {
|
||||||
|
let elves_too_close = day23::do_round(&mut elves, i);
|
||||||
|
if !elves_too_close {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Elves cover {} empty tiles", empty_ground(&elves));
|
||||||
|
}
|
112
src/day23.rs
Normal file
112
src/day23.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::util::{self, SignedCoord};
|
||||||
|
|
||||||
|
pub fn parse_map(input: &str) -> HashSet<SignedCoord> {
|
||||||
|
let mut result = HashSet::new();
|
||||||
|
for (y, row) in input.lines().enumerate() {
|
||||||
|
for (x, c) in row.chars().enumerate() {
|
||||||
|
if c == '#' {
|
||||||
|
result.insert((y as isize, x as isize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUM_DIRS: usize = 4;
|
||||||
|
|
||||||
|
pub fn do_round(elves: &mut HashSet<SignedCoord>, it: usize) -> bool {
|
||||||
|
let mut proposals: HashMap<SignedCoord, Vec<SignedCoord>> = HashMap::new();
|
||||||
|
|
||||||
|
let mut elves_too_close = false;
|
||||||
|
for elf in elves.iter() {
|
||||||
|
if noone_adjacent(elves, elf) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elves_too_close = true;
|
||||||
|
for offset in 0..NUM_DIRS {
|
||||||
|
let dir = (it + offset) % NUM_DIRS;
|
||||||
|
if let Some(new_loc) = propose(elves, elf, dir) {
|
||||||
|
proposals.entry(new_loc).or_insert_with(Vec::new).push(*elf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (target, interested) in proposals {
|
||||||
|
if interested.len() == 1 {
|
||||||
|
elves.remove(&interested[0]);
|
||||||
|
elves.insert(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elves_too_close
|
||||||
|
}
|
||||||
|
|
||||||
|
fn noone_adjacent(elves: &HashSet<SignedCoord>, elf: &SignedCoord) -> bool {
|
||||||
|
!(elves.contains(&(elf.0, elf.1 + 1))
|
||||||
|
|| elves.contains(&(elf.0, elf.1 - 1))
|
||||||
|
|| elves.contains(&(elf.0 + 1, elf.1))
|
||||||
|
|| elves.contains(&(elf.0 + 1, elf.1 + 1))
|
||||||
|
|| elves.contains(&(elf.0 + 1, elf.1 - 1))
|
||||||
|
|| elves.contains(&(elf.0 - 1, elf.1))
|
||||||
|
|| elves.contains(&(elf.0 - 1, elf.1 + 1))
|
||||||
|
|| elves.contains(&(elf.0 - 1, elf.1 - 1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propose(elves: &HashSet<SignedCoord>, elf: &SignedCoord, dir: usize) -> Option<SignedCoord> {
|
||||||
|
let (moved, other) = match dir {
|
||||||
|
0 => (
|
||||||
|
(elf.0 - 1, elf.1),
|
||||||
|
((elf.0 - 1, elf.1 - 1), (elf.0 - 1, elf.1 + 1)),
|
||||||
|
), // N
|
||||||
|
1 => (
|
||||||
|
(elf.0 + 1, elf.1),
|
||||||
|
((elf.0 + 1, elf.1 - 1), (elf.0 + 1, elf.1 + 1)),
|
||||||
|
), // S
|
||||||
|
2 => (
|
||||||
|
(elf.0, elf.1 - 1),
|
||||||
|
((elf.0 - 1, elf.1 - 1), (elf.0 + 1, elf.1 - 1)),
|
||||||
|
), // E
|
||||||
|
3 => (
|
||||||
|
(elf.0, elf.1 + 1),
|
||||||
|
((elf.0 - 1, elf.1 + 1), (elf.0 + 1, elf.1 + 1)),
|
||||||
|
), // W
|
||||||
|
_ => panic!("Unknown direction {}", dir),
|
||||||
|
};
|
||||||
|
if elves.contains(&moved) || elves.contains(&other.0) || elves.contains(&other.1) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(moved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_map(elves: &HashSet<SignedCoord>) {
|
||||||
|
let (y_min, y_max) = util::minmax_unwrap(&elves.iter().map(|c| c.0).minmax());
|
||||||
|
let (x_min, x_max) = util::minmax_unwrap(&elves.iter().map(|c| c.1).minmax());
|
||||||
|
|
||||||
|
println!("({}, {})", y_min, x_min);
|
||||||
|
for y in y_min..(y_max + 1) {
|
||||||
|
for x in x_min..(x_max + 1) {
|
||||||
|
if elves.contains(&(y, x)) {
|
||||||
|
print!("#");
|
||||||
|
} else {
|
||||||
|
print!(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print!("\n");
|
||||||
|
}
|
||||||
|
print!("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty_ground(elves: &HashSet<SignedCoord>) -> usize {
|
||||||
|
let (y_min, y_max) = util::minmax_unwrap(&elves.iter().map(|c| c.0).minmax());
|
||||||
|
let (x_min, x_max) = util::minmax_unwrap(&elves.iter().map(|c| c.1).minmax());
|
||||||
|
let y_dim = (y_max + 1 - y_min) as usize;
|
||||||
|
let x_dim = (x_max + 1 - x_min) as usize;
|
||||||
|
|
||||||
|
y_dim * x_dim - elves.len()
|
||||||
|
}
|
@ -13,6 +13,7 @@ pub mod day2;
|
|||||||
pub mod day20;
|
pub mod day20;
|
||||||
pub mod day21;
|
pub mod day21;
|
||||||
pub mod day22;
|
pub mod day22;
|
||||||
|
pub mod day23;
|
||||||
pub mod day3;
|
pub mod day3;
|
||||||
pub mod day4;
|
pub mod day4;
|
||||||
pub mod day5;
|
pub mod day5;
|
||||||
|
10
src/util.rs
10
src/util.rs
@ -3,6 +3,8 @@ use std::env;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use itertools::MinMaxResult;
|
||||||
|
|
||||||
pub fn parse_input() -> String {
|
pub fn parse_input() -> String {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let input_path = args
|
let input_path = args
|
||||||
@ -153,3 +155,11 @@ impl Dir {
|
|||||||
Self::from_usize((d + 3) % 4).unwrap()
|
Self::from_usize((d + 3) % 4).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn minmax_unwrap<T: Clone>(mm: &MinMaxResult<T>) -> (T, T) {
|
||||||
|
match mm {
|
||||||
|
MinMaxResult::NoElements => panic!("No elements"),
|
||||||
|
MinMaxResult::OneElement(a) => (a.clone(), a.clone()),
|
||||||
|
MinMaxResult::MinMax(a, b) => (a.clone(), b.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user