[Rust/2022/23] Add solution

This commit is contained in:
Felix Bargfeldt 2023-10-26 10:41:18 +02:00
parent c3bcde3044
commit e34ead249e
Signed by: Defelo
GPG key ID: 2A05272471204DD3
6 changed files with 250 additions and 2 deletions

View file

@ -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
View 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);

View file

@ -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
View file

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

1
examples/2022/23/1.1 Normal file
View file

@ -0,0 +1 @@
110

1
examples/2022/23/1.2 Normal file
View file

@ -0,0 +1 @@
20