Not the complete code, but should be enough for this problem.
pub fn solve(
capacity_1: u8,
capacity_2: u8,
goal: u8,
start_bucket: &Bucket,
) -> Option<BucketStats> {
if goal == 0 {
return None;
}
let mut explored = HashSet::new();
let mut frontier = VecDeque::new();
let start = if start_bucket == &Bucket::One {
vec![(capacity_1, 0, Move::FillOne)]
} else {
vec![(0, capacity_2, Move::FillTwo)]
};
frontier.push_back(&start);
while !frontier.is_empty() {
let mut path = frontier.pop_front().unwrap();
let (x, y, _) = path[path.len() - 1];
for state in successors(x, y, capacity_1, capacity_2)
.iter()
.filter(|&s| !is_smaller_full_and_larger_empty(s.0, s.1, capacity_1, capacity_2)) {
if explored.contains(&(state.0, state.1)) {
continue;
}
explored.insert((state.0, state.1));
path.push(state.clone());
if state.0 == goal || state.1 == goal {
println!("{:?}", path);
return None;
}
frontier.push_back(path);
}
}
None
}
But it fails compilation.
warning: variable does not need to be mutable
--> src/lib.rs:52:13
|
52 | let mut path = frontier.pop_front().unwrap();
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0596]: cannot borrow `*path` as mutable, as it is behind a `&` reference
--> src/lib.rs:61:13
|
52 | let mut path = frontier.pop_front().unwrap();
| -------- help: consider changing this to be a mutable reference: `&mut Vec<(u8, u8, Move)>`
...
61 | path.push(state.clone());
| ^^^^^^^^^^^^^^^^^^^^^^^^ `path` is a `&` reference, so the data it refers to cannot be borrowed as mutable
Changing to frontier.push_back(&mut start) gives a different error:
warning: variable does not need to be mutable
--> src/lib.rs:52:13
|
52 | let mut path = frontier.pop_front().unwrap();
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0499]: cannot borrow `*path` as mutable more than once at a time
--> src/lib.rs:61:13
|
61 | path.push(state.clone());
| ^^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
...
66 | frontier.push_back(path);
| ------------------------
| | |
| | first mutable borrow occurs here
| first borrow later used here
error[E0502]: cannot borrow `path` as immutable because it is also borrowed as mutable
--> src/lib.rs:63:34
|
63 | println!("{:?}", path);
| ^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
...
66 | frontier.push_back(path);
| ---- mutable borrow occurs here
|
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0499]: cannot borrow `*path` as mutable more than once at a time
--> src/lib.rs:66:32
|
66 | frontier.push_back(path);
| ^^^^ `*path` was mutably borrowed here in the previous iteration of the loop
error[E0382]: borrow of moved value: `path`
--> src/lib.rs:61:13
|
52 | let mut path = frontier.pop_front().unwrap();
| -------- ----------------------------- this reinitialization might get skipped
| |
| move occurs because `path` has type `Vec<(u8, u8, Move)>`, which does not implement the `Copy` trait
...
61 | path.push(state.clone());
| ^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
...
66 | frontier.push_back(path);
| ---- value moved here, in previous iteration of loop
I mean, if you're going to store multiple different versions of the path, you need several versions of the path.
You might be able to use a custom linked list with Rc to share parts of the path that are identical, but unless your paths are very long, I don't think it would be worth it.