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 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 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 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}