diff --git a/examples/brute_force.rs b/examples/brute_force.rs index c806d58..b858656 100644 --- a/examples/brute_force.rs +++ b/examples/brute_force.rs @@ -1,35 +1,64 @@ -use factorio_blueprint::{ - belt_finding::{ - brute_force::{Bruteforce, BruteforceBuilder, PathField}, - Direction, Position, - }, - misc::Map, -}; +use std::io; + +use clap::{Parser, ValueEnum}; +use factorio_blueprint::belt_finding::brute_force::{problems, Bruteforce}; + +#[derive(ValueEnum, Clone)] +enum Mode { + Solutions, + Step, +} + +#[derive(ValueEnum, Clone)] +enum Problem { + Simple, + Snake, + Weaving, +} + +impl Problem { + fn get_problem(&self) -> Bruteforce { + match self { + Problem::Simple => problems::simple(), + Problem::Snake => problems::snake(), + Problem::Weaving => problems::weaving(), + } + } +} + +#[derive(Parser)] +struct Args { + #[arg(value_enum, default_value = "simple")] + problem: Problem, + #[arg(value_enum, default_value = "solutions")] + mode: Mode, +} fn main() { - let mut b = BruteforceBuilder::new(6, 8); + let args = Args::parse(); - b.add_path( - (Position::new(1, 0), Direction::Down), - (Position::new(0, 0), Direction::Up), - ); + let mut b = args.problem.get_problem(); - b.add_path( - (Position::new(4, 0), Direction::Down), - (Position::new(1, 7), Direction::Up), - ); + println!("{b}"); - b.set_blocked_range(0, 2, 5, 5, true); - // b.set_blocked_range(2, 0, 2, 2, true); + match args.mode { + Mode::Solutions => { + while b.next_finish_state() { + println!("{}\n{}\n{}", b.count(), b.solution_count(), b); + } - let mut b = b.build(); - - while b.next_finish_state() { - println!("{}\n{}\n{}", b.count(), b.solution_count(), b); + println!("{}\n{}", b.count(), b.solution_count()); + } + Mode::Step => { + while b.next_state() { + println!("{}", b); + let mut s = String::new(); + let _ = io::stdin().read_line(&mut s); + } + println!("{}\n{}", b.count(), b.solution_count()); + } } - println!("{}\n{}", b.count(), b.solution_count()); - // println!( // "{}\n{}\n{}\n{}", // b.count(), diff --git a/src/belt_finding/brute_force.rs b/src/belt_finding/brute_force.rs index f93be04..1a06a53 100644 --- a/src/belt_finding/brute_force.rs +++ b/src/belt_finding/brute_force.rs @@ -27,16 +27,16 @@ pub enum PathField { } impl PathField { - fn pos(&self) -> &Position { - match self { - PathField::Belt { pos, dir: _ } => pos, - PathField::Underground { - pos, - dir: _, - len: _, - } => pos, - } - } + // fn pos(&self) -> &Position { + // match self { + // PathField::Belt { pos, dir: _ } => pos, + // PathField::Underground { + // pos, + // dir: _, + // len: _, + // } => pos, + // } + // } fn dir(&self) -> &Direction { match self { @@ -408,7 +408,11 @@ impl Bruteforce { pos, dir: second_last.dir().clockwise(), }); - return true; + if self.is_next_free(&pos, &second_last.dir().clockwise()) { + return true; + } else { + return self.modify_remove(); + } } if second_last.dir().clockwise() == dir { @@ -416,7 +420,11 @@ impl Bruteforce { pos, dir: second_last.dir().counter_clockwise(), }); - return true; + if self.is_next_free(&pos, &second_last.dir().counter_clockwise()) { + return true; + } else { + return self.modify_remove(); + } } if second_last.dir().counter_clockwise() == dir @@ -452,6 +460,13 @@ impl Bruteforce { // &mut self.problems[i].path // } + fn is_next_free(&self, pos: &Position, dir: &Direction) -> bool { + let i = self.modify_pointer(); + self.pos_in_direction(pos, dir, 1) + .filter(|p| !self.map.get(p.x, p.y).blocked || self.problems[i].end_pos == *p) + .is_some() + } + // Add an Path elemeent fn add(&mut self) -> bool { let (pos, dir) = self.path_field_end(self.add_path().last().unwrap()); @@ -459,7 +474,7 @@ impl Bruteforce { if let Some(p) = self.pos_in_direction(&pos, &dir, 1) { if !self.map.get(p.x, p.y).blocked { self.apply_path_field(PathField::Belt { pos: p, dir }); - return true; + return self.is_next_free(&p, &dir); } } @@ -599,3 +614,114 @@ impl Display for Bruteforce { Ok(()) } } + +#[cfg(test)] +mod test { + use super::problems; + + #[test] + fn simple() { + let mut b = problems::simple(); + + while b.next_finish_state() {} + + assert_eq!(b.solution_count(), 9); + } + + #[test] + fn snake() { + let mut b = problems::snake(); + + while b.next_finish_state() {} + + assert_eq!(b.solution_count(), 5); + } +} + +pub mod problems { + use super::*; + + pub fn simple() -> Bruteforce { + let mut b = BruteforceBuilder::new(6, 8); + + b.add_path( + (Position::new(1, 0), Direction::Down), + (Position::new(0, 0), Direction::Up), + ); + + b.add_path( + (Position::new(4, 0), Direction::Down), + (Position::new(1, 7), Direction::Up), + ); + + b.set_blocked_range(0, 2, 5, 5, true); + + b.build() + } + + pub fn snake() -> Bruteforce { + let mut p = BruteforceBuilder::new(14, 3); + + p.add_path( + (Position::new(0, 0), Direction::Right), + (Position::new(13, 0), Direction::Right), + ); + p.add_path( + (Position::new(0, 1), Direction::Right), + (Position::new(13, 1), Direction::Right), + ); + p.add_path( + (Position::new(0, 2), Direction::Right), + (Position::new(13, 2), Direction::Right), + ); + + p.set_blocked_range(3, 2, 10, 2, true); + + p.build() + } + + pub fn weaving() -> Bruteforce { + let mut b = BruteforceBuilder::new(14, 6); + + b.add_path( + (Position::new(0, 0), Direction::Right), + (Position::new(13, 0), Direction::Right), + ); + + b.add_path( + (Position::new(0, 1), Direction::Right), + (Position::new(13, 1), Direction::Right), + ); + + b.add_path( + (Position::new(0, 2), Direction::Right), + (Position::new(13, 2), Direction::Right), + ); + + b.add_path( + (Position::new(0, 3), Direction::Right), + (Position::new(13, 3), Direction::Right), + ); + + b.add_path( + (Position::new(0, 4), Direction::Right), + (Position::new(13, 4), Direction::Right), + ); + + b.add_path( + (Position::new(0, 5), Direction::Right), + (Position::new(13, 5), Direction::Right), + ); + + // b.set_blocked_range(7, 2, 10, 2, true); + // b.set_blocked_range(7, 3, 10, 4, true); + + b.set_blocked_range(3, 2, 10, 3, true); + b.set_blocked(2, 0, true); + b.set_blocked(11, 0, true); + b.set_blocked(2, 5, true); + b.set_blocked(11, 5, true); + + b.build() + } +} diff --git a/src/belt_finding/mod.rs b/src/belt_finding/mod.rs index 62b4dd3..1f90724 100644 --- a/src/belt_finding/mod.rs +++ b/src/belt_finding/mod.rs @@ -1,11 +1,10 @@ use crate::belt_finding::brute_force::BruteforceBuilder; use crate::graph::wheighted_graph::shortest_path::dijkstra; use crate::graph::wheighted_graph::WheightedGraph; +use crate::misc::Map; use crate::priority_queue::BinaryHeap; -use crate::{misc::Map, priority_queue::PriorityQueue}; use colored::{Color, Colorize}; -use std::fmt::{write, Display}; -use std::io::Write; +use std::fmt::Display; pub mod brute_force; @@ -42,9 +41,9 @@ impl Direction { } } - fn horizontal(&self) -> bool { - !self.vertical() - } + // fn horizontal(&self) -> bool { + // !self.vertical() + // } fn reverse(&self) -> Self { match self { diff --git a/src/graph/wheighted_graph/mod.rs b/src/graph/wheighted_graph/mod.rs index 20063ee..a27e5e3 100644 --- a/src/graph/wheighted_graph/mod.rs +++ b/src/graph/wheighted_graph/mod.rs @@ -1,8 +1,6 @@ pub mod adjacency_list; pub mod shortest_path; -use clap::builder::NonEmptyStringValueParser; - pub trait WheightedGraph: Sized { type Node; fn num_edges(&self, node: &Self::Node) -> usize; diff --git a/src/graph/wheighted_graph/shortest_path.rs b/src/graph/wheighted_graph/shortest_path.rs index ba9d3d3..a6142ce 100644 --- a/src/graph/wheighted_graph/shortest_path.rs +++ b/src/graph/wheighted_graph/shortest_path.rs @@ -1,9 +1,4 @@ -use std::{ - collections::{BinaryHeap, HashMap}, - fmt::Debug, - hash::Hash, - hash::Hasher, -}; +use std::{collections::HashMap, fmt::Debug, hash::Hash, hash::Hasher}; use crate::priority_queue::PriorityQueue; @@ -87,7 +82,7 @@ where if score < n.score { n.parent = o.node.clone(); n.score = score; - q.decrease_key(&h, |i| i.score = score); + q.decrease_key(h, |i| i.score = score); } } } else { diff --git a/src/priority_queue/fibonacci_heap.rs b/src/priority_queue/fibonacci_heap.rs index 8dcaa98..dca5da5 100644 --- a/src/priority_queue/fibonacci_heap.rs +++ b/src/priority_queue/fibonacci_heap.rs @@ -81,7 +81,7 @@ where } } - fn decrease_key(&mut self, handle: &Self::Handle, f: impl Fn(&mut T)) { + fn decrease_key(&mut self, _handle: &Self::Handle, _f: impl Fn(&mut T)) { todo!() } } @@ -127,7 +127,7 @@ where } let mut prev = None; - let mut start = None; + // let mut start = None; for h in &mut self.update_rank { if let Some(h) = h.take() { @@ -136,7 +136,7 @@ where self.arena.get_mut(&p).right = h; } else { prev = Some(h); - start = Some(h); + // start = Some(h); } if let Some(m) = self.min { if self.arena.get(&h).data < self.arena.get(&m).data {