summaryrefslogtreecommitdiff
path: root/src/solvers/incremental_block.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/solvers/incremental_block.rs')
-rw-r--r--src/solvers/incremental_block.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/solvers/incremental_block.rs b/src/solvers/incremental_block.rs
new file mode 100644
index 0000000..d4ebb81
--- /dev/null
+++ b/src/solvers/incremental_block.rs
@@ -0,0 +1,133 @@
+use std::iter::repeat;
+use crate::solver::{Solver, wall_stats};
+use crate::structs::StoneWall;
+
+pub struct IncrementalBlockSover {
+ n: u32, h: u32, w: u32,
+ rows: Vec<Vec<(u32, u32)>>,
+}
+
+struct SubSolver<'s> {
+ solver: &'s mut IncrementalBlockSover,
+ start: u32,
+ count: u32,
+ heights: Vec<u32>,
+ // for all gaps the possible rows
+ gap_possibilities: Vec<Vec<u32>>,
+ pos: Vec<u32>,
+}
+
+impl<'s> SubSolver<'s> {
+ fn from_index(solver: &'s mut IncrementalBlockSover, index: u32) -> Option<Self> {
+ let gap_possibilities = vec![vec![]; index as usize];
+ let row_existence = vec![false; index as usize];
+ let start = solver.rows[0][index as usize].0 + 1;
+ for row in 1..solver.h {
+ let min_sz = start - solver.row_size(row);
+ for gap in 0..index {
+ if !solver.visited(row, min_sz + gap) {
+ gap_possibilities[gap as usize].push(row);
+ row_existence[row as usize] = true;
+ }
+ }
+ }
+ if row_existence.iter().all(|&x| x) {
+ Some(Self {
+ count: index,
+ start, solver,
+ heights: Vec::with_capacity(index as usize),
+ pos: vec![0; gap_possibilities.len()],
+ gap_possibilities,
+ })
+ } else { None }
+ }
+
+ fn increment_at(&mut self, n: u32) -> bool {
+ if self.pos[n as usize] as usize + 1 == self.gap_possibilities[n as usize].len() {
+ if n as usize + 1 == self.pos.len() {
+ false
+ } else {
+ self.increment_at(n + 1)
+ }
+ } else {
+ self.pos[n as usize] += 1;
+ true
+ }
+ }
+}
+
+impl<'s> Iterator for SubSolver<'s> {
+ type Item = ();
+
+ fn next(&mut self) -> Option<Self::Item> {
+ for (i, p) in self.pos.iter().enumerate().rev() {
+ t
+ }
+ None
+ }
+}
+
+impl IncrementalBlockSover {
+ fn generate_first_row(&mut self) {
+ let mut sum = 0;
+ self.rows[0] = (1..=self.n)
+ .map(|n| {
+ sum += n;
+ (sum - n, n)
+ })
+ .collect();
+ }
+
+ fn get_wall(&self) -> StoneWall {
+ let mut wall = StoneWall::create_empty(self.n);
+ for (h, row) in self.rows.iter().enumerate() {
+ for (n, &(_, stone)) in row.iter().enumerate() {
+ wall.set_stone(h as u32, n as u32, stone).unwrap()
+ }
+ }
+ wall
+ }
+
+ fn visited(&self, row: u32, stone: u32) -> bool {
+ self.rows[row as usize].iter()
+ .position(|&(_, s)| s == stone)
+ .is_some()
+ }
+
+ fn row_size(&self, row: u32) -> u32 {
+ self.rows[row as usize]
+ .last()
+ .map_or(0, |&(i, s)| i + s)
+ }
+}
+
+impl Solver for IncrementalBlockSover {
+ fn new(n: u32) -> Self {
+ let (h, w) = wall_stats(n);
+ Self {
+ n, h, w,
+ rows: repeat(Vec::with_capacity(h as usize))
+ .take(h as usize)
+ .collect()
+ }
+ }
+
+ fn solve(&mut self) -> StoneWall {
+ self.generate_first_row();
+ println!("{:?}", self.rows);
+ self.get_wall()
+ }
+
+ fn n(&self) -> u32 {
+ self.n
+ }
+
+ fn h(&self) -> u32 {
+ self.h
+ }
+
+ fn w(&self) -> u32 {
+ self.w
+ }
+}
+