1#![deny(missing_docs)]
2
3pub use quickbacktrack::*;
106
107pub type Color = u64;
109
110pub const EMPTY_EDGE: Color = 0;
112pub const DISCONNECTED_EDGE: Color = 1;
114
115#[derive(Clone, Debug)]
119pub struct Graph {
120 pub nodes: Vec<Node>,
122 pub edges: Vec<Vec<Color>>,
124 pub pairs: Vec<(usize, usize)>,
126 pub no_triangles: bool,
128 pub meet_quad: bool,
130 pub connected: bool,
132 pub commute_quad: Option<bool>,
145 cache_has_triangles: std::cell::Cell<bool>,
146 cache_connected: std::cell::Cell<bool>,
147 cache_upper_triangle_disconnected: std::cell::Cell<bool>,
148 cache_commute_quad_satisfied: std::cell::Cell<bool>,
149 cache_node_satisfied: Vec<std::cell::Cell<bool>>,
150}
151
152impl Puzzle for Graph {
153 type Pos = (usize, usize);
154 type Val = Color;
155 fn set(&mut self, (i, j): (usize, usize), val: Color) {
156 let old = if j <= i {self.edges[i][j]} else {self.edges[j][i]};
157 if j <= i {self.edges[i][j] = val} else {self.edges[j][i] = val}
158 if old != 0 && val < 2 {
159 self.cache_connected.set(false);
160 self.cache_upper_triangle_disconnected.set(false);
161 }
162 if !(old == 0 && val == 1) {
163 self.cache_commute_quad_satisfied.set(false);
164 }
165 if old != 0 {
166 self.cache_has_triangles.set(false);
167 self.cache_node_satisfied[i].set(false);
168 self.cache_node_satisfied[j].set(false);
169 }
170 }
171 fn get(&self, (i, j): (usize, usize)) -> Color {
172 if j <= i {self.edges[i][j]} else {self.edges[j][i]}
173 }
174 fn print(&self) {
175 for i in 0..self.nodes.len() {
176 eprint!("{} ", self.nodes[i].color);
177 }
178 eprintln!("\n========================================");
179 for i in 0..self.nodes.len() {
180 for j in 0..self.nodes.len() {
181 eprint!("{} ", self.get((i, j)));
182 }
183 eprintln!("");
184 }
185 }
186 fn solve_simple<F: FnMut(&mut Self, Self::Pos, Self::Val)>(&mut self, mut f: F) {
187 let n = self.nodes.len();
188 for i in 0..n {
189 for j in i+1..n {
190 let colors = self.colors((i, j));
191 if colors.len() == 1 {
192 f(self, (i, j), colors[0]);
193 }
194 }
195 }
196 }
197 fn is_solved(&self) -> bool {
198 self.all_satisfied() &&
199 self.pairs_satisfied() &&
200 if self.no_triangles {!self.has_triangles()} else {true} &&
201 if self.connected {self.is_connected()} else {true} &&
202 if let Some(val) = self.commute_quad {self.commute_quad_satisfied(val)} else {true} &&
203 if self.meet_quad {self.meet_quad_satisfied()} else {true}
204 }
205 fn remove(&mut self, other: &Graph) {
206 let n = self.nodes.len();
207 for i in 0..n {
208 for j in i..n {
209 if other.get((i, j)) != 0 {
210 self.set((i, j), 0);
211 }
212 }
213 }
214 }
215}
216
217impl Default for Graph {
218 fn default() -> Graph {Graph::new()}
219}
220
221impl Graph {
222 pub fn new() -> Graph {
229 Graph {
230 nodes: vec![],
231 edges: vec![],
232 pairs: vec![],
233 no_triangles: false,
234 meet_quad: false,
235 connected: false,
236 commute_quad: None,
237 cache_has_triangles: std::cell::Cell::new(false),
238 cache_connected: std::cell::Cell::new(false),
239 cache_upper_triangle_disconnected: std::cell::Cell::new(false),
240 cache_commute_quad_satisfied: std::cell::Cell::new(false),
241 cache_node_satisfied: vec![],
242 }
243 }
244
245 pub fn graphviz(&self, layout: &str, node_colors: &[&str], edge_colors: &[&str]) -> String {
247 use std::fmt::Write;
248
249 let mut s = String::new();
250 writeln!(&mut s, "strict graph {{").unwrap();
251 writeln!(&mut s, " layout={}; edge[penwidth=4]", layout).unwrap();
252 for i in 0..self.nodes.len() {
253 writeln!(&mut s, " {}[regular=true,style=filled,fillcolor={}];", i,
254 node_colors[self.nodes[i].color as usize % node_colors.len()]).unwrap();
255 }
256 for i in 0..self.nodes.len() {
257 for (j, &ed) in self.edges[i].iter().enumerate() {
258 if ed < 2 {continue};
259 writeln!(&mut s, " {} -- {}[color={}];", i, j,
260 edge_colors[(ed - 2) as usize % edge_colors.len()]).unwrap();
261 }
262 }
263 writeln!(&mut s, "}}").unwrap();
264 s
265 }
266
267 pub fn fst_empty(&self) -> Option<(usize, usize)> {
269 let n = self.nodes.len();
270 for i in 0..n {
271 for j in i..n {
272 let s = self.colors((i, j)).len();
273 if s == 0 {continue};
274 if self.get((i, j)) == 0 {
275 return Some((i, j));
276 }
277 }
278 }
279 None
280 }
281
282 pub fn min_colors(&self) -> Option<(usize, usize)> {
284 let mut min: Option<(usize, usize, usize)> = None;
285 let n = self.nodes.len();
286 'outer: for i in 0..n {
287 for j in i..n {
288 let s = self.colors((i, j)).len();
289 if s == 0 {continue};
290 if min.is_none() || min.unwrap().2 > s {
291 min = Some((i, j, s));
292 if s == 1 {break 'outer}
293 }
294 }
295 }
296 min.map(|n| (n.0, n.1))
297 }
298
299 pub fn solve(self, solve_settings: SolveSettings) -> Option<Solution<Graph>> {
303 let solver = BackTrackSolver::new(self, solve_settings);
304 solver.solve(
305 Graph::min_colors,
306 Graph::colors
307 )
308 }
309
310 pub fn push(&mut self, node: Node) {
312 self.nodes.push(node);
313 self.edges.push(vec![0; self.nodes.len()]);
314 self.cache_node_satisfied.push(std::cell::Cell::new(false));
315 }
316
317 pub fn push_pair(&mut self, (i, j): (usize, usize)) {
319 self.pairs.push((i.min(j), i.max(j)));
320 }
321
322 pub fn node_satisfied(&self, i: usize) -> Vec<Constraint> {
326 if self.cache_node_satisfied[i].get() {return vec![]};
327 let mut res = vec![];
328 let mut m = vec![false; self.nodes[i].edges.len()];
329 for j in 0..self.nodes.len() {
330 let edge = self.get((i, j));
331 if edge == 0 {continue};
332 for k in 0..m.len() {
333 if m[k] {continue};
334 let con = &self.nodes[i].edges[k];
335 if con.edge == edge &&
336 con.node == self.nodes[j].color
337 {
338 m[k] = true;
339 break;
340 }
341 }
342 }
343 for k in 0..m.len() {
344 if !m[k] {
345 res.push(self.nodes[i].edges[k].clone());
346 }
347 }
348 if res.len() == 0 {
349 self.cache_node_satisfied[i].set(true);
350 }
351 res
352 }
353
354 pub fn all_satisfied(&self) -> bool {
356 for i in 0..self.nodes.len() {
357 if self.node_satisfied(i).len() != 0 {return false}
358 }
359 true
360 }
361
362 pub fn pairs_satisfied(&self) -> bool {
364 for &(i, j) in &self.pairs {
365 if self.edges[j][i] < 2 {return false}
366 }
367 true
368 }
369
370 pub fn has_triangles(&self) -> bool {
372 if self.cache_has_triangles.get() {return true};
373 let n = self.nodes.len();
374 for i in 0..n {
375 for j in i+1..n {
376 if self.get((i, j)) < 2 {continue};
377 for k in j+1..n {
378 if self.get((j, k)) >= 2 &&
379 self.get((i, k)) >= 2
380 {
381 self.cache_has_triangles.set(true);
382 return true
383 }
384 }
385 }
386 }
387 false
388 }
389
390 pub fn meet_quad_satisfied(&self) -> bool {
393 let n = self.nodes.len();
394 for i in 0..n {
395 let mut found = false;
396 'outer: for j in 0..n {
397 if i == j {continue};
398 if self.get((i, j)) < 2 {continue};
399 for k in j+1..n {
400 if k == i {continue};
401 if self.get((j, k)) < 2 &&
402 self.get((i, k)) < 2 {continue};
403 if self.get((j, k)) >= 2 &&
404 self.get((i, k)) >= 2 {
405 found = true;
407 break 'outer;
408 }
409 for k2 in 0..n {
410 if k2 == i || k2 == j || k2 == k {continue};
411 if self.get((k, k2)) >= 2 &&
412 (
413 self.get((j, k)) >= 2 &&
414 self.get((i, k2)) >= 2 ||
415 self.get((i, k)) >= 2 &&
416 self.get((j, k2)) >= 2
417 )
418 {
419 found = true;
420 break 'outer;
421 }
422 }
423 }
424 }
425
426 if !found {
427 return false
428 }
429 }
430 true
431 }
432
433 pub fn commute_quad_satisfied(&self, commute: bool) -> bool {
438 if self.cache_commute_quad_satisfied.get() {return true};
439 let n = self.nodes.len();
440 for i in 0..n {
441 for j in 0..n {
442 if i == j {continue};
443 if self.get((i, j)) < 2 {continue};
444 for k in j+1..n {
445 if k == i {continue};
446 if self.get((j, k)) < 2 &&
447 self.get((i, k)) < 2 {continue};
448 for k2 in 0..n {
449 if k2 == i || k2 == j || k2 == k {continue};
450 if self.get((k, k2)) >= 2 &&
451 self.get((j, k)) >= 2 &&
452 self.get((i, k2)) >= 2
453 {
454 let s = if commute {
455 self.get((i, j)) == self.get((k, k2)) &&
456 self.get((i, k2)) == self.get((j, k))
457 } else {
458 let ij = self.get((i, j));
459 let jk = self.get((j, k));
460 let kk2 = self.get((k, k2));
461 let ik2 = self.get((i, k2));
462 let x0 = (ij ^ 1) == kk2;
463 let x1 = ij == kk2;
464 let y0 = (jk ^ 1) == ik2;
465 let y1 = jk == ik2;
466 if (x0 ^ x1) && (y0 ^ y1) {x0 ^ y0} else {false}
467 };
468 if !s {return false}
469 } else if self.get((k, k2)) >= 2 &&
470 self.get((i, k)) >= 2 &&
471 self.get((j, k2)) >= 2
472 {
473 let s = if commute {
474 self.get((i, k)) == self.get((j, k2)) &&
475 self.get((i, j)) == self.get((k, k2))
476 } else {
477 let ik = self.get((i, k));
478 let ij = self.get((i, j));
479 let jk2 = self.get((j, k2));
480 let kk2 = self.get((k, k2));
481 let x0 = (ik ^ 1) == jk2;
482 let x1 = ik == jk2;
483 let y0 = (ij ^ 1) == kk2;
484 let y1 = ij == kk2;
485 if (x0 ^ x1) && (y0 ^ y1) {x0 ^ y0} else {false}
486 };
487 if !s {return false}
488 }
489 }
490 }
491 }
492 }
493 self.cache_commute_quad_satisfied.set(true);
494 true
495 }
496
497 pub fn is_connected(&self) -> bool {
499 if self.cache_connected.get() {return true};
500 let n = self.nodes.len();
501 let mut reachable = vec![false; n];
502 for i in 0..n {
503 if self.get((0, i)) >= 2 {
504 reachable[i] = true;
505 }
506 }
507 loop {
508 let mut changed = false;
509 for i in 0..n {
510 if !reachable[i] {
511 for j in 0..n {
512 if reachable[j] && self.get((i, j)) >= 2 {
513 reachable[i] = true;
514 changed = true;
515 break;
516 }
517 }
518 }
519 }
520 if !changed {break}
521 }
522
523 let val = reachable.iter().all(|&b| b);
524 if val {self.cache_connected.set(true)};
525 val
526 }
527
528 pub fn is_upper_right_disconnected(&self) -> bool {
532 if self.cache_upper_triangle_disconnected.get() {return true};
533 let n = self.nodes.len();
534 if n % 2 != 0 {return false}
535 for i in 0..n/2 {
536 for j in n/2..n {
537 if i == j {continue}
538 if self.get((i, j)) != 1 {return false}
539 }
540 }
541 self.cache_upper_triangle_disconnected.set(true);
542 true
543 }
544
545 pub fn colors(&self, (i, j): (usize, usize)) -> Vec<Color> {
547 if self.get((i, j)) != 0 {return vec![]};
548 if !self.nodes[i].self_connected && i == j {return vec![]};
549 if self.no_triangles && self.has_triangles() {return vec![]};
550 if self.connected && self.is_upper_right_disconnected() {return vec![]};
551 if let Some(val) = self.commute_quad {if !self.commute_quad_satisfied(val) {return vec![]}};
552 let mut res = vec![];
553 let errors = self.node_satisfied(i);
554 let other_errors = self.node_satisfied(j);
555 for err in &errors {
556 if err.node != self.nodes[j].color {continue}
557 for other_err in &other_errors {
558 if err.edge == other_err.edge &&
559 other_err.node == self.nodes[i].color
560 {
561 res.push(err.edge);
562 break;
563 }
564 }
565 }
566 res.push(1);
567 res.sort();
568 res.dedup();
569 res
570 }
571}
572
573#[derive(Copy, Clone, Debug, PartialEq, Eq)]
575pub struct Constraint {
576 pub edge: Color,
578 pub node: Color,
580}
581
582#[derive(Clone, Debug, PartialEq, Eq)]
584pub struct Node {
585 pub color: Color,
587 pub self_connected: bool,
589 pub edges: Vec<Constraint>,
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596
597 #[test]
598 fn simple1() {
599 let mut g = Graph::new();
600 let a = Node {
601 color: 1,
602 self_connected: false,
603 edges: vec![Constraint {edge: 2, node: 1}],
604 };
605 assert_eq!(g.nodes.len(), 0);
606 g.push(a.clone());
607 assert_eq!(g.node_satisfied(0), vec![
608 Constraint {edge: 2, node: 1}
609 ]);
610 g.push(a.clone());
611 assert_eq!(g.node_satisfied(0), vec![
612 Constraint {edge: 2, node: 1}
613 ]);
614 assert_eq!(g.node_satisfied(1), vec![
615 Constraint {edge: 2, node: 1}
616 ]);
617 assert_eq!(g.colors((0, 1)), vec![1, 2]);
618 g.set((0, 1), 2);
619 assert_eq!(g.node_satisfied(0), vec![]);
620 g.set((0, 1), 2);
621 assert!(g.all_satisfied());
622 }
623}