Skip to content

Commit ec7ec7e

Browse files
committed
Broken code, while I try to understand ownership, borrowing and lifetimes :(
1 parent ae02376 commit ec7ec7e

File tree

5 files changed

+122
-21
lines changed

5 files changed

+122
-21
lines changed

12/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use std::fmt;
22
use std::io;
33

4+
use crate::map::Coord;
5+
46
#[derive(Debug)]
57
pub enum Error {
68
IOError(String),
79
ParseError,
10+
NoRoute(Coord, Coord),
811
}
912

1013
impl std::error::Error for Error {}
@@ -14,6 +17,7 @@ impl fmt::Display for Error {
1417
match self {
1518
Self::IOError(reason) => write!(f, "IO error: {reason}"),
1619
Self::ParseError => write!(f, "Parse error: Couldn't parse input"),
20+
Self::NoRoute(start, finish) => write!(f, "No route found from {start} to {finish}"),
1721
}
1822
}
1923
}

12/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
mod error;
22
mod map;
3+
mod route;
34

45
pub use crate::error::Error;
56
pub use crate::map::Map;
7+
pub use crate::route::Route;

12/src/main.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use aoc22_12::{Error, Map};
1+
use aoc22_12::{Error, Map, Route};
22

33
fn main() {
44
if let Err(e) = run() {
@@ -10,7 +10,8 @@ fn main() {
1010
fn run() -> Result<(), Error> {
1111
let map = Map::parse()?;
1212

13-
//println!("{} x {}", map.size().x(), map.size().y());
13+
let route = Route::try_from(&map)?;
14+
println!("Part 1: {}", route.len());
1415

1516
Ok(())
1617
}

12/src/map.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::fmt;
12
use std::io::stdin;
23
use std::ops::Sub;
34

@@ -8,7 +9,7 @@ pub struct Elevation(u8);
89

910
impl From<char> for Elevation {
1011
fn from(input: char) -> Self {
11-
Elevation(input as u8 - b'a')
12+
Self(input as u8 - b'a')
1213
}
1314
}
1415

@@ -28,23 +29,22 @@ impl Sub for Elevation {
2829
}
2930
}
3031

31-
#[derive(Clone, Copy)]
32-
pub struct Coord(usize, usize);
33-
34-
impl Coord {
35-
pub fn x(self) -> usize {
36-
self.0
37-
}
32+
#[derive(Clone, Copy, Debug, PartialEq)]
33+
pub struct Coord {
34+
pub x: usize,
35+
pub y: usize,
36+
}
3837

39-
pub fn y(self) -> usize {
40-
self.1
38+
impl fmt::Display for Coord {
39+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40+
write!(f, "({}, {})", self.x, self.y)
4141
}
4242
}
4343

4444
pub struct Map {
4545
field: (Vec<Elevation>, usize, usize),
4646
pub start: Coord,
47-
pub end: Coord,
47+
pub finish: Coord,
4848
}
4949

5050
impl Map {
@@ -74,12 +74,12 @@ impl Map {
7474

7575
'S' => {
7676
field.push('a'.into());
77-
start = Some(Coord(x, y));
77+
start = Some(Coord { x, y });
7878
}
7979

8080
'E' => {
8181
field.push('z'.into());
82-
end = Some(Coord(x, y));
82+
end = Some(Coord { x, y });
8383
}
8484

8585
_ => return Err(Error::ParseError),
@@ -90,22 +90,22 @@ impl Map {
9090
line.clear();
9191
}
9292

93-
Ok(Map {
93+
Ok(Self {
9494
field: (field, width.ok_or(Error::ParseError)?, y),
9595
start: start.ok_or(Error::ParseError)?,
96-
end: end.ok_or(Error::ParseError)?,
96+
finish: end.ok_or(Error::ParseError)?,
9797
})
9898
}
9999

100100
pub fn size(&self) -> Coord {
101-
let (_, width, height) = self.field;
102-
Coord(width, height)
101+
let (_, x, y) = self.field;
102+
Coord { x, y }
103103
}
104104

105105
pub fn elevation(&self, at: Coord) -> Elevation {
106106
let (field, width, height) = &self.field;
107-
assert!(at.x() < *width && at.y() < *height);
107+
assert!(at.x < *width && at.y < *height);
108108

109-
field[at.x() + (at.y() * width)]
109+
field[at.x + (at.y * width)]
110110
}
111111
}

12/src/route.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::collections::VecDeque;
2+
3+
use crate::error::Error;
4+
use crate::map::{Coord, Map};
5+
6+
struct LocationNode<'a> {
7+
parent: Option<&'a LocationNode<'a>>,
8+
coord: Coord,
9+
}
10+
11+
// FIXME
12+
impl Iterator for LocationNode<'_> {
13+
type Item<'a> = LocationNode<'a>;
14+
15+
fn next(&mut self) -> Option<Self::Item> {
16+
self.parent
17+
}
18+
}
19+
20+
pub struct Route(Vec<Coord>);
21+
22+
impl TryFrom<&Map> for Route {
23+
type Error = Error;
24+
25+
fn try_from(map: &Map) -> Result<Self, Self::Error> {
26+
let width = map.size().x as isize;
27+
let height = map.size().y as isize;
28+
29+
// Maintain a tree of visited locations
30+
let mut tree: Vec<LocationNode> = vec![LocationNode {
31+
parent: None,
32+
coord: map.start,
33+
}];
34+
35+
// Maintain a queue of locations from which to explore, starting with the root
36+
let mut to_explore: VecDeque<&LocationNode> = VecDeque::from([&tree[0]]);
37+
38+
// Breadth-first search that builds up the tree until it reaches the finish
39+
while let Some(location) = to_explore.pop_front() {
40+
if location.coord == map.finish {
41+
// Iterate up to the root (i.e., start) and reverse to obtain the route
42+
let route = Vec::from_iter(*location.iter().rev().map(|location| location.coord));
43+
return Ok(Route(route));
44+
}
45+
46+
// Find assailable locations (besides where we just came from) and add enqueue
47+
let previous = location.parent;
48+
for delta_x in [-1, 1] {
49+
for delta_y in [-1, 1] {
50+
// Short-circuit the loop if potential locations fall off the edges of the map
51+
let new_x = location.coord.x as isize + delta_x;
52+
let new_y = location.coord.y as isize + delta_y;
53+
if new_x < 0 || new_x >= width || new_y < 0 || new_y >= height {
54+
continue;
55+
}
56+
57+
let potential = Coord {
58+
x: new_x as usize,
59+
y: new_y as usize,
60+
};
61+
62+
// Short-circuit the loop if we've just come from a potential location
63+
if previous.is_some() && previous.unwrap().coord == potential {
64+
continue;
65+
}
66+
67+
// Add assailable locations to the tree and enqueue to explore
68+
if (map.elevation(location.coord) - map.elevation(potential)).assailable() {
69+
// FIXME
70+
tree.push(LocationNode {
71+
parent: Some(location),
72+
coord: potential,
73+
});
74+
75+
to_explore.push_back(tree.last().unwrap())
76+
}
77+
}
78+
}
79+
}
80+
81+
// No route found
82+
Err(Error::NoRoute(map.start, map.finish))
83+
}
84+
}
85+
86+
impl Route {
87+
pub fn len(&self) -> usize {
88+
self.0.len()
89+
}
90+
91+
pub fn is_empty(&self) -> bool {
92+
self.0.is_empty()
93+
}
94+
}

0 commit comments

Comments
 (0)