mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implementation day 24.
This commit is contained in:
@@ -1,12 +1,139 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Read;
|
||||
use std::mem::swap;
|
||||
|
||||
use crate::common::Lines;
|
||||
use crate::Solution;
|
||||
|
||||
type Pos = (i32, i32);
|
||||
|
||||
const DIRECTIONS: [Pos; 6] = [(-2, 0), (2, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)];
|
||||
|
||||
fn convert_pos(s: &str) -> Pos {
|
||||
let mut s = s.chars();
|
||||
|
||||
let mut x = 0;
|
||||
let mut y = 0;
|
||||
|
||||
while let Some(c) = s.next() {
|
||||
match c {
|
||||
'e' => x += 2,
|
||||
'w' => x -= 2,
|
||||
'n' | 's' => {
|
||||
if c == 'n' {
|
||||
y += 1;
|
||||
} else {
|
||||
y -= 1;
|
||||
}
|
||||
|
||||
match s.next() {
|
||||
Some('e') => x += 1,
|
||||
Some('w') => x -= 1,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn step(current: &HashSet<Pos>, target: &mut HashSet<Pos>) {
|
||||
let mut black_count: HashMap<Pos, u32> = current.iter().map(|&pos| (pos, 0)).collect();
|
||||
|
||||
for &(x, y) in current {
|
||||
for &(dx, dy) in &DIRECTIONS {
|
||||
let pos = (x + dx, y + dy);
|
||||
|
||||
*black_count.entry(pos).or_default() += 1;
|
||||
}
|
||||
}
|
||||
|
||||
target.clear();
|
||||
|
||||
for (pos, neighbours) in black_count {
|
||||
let is_black = current.contains(&pos);
|
||||
|
||||
let going_black = match neighbours {
|
||||
1 | 2 if is_black => true,
|
||||
2 if !is_black => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if going_black {
|
||||
target.insert(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_black_tiles(input: &mut dyn Read) -> HashSet<Pos> {
|
||||
let mut black = HashSet::new();
|
||||
|
||||
for line in Lines::new(input) {
|
||||
let pos = convert_pos(&line);
|
||||
|
||||
if !black.insert(pos) {
|
||||
black.remove(&pos);
|
||||
}
|
||||
}
|
||||
|
||||
black
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day24;
|
||||
|
||||
impl Solution for Day24 {
|
||||
fn part1(&mut self, _input: &mut dyn Read) -> String {
|
||||
todo!()
|
||||
fn part1(&mut self, input: &mut dyn Read) -> String {
|
||||
get_black_tiles(input).len().to_string()
|
||||
}
|
||||
|
||||
fn part2(&mut self, input: &mut dyn Read) -> String {
|
||||
let mut state = get_black_tiles(input);
|
||||
let mut scratch_pad = state.clone();
|
||||
|
||||
for _ in 0..100 {
|
||||
step(&state, &mut scratch_pad);
|
||||
swap(&mut state, &mut scratch_pad);
|
||||
}
|
||||
|
||||
state.len().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::test_implementation;
|
||||
|
||||
use super::*;
|
||||
|
||||
const SAMPLE: &[u8] = include_bytes!("../samples/24.txt");
|
||||
|
||||
#[test]
|
||||
fn test_convert_pos() {
|
||||
assert_eq!((1, -1), convert_pos("esew"));
|
||||
assert_eq!((0, 0), convert_pos("nwwswee"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_step() {
|
||||
let state = get_black_tiles(&mut SAMPLE.clone());
|
||||
let mut target = state.clone();
|
||||
|
||||
step(&state, &mut target);
|
||||
|
||||
assert_eq!(15, target.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_part1() {
|
||||
test_implementation!(Day24, 1, SAMPLE, 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_part2() {
|
||||
test_implementation!(Day24, 2, SAMPLE, 2208);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user