deus/solvers/
state2.rs

1pub trait Level {
2    fn size(&self) -> (usize, usize);
3    fn is_solved(&self) -> bool;
4    fn make_move<'a>(&'a mut self, x: usize, y: usize) -> &'a mut dyn Level;
5    fn get(&self, x: usize, y: usize) -> Option<usize>;
6    fn set(&mut self, x: usize, y: usize, v: usize) -> bool;
7}
8
9#[derive(Debug)]
10pub struct StructLevel {
11    sx: usize,
12    sy: usize,
13    level: Vec<Vec<usize>>,
14}
15
16impl StructLevel {
17    pub fn new(sx: usize, sy: usize) -> StructLevel {
18        let v = vec![vec![0usize; sx]; sy];
19        StructLevel {
20            sx: sx,
21            sy: sy,
22            level: v,
23        }
24    }
25}
26
27impl Level for StructLevel {
28    fn size(&self) -> (usize, usize) {
29        (self.sx, self.sy)
30    }
31
32    fn get(&self, x: usize, y: usize) -> Option<usize> {
33        if x < self.sx && y < self.sy {
34            Some(self.level[y][x])
35        } else {
36            None
37        }
38    }
39
40    fn set(&mut self, x: usize, y: usize, v: usize) -> bool {
41        if x < self.sx && y < self.sy {
42            match v {
43                0..=1 => {
44                    *self.level.get_mut(y).unwrap().get_mut(x).unwrap() = v;
45                    true
46                }
47                _ => false,
48            }
49        } else {
50            false
51        }
52    }
53
54    fn is_solved(&self) -> bool {
55        for v in self.level.iter() {
56            for e in v.iter() {
57                if *e != 1 {
58                    return false;
59                }
60            }
61        }
62        true
63    }
64
65    fn make_move<'a>(&'a mut self, x: usize, y: usize) -> &'a mut dyn Level {
66        if x >= self.sx || y >= self.sy {
67            return self;
68        }
69        fn switch(this: &mut StructLevel, x: usize, y: usize) {
70            match this.get(x, y) {
71                Some(1) => this.set(x, y, 0),
72                Some(0) => this.set(x, y, 1),
73                _ => false,
74            };
75        }
76        if y > 0 {
77            switch(self, x, y - 1);
78        }
79        if x > 0 {
80            switch(self, x - 1, y);
81        }
82        switch(self, x, y);
83        switch(self, x + 1, y);
84        switch(self, x, y + 1);
85        self
86    }
87}
88
89pub fn solve(level: &StructLevel) -> Option<Vec<(usize, usize)>> {
90    let (sx, sy) = level.size();
91    let mut mat = vec![vec![0usize; sy * sx]; sy * sx];
92    let mut blank = StructLevel::new(sx, sy);
93    let mut expected = vec![0; sx * sy];
94    for y in 0..sy {
95        for x in 0..sx {
96            let row = y * sx + x;
97            blank.make_move(x, y);
98            for by in 0..sy {
99                for bx in 0..sx {
100                    let col = by * sx + bx;
101                    *mat.get_mut(row).unwrap().get_mut(col).unwrap() = blank.get(bx, by).unwrap();
102                }
103            }
104            blank.make_move(x, y);
105            *expected.get_mut(row).unwrap() = level.get(x, y).unwrap() + 1 % 2;
106        }
107    }
108    let sol = gauss_jordan_zf2(mat, expected);
109    match sol {
110        Some(s) => {
111            let mut ret = Vec::with_capacity(s.len());
112            for i in 0..s.len() {
113                if s[i] != 0 {
114                    let x = i % sx;
115                    let y = i / sx;
116                    ret.push((x, y));
117                }
118            }
119            Some(ret)
120        }
121        None => None,
122    }
123}
124
125fn gauss_jordan_zf2(mat: Vec<Vec<usize>>, expected: Vec<usize>) -> Option<Vec<usize>> {
126    let mut m = mat.clone();
127    let mut bs = expected.clone();
128    let rows = m.len();
129    if rows == 0 {
130        return None;
131    }
132    let cols = m[0].len();
133    if cols == 0 {
134        return None;
135    }
136
137    fn swap(m: &mut Vec<Vec<usize>>, bs: &mut Vec<usize>, i: usize, j: usize) {
138        if i == j {
139            return;
140        }
141        // XXX is cloning optimal here?
142        let tmpi = m.get(i).unwrap().clone();
143        let tmpj = m.get(j).unwrap().clone();
144        *m.get_mut(i).unwrap() = tmpj;
145        *m.get_mut(j).unwrap() = tmpi;
146
147        let tmp = *bs.get(i).unwrap();
148        *bs.get_mut(i).unwrap() = *bs.get(j).unwrap();
149        *bs.get_mut(j).unwrap() = tmp;
150    };
151
152    fn add(m: &mut Vec<Vec<usize>>, bs: &mut Vec<usize>, i: usize, j: usize) {
153        if i == j {
154            panic!("trying to add row to itself");
155        }
156        for x in 0..m.get(i).unwrap().len() {
157            *m.get_mut(i).unwrap().get_mut(x).unwrap() += *m.get(j).unwrap().get(x).unwrap();
158            *m.get_mut(i).unwrap().get_mut(x).unwrap() %= 2;
159        }
160        *bs.get_mut(i).unwrap() += *bs.get(j).unwrap();
161        *bs.get_mut(i).unwrap() %= 2;
162    };
163
164    for pivot in 0..rows {
165        // 1. find pivot row
166        for i in pivot..rows {
167            if m[i][pivot] != 0 {
168                swap(&mut m, &mut bs, i, pivot);
169                break;
170            }
171        }
172        if m[pivot][pivot] == 0 && bs[pivot] != 0 {
173            return None;
174        }
175
176        // 2. add pivot to all rows that have 1 in this column
177        for i in 0..rows {
178            if i == pivot {
179                continue;
180            }
181            if m[i][pivot] != 0 {
182                add(&mut m, &mut bs, i, pivot);
183            }
184        }
185    }
186    Some(bs)
187}
188
189#[test]
190fn test(){
191    let s = StructLevel::new(9,9);
192    if let Some(s) = solve(&s) {
193        for (i, j) in s {
194            println!("({}, {})", i + 1, j + 1)
195        }
196    }
197}