[Rust/2022/23] Add solution
This commit is contained in:
parent
c3bcde3044
commit
e34ead249e
6 changed files with 250 additions and 2 deletions
|
@ -1,13 +1,13 @@
|
|||
# AdventOfCode
|
||||
[Advent of Code](https://adventofcode.com/) solutions in [<img height=12 src=".assets/rs.svg"> Rust](Rust), [<img height=12 src=".assets/hs.svg"> Haskell](Haskell), [<img height=12 src=".assets/py.svg"> Python](Python) and [<img height=12 src=".assets/apl.svg"> APL](APL)
|
||||
|
||||
## [2022](https://adventofcode.com/2022) ([<img height=18 src=".assets/rs.svg"> Rust](Rust/2022): 23/25 | [<img height=18 src=".assets/py.svg"> Python](Python/2022): 18/25 | [<img height=18 src=".assets/hs.svg"> Haskell](Haskell/2022): 9/25)
|
||||
## [2022](https://adventofcode.com/2022) ([<img height=18 src=".assets/rs.svg"> Rust](Rust/2022): 24/25 | [<img height=18 src=".assets/py.svg"> Python](Python/2022): 18/25 | [<img height=18 src=".assets/hs.svg"> Haskell](Haskell/2022): 9/25)
|
||||
|Mo|Tu|We|Th|Fr|Sa|Su|
|
||||
|-|-|-|-|-|-|-|
|
||||
||||[**1**](https://adventofcode.com/2022/day/1) [<img height=12 src=".assets/rs.svg">](Rust/2022/01.rs "Rust solution for 2022/01") [<img height=12 src=".assets/hs.svg">](Haskell/2022/01.hs "Haskell solution for 2022/01") [<img height=12 src=".assets/py.svg">](Python/2022/01.py "Python solution for 2022/01")|[**2**](https://adventofcode.com/2022/day/2) [<img height=12 src=".assets/rs.svg">](Rust/2022/02.rs "Rust solution for 2022/02") [<img height=12 src=".assets/hs.svg">](Haskell/2022/02.hs "Haskell solution for 2022/02") [<img height=12 src=".assets/py.svg">](Python/2022/02.py "Python solution for 2022/02")|[**3**](https://adventofcode.com/2022/day/3) [<img height=12 src=".assets/rs.svg">](Rust/2022/03.rs "Rust solution for 2022/03") [<img height=12 src=".assets/hs.svg">](Haskell/2022/03.hs "Haskell solution for 2022/03") [<img height=12 src=".assets/py.svg">](Python/2022/03.py "Python solution for 2022/03")|[**4**](https://adventofcode.com/2022/day/4) [<img height=12 src=".assets/rs.svg">](Rust/2022/04.rs "Rust solution for 2022/04") [<img height=12 src=".assets/hs.svg">](Haskell/2022/04.hs "Haskell solution for 2022/04") [<img height=12 src=".assets/py.svg">](Python/2022/04.py "Python solution for 2022/04")|
|
||||
|[**5**](https://adventofcode.com/2022/day/5) [<img height=12 src=".assets/rs.svg">](Rust/2022/05.rs "Rust solution for 2022/05") [<img height=12 src=".assets/hs.svg">](Haskell/2022/05.hs "Haskell solution for 2022/05") [<img height=12 src=".assets/py.svg">](Python/2022/05.py "Python solution for 2022/05")|[**6**](https://adventofcode.com/2022/day/6) [<img height=12 src=".assets/rs.svg">](Rust/2022/06.rs "Rust solution for 2022/06") [<img height=12 src=".assets/hs.svg">](Haskell/2022/06.hs "Haskell solution for 2022/06") [<img height=12 src=".assets/py.svg">](Python/2022/06.py "Python solution for 2022/06")|[**7**](https://adventofcode.com/2022/day/7) [<img height=12 src=".assets/rs.svg">](Rust/2022/07.rs "Rust solution for 2022/07") [<img height=12 src=".assets/hs.svg">](Haskell/2022/07.hs "Haskell solution for 2022/07") [<img height=12 src=".assets/py.svg">](Python/2022/07.py "Python solution for 2022/07")|[**8**](https://adventofcode.com/2022/day/8) [<img height=12 src=".assets/rs.svg">](Rust/2022/08.rs "Rust solution for 2022/08") [<img height=12 src=".assets/hs.svg">](Haskell/2022/08.hs "Haskell solution for 2022/08") [<img height=12 src=".assets/py.svg">](Python/2022/08.py "Python solution for 2022/08")|[**9**](https://adventofcode.com/2022/day/9) [<img height=12 src=".assets/rs.svg">](Rust/2022/09.rs "Rust solution for 2022/09") [<img height=12 src=".assets/hs.svg">](Haskell/2022/09.hs "Haskell solution for 2022/09") [<img height=12 src=".assets/py.svg">](Python/2022/09.py "Python solution for 2022/09")|[**10**](https://adventofcode.com/2022/day/10) [<img height=12 src=".assets/rs.svg">](Rust/2022/10.rs "Rust solution for 2022/10") [<img height=12 src=".assets/py.svg">](Python/2022/10.py "Python solution for 2022/10")|[**11**](https://adventofcode.com/2022/day/11) [<img height=12 src=".assets/rs.svg">](Rust/2022/11.rs "Rust solution for 2022/11") [<img height=12 src=".assets/py.svg">](Python/2022/11.py "Python solution for 2022/11")|
|
||||
|[**12**](https://adventofcode.com/2022/day/12) [<img height=12 src=".assets/rs.svg">](Rust/2022/12.rs "Rust solution for 2022/12") [<img height=12 src=".assets/py.svg">](Python/2022/12.py "Python solution for 2022/12")|[**13**](https://adventofcode.com/2022/day/13) [<img height=12 src=".assets/rs.svg">](Rust/2022/13.rs "Rust solution for 2022/13") [<img height=12 src=".assets/py.svg">](Python/2022/13.py "Python solution for 2022/13")|[**14**](https://adventofcode.com/2022/day/14) [<img height=12 src=".assets/rs.svg">](Rust/2022/14.rs "Rust solution for 2022/14") [<img height=12 src=".assets/py.svg">](Python/2022/14.py "Python solution for 2022/14")|[**15**](https://adventofcode.com/2022/day/15) [<img height=12 src=".assets/rs.svg">](Rust/2022/15.rs "Rust solution for 2022/15") [<img height=12 src=".assets/py.svg">](Python/2022/15.py "Python solution for 2022/15")|[**16**](https://adventofcode.com/2022/day/16) [<img height=12 src=".assets/rs.svg">](Rust/2022/16.rs "Rust solution for 2022/16") [<img height=12 src=".assets/py.svg">](Python/2022/16.py "Python solution for 2022/16")|[**17**](https://adventofcode.com/2022/day/17) [<img height=12 src=".assets/rs.svg">](Rust/2022/17.rs "Rust solution for 2022/17") [<img height=12 src=".assets/py.svg">](Python/2022/17.py "Python solution for 2022/17")|[**18**](https://adventofcode.com/2022/day/18) [<img height=12 src=".assets/rs.svg">](Rust/2022/18.rs "Rust solution for 2022/18") [<img height=12 src=".assets/py.svg">](Python/2022/18.py "Python solution for 2022/18")|
|
||||
|[**19**](https://adventofcode.com/2022/day/19) [<img height=12 src=".assets/rs.svg">](Rust/2022/19.rs "Rust solution for 2022/19")|[**20**](https://adventofcode.com/2022/day/20) [<img height=12 src=".assets/rs.svg">](Rust/2022/20.rs "Rust solution for 2022/20")|[**21**](https://adventofcode.com/2022/day/21) [<img height=12 src=".assets/rs.svg">](Rust/2022/21.rs "Rust solution for 2022/21")|[**22**](https://adventofcode.com/2022/day/22) [<img height=12 src=".assets/rs.svg">](Rust/2022/22.rs "Rust solution for 2022/22")|[**23**](https://adventofcode.com/2022/day/23)|[**24**](https://adventofcode.com/2022/day/24)|[**25**](https://adventofcode.com/2022/day/25) [<img height=12 src=".assets/rs.svg">](Rust/2022/25.rs "Rust solution for 2022/25")|
|
||||
|[**19**](https://adventofcode.com/2022/day/19) [<img height=12 src=".assets/rs.svg">](Rust/2022/19.rs "Rust solution for 2022/19")|[**20**](https://adventofcode.com/2022/day/20) [<img height=12 src=".assets/rs.svg">](Rust/2022/20.rs "Rust solution for 2022/20")|[**21**](https://adventofcode.com/2022/day/21) [<img height=12 src=".assets/rs.svg">](Rust/2022/21.rs "Rust solution for 2022/21")|[**22**](https://adventofcode.com/2022/day/22) [<img height=12 src=".assets/rs.svg">](Rust/2022/22.rs "Rust solution for 2022/22")|[**23**](https://adventofcode.com/2022/day/23) [<img height=12 src=".assets/rs.svg">](Rust/2022/23.rs "Rust solution for 2022/23")|[**24**](https://adventofcode.com/2022/day/24)|[**25**](https://adventofcode.com/2022/day/25) [<img height=12 src=".assets/rs.svg">](Rust/2022/25.rs "Rust solution for 2022/25")|
|
||||
|26|27|28|29|30|31||
|
||||
|
||||
## [2021](https://adventofcode.com/2021) ([<img height=18 src=".assets/rs.svg"> Rust](Rust/2021): 25/25 | [<img height=18 src=".assets/py.svg"> Python](Python/2021): 25/25 | [<img height=18 src=".assets/apl.svg"> APL](APL/2021): 17/25)
|
||||
|
|
236
Rust/2022/23.rs
Normal file
236
Rust/2022/23.rs
Normal file
|
@ -0,0 +1,236 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
type Input = Vec<Position>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(i, line)| {
|
||||
line.chars().enumerate().filter_map(move |(j, c)| {
|
||||
(c == '#').then_some(Position::from_coords(j as _, i as _))
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
const SIZE: u16 = 256;
|
||||
const OFFSET: u16 = 16;
|
||||
|
||||
type PositionType = u16;
|
||||
type BucketType = usize;
|
||||
const BUCKET_COUNT: usize = (1 << PositionType::BITS as usize) / BUCKET_SIZE;
|
||||
const BUCKET_SIZE: usize = BucketType::BITS as usize;
|
||||
|
||||
const DIRECTIONS: [Direction; 4] = [
|
||||
Direction::North,
|
||||
Direction::South,
|
||||
Direction::West,
|
||||
Direction::East,
|
||||
];
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct Position(PositionType);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct PositionSet([BucketType; BUCKET_COUNT]);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
enum Direction {
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
}
|
||||
|
||||
impl Add<Direction> for Position {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Direction) -> Self::Output {
|
||||
match rhs {
|
||||
Direction::North => Self(self.0 - SIZE),
|
||||
Direction::East => Self(self.0 + 1),
|
||||
Direction::South => Self(self.0 + SIZE),
|
||||
Direction::West => Self(self.0 - 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
fn rotate_left(self) -> Self {
|
||||
match self {
|
||||
Self::North => Self::West,
|
||||
Self::East => Self::North,
|
||||
Self::South => Self::East,
|
||||
Self::West => Self::South,
|
||||
}
|
||||
}
|
||||
|
||||
fn rotate_right(self) -> Self {
|
||||
match self {
|
||||
Self::North => Self::East,
|
||||
Self::East => Self::South,
|
||||
Self::South => Self::West,
|
||||
Self::West => Self::North,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Position {
|
||||
fn from_coords(x: PositionType, y: PositionType) -> Self {
|
||||
Self((y + OFFSET) * SIZE + x + OFFSET)
|
||||
}
|
||||
|
||||
fn coords(self) -> (PositionType, PositionType) {
|
||||
(self.0 % SIZE, self.0 / SIZE)
|
||||
}
|
||||
|
||||
fn neighbors(self) -> [Position; 8] {
|
||||
[
|
||||
Self(self.0 - SIZE - 1),
|
||||
Self(self.0 - SIZE),
|
||||
Self(self.0 - SIZE + 1),
|
||||
Self(self.0 - 1),
|
||||
Self(self.0 + 1),
|
||||
Self(self.0 + SIZE - 1),
|
||||
Self(self.0 + SIZE),
|
||||
Self(self.0 + SIZE + 1),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Position> for PositionSet {
|
||||
fn from_iter<T: IntoIterator<Item = Position>>(iter: T) -> Self {
|
||||
let mut out = Self::default();
|
||||
for p in iter {
|
||||
out.insert(p);
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PositionSet {
|
||||
fn default() -> Self {
|
||||
Self([0; BUCKET_COUNT])
|
||||
}
|
||||
}
|
||||
|
||||
impl PositionSet {
|
||||
fn contains(&self, p: Position) -> bool {
|
||||
self.0[p.0 as usize / BUCKET_SIZE] & (1 << (p.0 % BUCKET_SIZE as u16)) != 0
|
||||
}
|
||||
|
||||
fn remove(&mut self, p: Position) {
|
||||
self.0[p.0 as usize / BUCKET_SIZE] &= !(1 << (p.0 % BUCKET_SIZE as u16));
|
||||
}
|
||||
|
||||
fn insert(&mut self, p: Position) {
|
||||
self.0[p.0 as usize / BUCKET_SIZE] |= 1 << (p.0 % BUCKET_SIZE as u16);
|
||||
}
|
||||
|
||||
fn toggle(&mut self, p: Position) {
|
||||
self.0[p.0 as usize / BUCKET_SIZE] ^= 1 << (p.0 % BUCKET_SIZE as u16);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
positions: Vec<Position>,
|
||||
proposed: Vec<Position>,
|
||||
occupied: PositionSet,
|
||||
cnt: usize,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn from_input(input: &Input) -> Self {
|
||||
let positions = input.clone();
|
||||
let occupied = input.iter().copied().collect();
|
||||
Self {
|
||||
proposed: positions.clone(),
|
||||
positions,
|
||||
occupied,
|
||||
cnt: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn size(&self) -> (usize, usize) {
|
||||
let (x, y) = self.positions[0].coords();
|
||||
let (x1, y1, x2, y2) = self
|
||||
.positions
|
||||
.iter()
|
||||
.fold((x, y, x, y), |(x1, y1, x2, y2), p| {
|
||||
let (x, y) = p.coords();
|
||||
(x1.min(x), y1.min(y), x2.max(x), y2.max(y))
|
||||
});
|
||||
((x2 - x1 + 1) as _, (y2 - y1 + 1) as _)
|
||||
}
|
||||
|
||||
fn empty_tiles(&self) -> usize {
|
||||
let (w, h) = self.size();
|
||||
w * h - self.positions.len()
|
||||
}
|
||||
|
||||
fn simulate(&mut self) -> bool {
|
||||
let mut proposed_set = PositionSet::default();
|
||||
self.positions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, &p)| {
|
||||
if !p.neighbors().into_iter().any(|q| self.occupied.contains(q)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let d = (0..4)
|
||||
.map(|di| DIRECTIONS[(di + self.cnt) % 4])
|
||||
.find(|&d| {
|
||||
!self.occupied.contains(p + d)
|
||||
&& !self.occupied.contains(p + d + d.rotate_left())
|
||||
&& !self.occupied.contains(p + d + d.rotate_right())
|
||||
})?;
|
||||
Some((i, p + d))
|
||||
})
|
||||
.for_each(|(i, q)| {
|
||||
proposed_set.toggle(q);
|
||||
self.proposed[i] = q;
|
||||
});
|
||||
|
||||
let mut moved = false;
|
||||
self.positions
|
||||
.iter_mut()
|
||||
.zip(self.proposed.iter_mut())
|
||||
.for_each(|(p, q)| {
|
||||
if !proposed_set.contains(*q) {
|
||||
*q = *p;
|
||||
} else {
|
||||
self.occupied.remove(*p);
|
||||
self.occupied.insert(*q);
|
||||
*p = *q;
|
||||
moved = true;
|
||||
}
|
||||
});
|
||||
|
||||
self.cnt += 1;
|
||||
moved
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> usize {
|
||||
let mut state = State::from_input(input);
|
||||
for _ in 0..10 {
|
||||
state.simulate();
|
||||
}
|
||||
state.empty_tiles()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> usize {
|
||||
let mut out = 1;
|
||||
let mut state = State::from_input(input);
|
||||
while state.simulate() {
|
||||
out += 1;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
aoc::main!(2022, 23, ex: 1);
|
|
@ -193,5 +193,8 @@ path = "2022/21.rs"
|
|||
name = "2022_22"
|
||||
path = "2022/22.rs"
|
||||
[[bin]]
|
||||
name = "2022_23"
|
||||
path = "2022/23.rs"
|
||||
[[bin]]
|
||||
name = "2022_25"
|
||||
path = "2022/25.rs"
|
||||
|
|
7
examples/2022/23/1
Normal file
7
examples/2022/23/1
Normal file
|
@ -0,0 +1,7 @@
|
|||
....#..
|
||||
..###.#
|
||||
#...#.#
|
||||
.#...##
|
||||
#.###..
|
||||
##.#.##
|
||||
.#..#..
|
1
examples/2022/23/1.1
Normal file
1
examples/2022/23/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
110
|
1
examples/2022/23/1.2
Normal file
1
examples/2022/23/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
20
|
Loading…
Add table
Add a link
Reference in a new issue