[Rust/2022/24] Add solution

This commit is contained in:
Felix Bargfeldt 2023-10-26 17:57:27 +02:00
parent e34ead249e
commit e3f1cdbc20
Signed by: Defelo
GPG key ID: 2A05272471204DD3
7 changed files with 213 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): 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)
## [2022](https://adventofcode.com/2022) ([<img height=18 src=".assets/rs.svg"> Rust](Rust/2022): 25/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) [<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")|
|[**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) [<img height=12 src=".assets/rs.svg">](Rust/2022/24.rs "Rust solution for 2022/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)

192
Rust/2022/24.rs Normal file
View file

@ -0,0 +1,192 @@
#![feature(test)]
use std::{cmp::Ordering, collections::BinaryHeap};
use itertools::Itertools;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
#[derive(Debug)]
struct Input {
width: usize,
height: usize,
blizzards: Vec<Vec<Option<Direction>>>,
}
#[derive(Debug, Clone, Copy)]
enum Direction {
North,
East,
South,
West,
}
fn setup(input: &str) -> Input {
let blizzards = input
.lines()
.skip(1)
.take_while(|l| l.as_bytes()[1] != b'#')
.map(|line| {
line.bytes()
.skip(1)
.take_while(|&c| c != b'#')
.map(|c| match c {
b'.' => None,
b'^' => Some(Direction::North),
b'>' => Some(Direction::East),
b'v' => Some(Direction::South),
b'<' => Some(Direction::West),
_ => panic!(),
})
.collect_vec()
})
.collect_vec();
Input {
width: blizzards[0].len(),
height: blizzards.len(),
blizzards,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct State {
time: usize,
position: usize,
cnt: usize,
dist: usize,
}
impl PartialOrd for State {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for State {
fn cmp(&self, other: &Self) -> Ordering {
other.dist.cmp(&self.dist)
}
}
impl State {
fn init(input: &Input) -> Self {
Self {
time: 0,
position: input.width * input.height,
cnt: 0,
dist: usize::MAX,
}
}
fn next(self, input: &Input, target: usize) -> impl Iterator<Item = Self> + '_ {
let &Input {
width: w,
height: h,
..
} = input;
let mut out: SmallVec<[_; 7]> = smallvec![self.position];
match self.position {
p if p == w * h => out.push(0),
p if p == w * h + 1 => out.push(w * h - 1),
p => {
if p == 0 {
out.push(w * h);
}
if p == w * h - 1 {
out.push(w * h + 1);
}
if p >= w {
out.push(p - w);
}
if p + w < w * h {
out.push(p + w);
}
if p % w > 0 {
out.push(p - 1);
}
if p % w < w - 1 {
out.push(p + 1);
}
}
}
out.into_iter()
.filter(move |&p| {
let (i, j) = (p / w, p % w);
let t = self.time + 1;
p >= w * h
|| !matches!(
input.blizzards[i][(j + w - t % w) % w],
Some(Direction::East)
) && !matches!(input.blizzards[i][(j + t) % w], Some(Direction::West))
&& !matches!(
input.blizzards[(i + h - t % h) % h][j],
Some(Direction::South)
)
&& !matches!(input.blizzards[(i + t) % h][j], Some(Direction::North))
})
.map(move |p| {
let time = self.time + 1;
let cnt = self.cnt
+ (self.cnt % 2) * (p == w * h) as usize
+ ((self.cnt + 1) % 2) * (p == w * h + 1) as usize;
let start_to_goal = w + h;
let (start, goal) = match p {
p if p == w * h => (0, start_to_goal),
p if p == w * h + 1 => (start_to_goal, 0),
p => {
let (i, j) = (p / w, p % w);
(i + j + 1, start_to_goal - i - j - 2)
}
};
Self {
time,
cnt,
position: p,
dist: {
if cnt != target {
time + start * (cnt % 2)
+ goal * ((cnt + 1) % 2)
+ (target - cnt - 1) * start_to_goal
} else {
0
}
},
}
})
}
}
fn solve(input: &Input, target: usize) -> usize {
let mut queue = BinaryHeap::from([State::init(input)]);
let mut seen = FxHashSet::default();
while let Some(state) = queue.pop() {
if state.cnt == target {
return state.time;
}
for next in state.next(input, target) {
if seen.insert(next) {
queue.push(next);
}
}
}
panic!()
}
fn part1(input: &Input) -> usize {
solve(input, 1)
}
fn part2(input: &Input) -> usize {
solve(input, 3)
}
aoc::main!(2022, 24, ex: 1);

7
Rust/Cargo.lock generated
View file

@ -23,6 +23,7 @@ dependencies = [
"rayon",
"regex",
"rustc-hash",
"smallvec",
]
[[package]]
@ -448,6 +449,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "smallvec"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "tempfile"
version = "3.8.0"

View file

@ -26,6 +26,7 @@ paste = "1.0.14"
rayon = "1.8.0"
regex = "1.10.2"
rustc-hash = "1.1.0"
smallvec = "1.11.1"
[dev-dependencies]
proptest = "1.3.1"
@ -196,5 +197,8 @@ path = "2022/22.rs"
name = "2022_23"
path = "2022/23.rs"
[[bin]]
name = "2022_24"
path = "2022/24.rs"
[[bin]]
name = "2022_25"
path = "2022/25.rs"

6
examples/2022/24/1 Normal file
View file

@ -0,0 +1,6 @@
#.######
#>>.<^<#
#.<..<<#
#>v.><>#
#<^v^^>#
######.#

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

@ -0,0 +1 @@
18

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

@ -0,0 +1 @@
54