diff options
-rw-r--r-- | src/main.rs | 4 | ||||
-rw-r--r-- | src/solver.rs | 9 | ||||
-rw-r--r-- | src/solvers/intuitive.rs (renamed from src/solvers.rs) | 72 | ||||
-rw-r--r-- | src/solvers/mod.rs | 1 | ||||
-rw-r--r-- | src/structs.rs | 98 |
5 files changed, 120 insertions, 64 deletions
diff --git a/src/main.rs b/src/main.rs index bb8b978..a1cdd3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ +mod structs; +mod solver; mod solvers; fn main() { - let mut solver = solvers::Solver::<u32>::new(8); + let mut solver = solvers::intuitive::NormalSolver::<u32>::new(6); solver.solve(); //wall.output(solver.n, solver.h); diff --git a/src/solver.rs b/src/solver.rs new file mode 100644 index 0000000..c289cd6 --- /dev/null +++ b/src/solver.rs @@ -0,0 +1,9 @@ +use crate::structs::StoneWall; + +pub trait Solver { + fn new(n: u32) -> Self; + fn solve(&mut self) -> StoneWall; + fn n(&self) -> u32; + fn h(&self) -> u32; + fn w(&self) -> u32; +} diff --git a/src/solvers.rs b/src/solvers/intuitive.rs index a0845a1..61ecbdf 100644 --- a/src/solvers.rs +++ b/src/solvers/intuitive.rs @@ -1,62 +1,8 @@ -pub struct Wall { - heights: Vec<u32>, -} - -impl Wall { - pub fn from_heights(heights: Vec<u32>) -> Self { - Self { heights } - } - - #[allow(dead_code)] - fn create_empty(w: u32) -> Self { - let heights = if w == 0 { - vec![] - } else if w == 1 { - vec![0] - } else { - let mut v = Vec::with_capacity(w as usize); - v.push(0); - v.push(1); - v - }; - Self { heights } - } - - pub fn calculate_row(&self, r: u32, stones: &mut [u32]) { - let mut len = 1; - let mut i = 0; - for &height in self.heights.iter().chain([r].iter()) { - if height == r { - stones[i] = len; - i += 1; - len = 0; - } - len += 1; - } - } - - pub fn output(&self, n: u32, h: u32) { - let mut stones = vec![0; n as usize]; - let mut toggle = 0; - let colors = [ - "\x1b[31m", "\x1b[32m", "\x1b[33m", "\x1b[34m", "\x1b[35m", "\x1b[36m", - ]; - for row in 0..h { - self.calculate_row(row, &mut stones); - for &len in stones.iter() { - print!("{}", colors[toggle]); - toggle = (toggle + 1) % colors.len(); - for _ in 0..len { - print!("◙"); - } - } - println!("\x1b[m"); - } - } -} +use crate::solver::Solver; +use crate::structs::GapHeights; /// Solve for a given N and return the resulting wall -pub struct Solver<T: num::PrimInt> { +pub struct NormalSolver<T: num::PrimInt> { pub n: u32, /// calculated height [might not be correct!] pub h: u32, @@ -133,7 +79,7 @@ impl<T: num::PrimInt> SaveState<T> { } } -impl<T: num::PrimInt> Solver<T> { +impl<T: num::PrimInt> NormalSolver<T> { pub fn new(n: u32) -> Self { let h = n / 2 + 1; let w = h * (n - 1); @@ -195,15 +141,15 @@ impl<T: num::PrimInt> Solver<T> { sums[sum - 1] = i as u32; } } - Wall::from_heights(sums.iter().map(|x| *x as u32).collect()).output(self.w, self.h); + GapHeights::from_heights(sums.iter().map(|x| *x as u32).collect()).output(self.w, self.h); true } #[allow(dead_code)] - fn check_gaps(&mut self, wall: &Wall) -> bool { - for (r, i) in wall.heights.iter().zip(1..self.w) { - let stone = i - self.solve_stack[*r as usize].sum; - self.solve_stack[*r as usize].set_bit(stone); + fn check_gaps(&mut self, wall: &GapHeights) -> bool { + for (i, r) in wall.iter().enumerate() { + let stone = (i + 1) as u32 - self.solve_stack[r as usize].sum; + self.solve_stack[r as usize].set_bit(stone); } for state in self.solve_stack.as_ref() as &[SaveState<T>] { if state.bitmask != T::from(1 << self.n).unwrap() { diff --git a/src/solvers/mod.rs b/src/solvers/mod.rs new file mode 100644 index 0000000..0b1d716 --- /dev/null +++ b/src/solvers/mod.rs @@ -0,0 +1 @@ +pub mod intuitive; diff --git a/src/structs.rs b/src/structs.rs new file mode 100644 index 0000000..571c79d --- /dev/null +++ b/src/structs.rs @@ -0,0 +1,98 @@ +pub struct StoneWall { + rows: Vec<Vec<u32>>, +} + +impl StoneWall { + pub fn create_empty(n: u32) -> Self { + let n = n as usize; + let h = n / 2 + 1; + let mut rows = vec![vec![0; n]; h]; + rows.get_mut(0).map(|r| r[0] = 1); + rows.get_mut(1).map(|r| r[1] = 2); + Self { + rows, + } + } +} + +pub struct GapHeights { + heights: Vec<u32>, +} + +impl GapHeights { + pub fn from_heights(heights: Vec<u32>) -> Self { + Self { heights } + } + + #[allow(dead_code)] + fn create_empty(w: u32) -> Self { + let heights = if w == 0 { + vec![] + } else if w == 1 { + vec![0] + } else { + let mut v = Vec::with_capacity(w as usize); + v.push(0); + v.push(1); + v + }; + Self { heights } + } + + pub fn add_gap(&mut self, height: u32) { + self.add_gap(height) + } + + pub fn calculate_row(&self, r: u32, stones: &mut [u32]) { + let mut len = 1; + let mut i = 0; + for &height in self.heights.iter().chain([r].iter()) { + if height == r { + stones[i] = len; + i += 1; + len = 0; + } + len += 1; + } + } + + pub fn output(&self, n: u32, h: u32) { + let mut stones = vec![0; n as usize]; + let mut toggle = 0; + let colors = [ + "\x1b[31m", "\x1b[32m", "\x1b[33m", "\x1b[34m", "\x1b[35m", "\x1b[36m", + ]; + for row in 0..h { + self.calculate_row(row, &mut stones); + for &len in stones.iter() { + print!("{}", colors[toggle]); + toggle = (toggle + 1) % colors.len(); + for _ in 0..len { + print!("◙"); + } + } + println!("\x1b[m"); + } + } + + pub fn iter<'a>(&'a self) -> GapIter<'a> { + GapIter { + gap_heights: self, + i: 0, + } + } +} + +pub struct GapIter<'a> { + gap_heights: &'a GapHeights, + i: usize, +} + +impl<'a> Iterator for GapIter<'a> { + type Item = u32; + fn next(&mut self) -> Option<Self::Item> { + let i = self.i; + self.i += 1; + self.gap_heights.heights.get(i).map(|&x| x) + } +} |