Improved performance increased memory consumption when complex

master
Hecht 2 years ago
parent a47cf2e7e4
commit 14013de668

@ -0,0 +1,537 @@
┌───────┬───────┬───────┐
| 8 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | | 5 |
| 9 | | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
65 --> Point { x: 0, y: 1, s: 0 } has only 3 possibilities
┌───────┬───────┬───────┐
| 8 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | | 5 |
| 9 | | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
65 --> Probe Point { x: 2, y: 5, s: 3 } 128
63 --> Point { x: 3, y: 7, s: 7 } has only 3 possibilities
┌───────┬───────┬───────┐
| 8 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | | 5 |
| 9 8 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
63 --> Probe Point { x: 2, y: 0, s: 0 } 16
58 --> Point { x: 0, y: 1, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 5 | | |
| | 6 3 8 | 5 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 5 | | 9 |
| | | 5 |
| 9 8 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | 5 |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
58 --> Probe Point { x: 6, y: 3, s: 5 } 128
56 --> Point { x: 0, y: 1, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 5 | | |
| | 6 3 8 | 5 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 5 | | 8 9 |
| | 8 | 5 |
| 9 8 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | 5 |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
56 --> Probe Point { x: 0, y: 7, s: 6 } 128
55 --> Point { x: 0, y: 1, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 5 | | |
| | 6 3 8 | 5 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 5 | | 8 9 |
| | 8 | 5 |
| 9 8 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | 5 |
| 8 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
55 --> Probe Point { x: 1, y: 2, s: 0 } 256
51 --> Point { x: 0, y: 1, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 5 | | 9 |
| | 6 3 8 | 5 4 1 |
| 9 | 5 | |
├───────┼───────┼───────┤
| 5 | | 8 9 |
| | 9 8 | 5 |
| 9 8 | 5 | |
├───────┼───────┼───────┤
| 9 | 8 2 | 5 |
| 8 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
51 --> Probe Point { x: 0, y: 4, s: 3 } 64
65 --> Probe Point { x: 2, y: 5, s: 3 } 64
63 --> Point { x: 5, y: 1, s: 1 } has only 3 possibilities
┌───────┬───────┬───────┐
| 8 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
63 --> Probe Point { x: 2, y: 0, s: 0 } 2
59 --> Point { x: 0, y: 1, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 2 | | |
| | 6 3 8 | 2 4 1 |
| | 5 2 | |
├───────┼───────┼───────┤
| | | 9 |
| | | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
63 --> Probe Point { x: 2, y: 0, s: 0 } 1
62 --> Point { x: 3, y: 0, s: 1 } has only 3 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
62 --> Probe Point { x: 5, y: 4, s: 4 } 64
60 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | 9 7 | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
60 --> Probe Point { x: 0, y: 7, s: 6 } 64
57 --> Point { x: 4, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 7 | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | 9 7 | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 7 2 | |
| 7 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
57 --> Probe Point { x: 6, y: 3, s: 5 } 4
51 --> Point { x: 5, y: 8, s: 7 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 7 | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | 2 | 3 9 7 |
| | 9 7 | 5 |
| 9 7 | 3 5 | |
├───────┼───────┼───────┤
| | 8 7 2 | |
| 7 5 | 1 9 | |
| | 4 5 | 9 7 |
└───────┴───────┴───────┘
51 --> Probe Point { x: 0, y: 4, s: 3 } 8
50 --> Point { x: 4, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 7 | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | 2 | 3 9 7 |
| 4 | 9 7 | 5 |
| 9 7 | 3 5 | |
├───────┼───────┼───────┤
| | 8 7 2 | |
| 7 5 | 1 9 | |
| | 4 5 | 9 7 |
└───────┴───────┴───────┘
50 --> Probe Point { x: 8, y: 2, s: 2 } 256
43 --> Point { x: 0, y: 2, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 7 4 9 | |
| | 6 3 8 | 4 1 |
| | 5 2 1 | 9 |
├───────┼───────┼───────┤
| | 2 4 | 3 9 7 |
| 4 | 9 7 | 5 |
| 9 7 | 3 5 | |
├───────┼───────┼───────┤
| | 8 7 2 | |
| 7 5 | 1 9 | |
| | 4 5 | 9 7 |
└───────┴───────┴───────┘
43 --> Probe Point { x: 1, y: 6, s: 6 } 4
36 --> Point { x: 1, y: 3, s: 3 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 7 4 9 | |
| 9 | 6 3 8 | 7 4 1 |
| 7 4 | 5 2 1 | 9 |
├───────┼───────┼───────┤
| | 2 4 | 3 9 7 |
| 4 3 | 9 7 | 5 |
| 9 7 | 3 5 | |
├───────┼───────┼───────┤
| 3 9 | 8 7 2 | |
| 7 5 | 1 9 | |
| | 4 5 | 9 7 |
└───────┴───────┴───────┘
36 --> Probe Point { x: 8, y: 7, s: 8 } 4
31 --> Point { x: 0, y: 6, s: 6 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 7 4 9 | |
| 9 | 6 3 8 | 7 4 1 |
| 7 4 | 5 2 1 | 9 |
├───────┼───────┼───────┤
| | 2 4 | 3 9 7 |
| 4 3 | 9 7 | 5 |
| 9 7 | 3 5 | 4 |
├───────┼───────┼───────┤
| 3 9 | 8 7 2 | |
| 7 5 | 1 9 6 | 4 3 |
| | 4 5 3 | 9 7 |
└───────┴───────┴───────┘
31 --> Probe Point { x: 0, y: 0, s: 0 } 32
62 --> Probe Point { x: 5, y: 4, s: 4 } 32
59 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
59 --> Probe Point { x: 0, y: 3, s: 3 } 128
57 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 8 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
57 --> Probe Point { x: 6, y: 5, s: 5 } 4
56 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 8 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 3 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
56 --> Probe Point { x: 6, y: 7, s: 8 } 128
53 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 8 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 8 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 3 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | 8 |
| 8 | 4 5 | 9 |
└───────┴───────┴───────┘
53 --> Probe Point { x: 0, y: 0, s: 0 } 64
38 --> Point { x: 6, y: 0, s: 2 } has only 2 possibilities
┌───────┬───────┬───────┐
| 7 8 1 | 2 4 9 | |
| 5 | 6 3 8 | 7 4 1 |
| | 5 1 7 | 2 8 9 |
├───────┼───────┼───────┤
| 8 5 | 3 4 | 9 |
| | 9 6 | 5 |
| 9 7 | 1 5 | 3 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 7 9 | 8 |
| 8 | 4 5 | 9 |
└───────┴───────┴───────┘
59 --> Probe Point { x: 0, y: 3, s: 3 } 32
57 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 6 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
57 --> Probe Point { x: 6, y: 5, s: 5 } 4
56 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 6 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 3 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
56 --> Probe Point { x: 8, y: 2, s: 2 } 256
54 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 9 | |
| | 6 3 | 4 1 |
| | 5 | 9 |
├───────┼───────┼───────┤
| 6 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 3 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
54 --> Probe Point { x: 6, y: 7, s: 8 } 1
35 --> Point { x: 7, y: 6, s: 8 } has only 2 possibilities
┌───────┬───────┬───────┐
| 4 8 1 | 7 2 9 | |
| 5 | 6 3 8 | 4 1 |
| | 5 1 4 | 9 |
├───────┼───────┼───────┤
| 6 2 5 | 1 3 | 9 |
| | 9 6 | 5 |
| 9 4 7 | 2 8 5 | 3 1 6 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 3 9 7 | 1 |
| | 4 5 1 | 9 |
└───────┴───────┴───────┘
57 --> Probe Point { x: 6, y: 5, s: 5 } 2
56 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 6 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 2 |
├───────┼───────┼───────┤
| | 8 6 2 | |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
56 --> Probe Point { x: 8, y: 0, s: 2 } 256
54 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | | 9 |
| | 6 3 | 4 1 |
| | 5 | |
├───────┼───────┼───────┤
| 6 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 2 |
├───────┼───────┼───────┤
| | 8 6 2 | 5 |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
54 --> Probe Point { x: 8, y: 7, s: 8 } 32
45 --> Point { x: 6, y: 2, s: 2 } has only 2 possibilities
┌───────┬───────┬───────┐
| 5 8 1 | | 6 3 9 |
| | 6 3 8 | 5 4 1 |
| | 5 1 9 | |
├───────┼───────┼───────┤
| 6 5 | | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 2 6 |
├───────┼───────┼───────┤
| | 8 6 2 | 5 |
| 5 | 9 | 6 |
| | 4 5 | 9 |
└───────┴───────┴───────┘
45 --> Probe Point { x: 6, y: 3, s: 5 } 128
41 --> Point { x: 3, y: 0, s: 1 } has only 2 possibilities
┌───────┬───────┬───────┐
| 5 8 1 | | 6 3 9 |
| | 6 3 8 | 5 4 1 |
| | 5 1 9 | 7 |
├───────┼───────┼───────┤
| 6 5 | | 8 9 |
| | 9 6 | 1 5 |
| 9 7 | 8 5 | 2 6 |
├───────┼───────┼───────┤
| | 8 6 2 | 5 |
| 5 | 9 | 6 |
| | 4 5 | 9 |
└───────┴───────┴───────┘
41 --> Probe Point { x: 1, y: 8, s: 6 } 64
36 --> Point { x: 6, y: 7, s: 8 } has only 2 possibilities
┌───────┬───────┬───────┐
| 5 8 1 | | 6 3 9 |
| 7 | 6 3 8 | 5 4 1 |
| 6 | 5 1 9 | 7 |
├───────┼───────┼───────┤
| 6 5 | | 8 9 |
| | 9 6 | 1 5 |
| 9 7 | 8 5 | 2 6 |
├───────┼───────┼───────┤
| | 8 6 2 | 7 5 |
| 5 | 9 | 6 |
| 7 6 | 4 5 | 9 |
└───────┴───────┴───────┘
56 --> Probe Point { x: 8, y: 0, s: 2 } 64
48 --> Point { x: 8, y: 3, s: 5 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 2 4 9 | 7 |
| | 6 3 | 4 1 |
| | 5 | 2 9 |
├───────┼───────┼───────┤
| 6 5 | 4 | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 2 |
├───────┼───────┼───────┤
| | 8 6 2 | 5 |
| 5 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
48 --> Probe Point { x: 2, y: 7, s: 6 } 8
46 --> Point { x: 2, y: 2, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 2 4 9 | 7 |
| | 6 3 | 4 1 |
| | 5 | 2 9 |
├───────┼───────┼───────┤
| 6 5 | 4 | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 2 |
├───────┼───────┼───────┤
| | 8 6 2 | 4 5 |
| 5 4 | 9 | |
| | 4 5 | 9 |
└───────┴───────┴───────┘
46 --> Probe Point { x: 8, y: 7, s: 8 } 2
45 --> Point { x: 2, y: 2, s: 0 } has only 2 possibilities
┌───────┬───────┬───────┐
| 8 1 | 2 4 9 | 7 |
| | 6 3 | 4 1 |
| | 5 | 2 9 |
├───────┼───────┼───────┤
| 6 5 | 4 | 9 |
| | 9 6 | 5 |
| 9 7 | 5 | 2 |
├───────┼───────┼───────┤
| | 8 6 2 | 4 5 |
| 5 4 | 9 | 2 |
| | 4 5 | 9 |
└───────┴───────┴───────┘
45 --> Probe Point { x: 6, y: 4, s: 5 } 4
┌───────┬───────┬───────┐
| 5 8 1 | 2 4 9 | 6 3 7 |
| 7 9 2 | 6 3 8 | 5 4 1 |
| 4 6 3 | 5 1 7 | 8 2 9 |
├───────┼───────┼───────┤
| 6 3 5 | 1 2 4 | 7 9 8 |
| 1 2 8 | 9 7 6 | 3 5 4 |
| 9 4 7 | 3 8 5 | 2 1 6 |
├───────┼───────┼───────┤
| 3 1 9 | 8 6 2 | 4 7 5 |
| 8 5 4 | 7 9 3 | 1 6 2 |
| 2 7 6 | 4 5 1 | 9 8 3 |
└───────┴───────┴───────┘
Solver found a solution for this sudoku!!
┌───────┬───────┬───────┐
| 5 8 1 | 2 4 9 | 6 3 7 |
| 7 9 2 | 6 3 8 | 5 4 1 |
| 4 6 3 | 5 1 7 | 8 2 9 |
├───────┼───────┼───────┤
| 6 3 5 | 1 2 4 | 7 9 8 |
| 1 2 8 | 9 7 6 | 3 5 4 |
| 9 4 7 | 3 8 5 | 2 1 6 |
├───────┼───────┼───────┤
| 3 1 9 | 8 6 2 | 4 7 5 |
| 8 5 4 | 7 9 3 | 1 6 2 |
| 2 7 6 | 4 5 1 | 9 8 3 |
└───────┴───────┴───────┘

@ -4,6 +4,8 @@ use std::collections::HashSet;
use crate::solver::{Solver, Generator, SodokuComplexity}; use crate::solver::{Solver, Generator, SodokuComplexity};
use crate::board::Board; use crate::board::Board;
use crate::utils::*; use crate::utils::*;
use std::borrow::Borrow;
use std::rc::Rc;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
const NUM : usize = 3; const NUM : usize = 3;
@ -24,7 +26,7 @@ struct Point {
pub s: usize, pub s: usize,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
enum Action { enum Action {
Trivial(Point, u16), Trivial(Point, u16),
Logic(Point, u16), Logic(Point, u16),
@ -41,13 +43,13 @@ struct SolverBoard {
} }
enum SolverBoardItem { enum SolverBoardItem {
Recursive(Vec<Action>), Prepare(Rc<SolverBoard>, Rc<HashSet<Action>>, Rc<Vec<Action>>, usize),
Initial, Process(Rc<SolverBoard>, Rc<HashSet<Action>>, Action),
Initial(SolverBoard),
} }
struct SolverBoardIterator { struct SolverBoardIterator {
cache: HashSet<[[u16; VALUES]; VALUES]>, // to avoid processing the same board twice cache: HashSet<[[u16; VALUES]; VALUES]>, // to avoid processing the same board twice
board: SolverBoard,
stack: Vec<SolverBoardItem>, stack: Vec<SolverBoardItem>,
} }
@ -68,20 +70,25 @@ impl HechtSolver {
return HechtSolver {}; return HechtSolver {};
} }
pub fn test(&self, board: &Board) -> bool { pub fn test(&self, board: &Board) {
let mut invalid_counter = 0; let mut invalid_counter = 0;
let mut unsolved_counter = 0; let mut unsolved_counter = 0;
let mut solved_counter = 0; let mut solved_counter = 0;
let count = 1024;
SolverBoardIterator::new(board) let mut boards : HashSet<Board> = HashSet::with_capacity(count);
let count = SolverBoardIterator::new(board)
.inspect(|_| invalid_counter += 1) .inspect(|_| invalid_counter += 1)
.filter(|x| x.valid) .filter(|x| x.valid)
.inspect(|_| unsolved_counter += 1) .inspect(|_| unsolved_counter += 1)
.filter(|x| x.is_solved()) .filter(|x| x.is_solved())
.inspect(|_| solved_counter += 1) .inspect(|_| solved_counter += 1)
.inspect(|x| x.to_board().unwrap().print() ) .filter_map(|x| x.to_board() )
.nth(1024).and_then(|_| {println!("I: {}, U: {}, S: {}", invalid_counter, unsolved_counter, solved_counter); Some(true)}) .take(1024)
.is_some() .for_each(|board| {boards.insert(board); });
println!("I: {}, U: {}, S: {}, B: {}", invalid_counter, unsolved_counter, solved_counter, boards.len())
} }
@ -138,9 +145,6 @@ impl SolverBoard {
} }
spg.solve_logically(); spg.solve_logically();
assert!(spg.valid);
spg spg
} }
@ -150,13 +154,11 @@ impl SolverBoard {
for x in 0..VALUES { for x in 0..VALUES {
for y in 0..VALUES { for y in 0..VALUES {
let value = self.arr[y][x]; let value = self.arr[y][x];
if value.count_ones() != 1 { if value.count_ones() == 1 {
return None
}
pg.set_value(x, y, (value.trailing_zeros() + 1) as u8); pg.set_value(x, y, (value.trailing_zeros() + 1) as u8);
} }
} }
}
Some(pg) Some(pg)
} }
@ -164,7 +166,7 @@ impl SolverBoard {
fn solve_logically(&mut self) { fn solve_logically(&mut self) {
while self.valid { while self.valid {
if let Some(action) = self.get_simple_action() { if let Some(action) = self.get_simple_action() {
self.apply(&action); self.apply(action);
} else { } else {
break; break;
} }
@ -214,16 +216,6 @@ impl SolverBoard {
self.arr[p.y][p.x] = bit_value; self.arr[p.y][p.x] = bit_value;
// self.todos.iter()
// // Filter positions that do not have the right coordinates
// .filter(|&pos| pos.x == p.x || pos.y == p.y || pos.s == p.s)
// // Filter positions that were known not to hold the value
// .filter(|&pos| (self.arr[pos.y][pos.x] & bit_value) != 0)
// .cloned()
// .collect::<Vec::<_>>()
// .iter()
// .for_each(|pos| self.remove_value(&pos, bit_value));
for idx in 0..CELLS { for idx in 0..CELLS {
let other = Point::from_index(idx); let other = Point::from_index(idx);
if p != &other && (other.x == p.x || other.y == p.y || other.s == p.s) { if p != &other && (other.x == p.x || other.y == p.y || other.s == p.s) {
@ -241,7 +233,7 @@ impl SolverBoard {
let point_value = self.arr[p.y][p.x]; let point_value = self.arr[p.y][p.x];
match point_value.count_ones() { match point_value.count_ones() {
1 => self.apply(&Action::Trivial(p, point_value)), 1 => self.apply(Action::Trivial(p, point_value)),
0 => self.valid = false, 0 => self.valid = false,
_ => {} _ => {}
} }
@ -254,7 +246,7 @@ impl SolverBoard {
Some(Action::Logic(p.clone(), bit_value)) Some(Action::Logic(p.clone(), bit_value))
} }
fn apply(&mut self, action : &Action) { fn apply(&mut self, action : Action) {
let (point, value) = action.get(); let (point, value) = action.get();
self.set_bit_value(point, value); self.set_bit_value(point, value);
@ -262,7 +254,7 @@ impl SolverBoard {
self.solve_logically(); self.solve_logically();
} }
self.audit.push(action.clone()); self.audit.push(action);
} }
@ -316,8 +308,9 @@ impl SolverBoard {
.map(|point| (point, self.get_value(point))) .map(|point| (point, self.get_value(point)))
.collect::<Vec<_>>(); // collect into the vector so we can (optionally) apply sorting .collect::<Vec<_>>(); // collect into the vector so we can (optionally) apply sorting
// now sort it (lowest value should be at the end (we use it as a stack)) vec.sort_unstable_by_key(|action| action.1.count_ones());
vec.sort_unstable_by_key(|action| CELLS as u32 - action.1.count_ones());
// println!(" {} --> {:?} has only {} possibilities", self.todos.len(), vec[0].0, vec[0].1.count_ones());
return vec.iter() return vec.iter()
.map(|action| SolverBoard::get_bitvalue_sequence().iter() .map(|action| SolverBoard::get_bitvalue_sequence().iter()
@ -339,97 +332,87 @@ impl SolverBoardIterator {
} }
fn from_board(board: SolverBoard) -> SolverBoardIterator { fn from_board(board: SolverBoard) -> SolverBoardIterator {
SolverBoardIterator{cache: HashSet::with_capacity(128), board, stack: vec![SolverBoardItem::Initial]} SolverBoardIterator{cache: HashSet::with_capacity(128), stack: vec![SolverBoardItem::Initial(board)]}
} }
fn next_board(&mut self) -> Option<SolverBoard> { fn next_board(&mut self) -> Option<SolverBoard> {
let mut result;
while let Some(item) = self.stack.pop() { while let Some(item) = self.stack.pop() {
if let SolverBoardItem::Recursive(actions) = item { // println!("Stack size {}, cache size {}", self.stack.len(), self.cache.len());
result = self.push_actions(&actions); if let Some(board) = self.pop_board(item) {
} else { return Some(board);
// initial
result = self.push_actions(&Vec::new());
}
if result.is_some() {
return result;
} }
} }
None None
} }
fn push_actions(&mut self, actions: &Vec<Action>) -> Option<SolverBoard> { fn pop_board(&mut self, item : SolverBoardItem) -> Option<SolverBoard> {
if self.already_processed(actions) { match item {
println!("Early hit! Stack: {}, Cache: {}", self.stack.len(), self.cache.len()); SolverBoardItem::Initial(board) => {
return None; self.handle_initial(board)
}
let mut new_board = self.board.clone();
let mut iter = actions.iter().peekable();
let mut arr_backup : Option<[[u16; VALUES]; VALUES]>= None;
while let Some(action) = iter.next() {
if iter.peek().is_some() {
new_board.apply(&action);
} else {
arr_backup = Some(new_board.arr);
new_board.apply(&action);
} }
SolverBoardItem::Process(board, excludes, action) => {
self.handle_process(board, excludes, action)
} }
SolverBoardItem::Prepare(board, excludes, actions, index) => {
if !new_board.valid { self.handle_prepare(board, excludes, actions, index)
if let Some(mut arr) = arr_backup {
if let Some(action) = actions.last() {
let (point, value) = action.get();
arr[point.y][point.x] = value;
self.insert_to_cache(arr);
} }
} }
return None
} }
if self.insert_to_cache(new_board.arr) { fn handle_initial(&mut self, board: SolverBoard) -> Option<SolverBoard> {
if !new_board.is_solved() { if board.valid {
let mut actions_copy = actions.to_vec(); return self.handle_board(Rc::new(board), Rc::new(HashSet::with_capacity(CELLS * VALUES)))
for action in new_board.get_all_actions() {
actions_copy.push(action);
self.stack.push(SolverBoardItem::Recursive(actions_copy.to_vec()));
actions_copy.pop();
}
}
return Some(new_board);
} else {
println!("Late hit! Stack: {}, Cache: {}", self.stack.len(), self.cache.len())
} }
None None
} }
/** /**
* Check if we can find a board in the cache, where all actions in the * The preparation step is quite memory and time consuming.
* vector have been applied. * For this reason it has been extracted into a separate computing step.
* Best case is, that only the last process step requires preparation.
*/ */
fn already_processed(&mut self, actions : &Vec<Action>) -> bool { fn handle_prepare(&mut self, board_ref: Rc<SolverBoard>, excludes_ref: Rc<HashSet<Action>>, actions: Rc<Vec<Action>>, index : usize) -> Option<SolverBoard> {
for board in self.cache.iter() { let mut excludes_ref = excludes_ref; // re-label
let applied = actions.iter() let excludes = Rc::make_mut(&mut excludes_ref);
.map(|a| a.get())
.all(|a| board[a.0.y][a.0.x] == a.1); // extend the current exclude list by the exceeded actions in the list (before the own index)
if applied { actions.iter().rev().take(index)
return true .for_each(|action| {excludes.insert(action.clone());});
self.stack.push(SolverBoardItem::Process(Rc::clone(&board_ref), Rc::clone(&excludes_ref), actions[index].clone()));
None
} }
fn handle_process(&mut self, board_ref: Rc<SolverBoard>, excludes: Rc<HashSet<Action>>, action: Action) -> Option<SolverBoard> {
let mut board_ref = board_ref; // re-label
let board = Rc::make_mut(&mut board_ref);
// println!(" {} --> Probe {:?} {:?}", board.todos.len(), action.get().0, action.get().1);
board.apply(action);
if !board.valid || !self.cache.insert(board.arr) {
return None;
} }
false
return self.handle_board(board_ref, excludes);
} }
fn insert_to_cache(&mut self, mut array : [[u16; VALUES]; VALUES]) -> bool {
for x in array.iter_mut() fn handle_board(&mut self, board: Rc<SolverBoard>, excludes: Rc<HashSet<Action>>)-> Option<SolverBoard> {
.flatten() if !board.is_solved() {
.filter(|value| value.count_ones() != 1) {
*x = 0; let actions = Rc::new(board.get_all_actions());
actions.iter()
.rev()
.enumerate()
.filter(|it| !excludes.contains(it.1))
.for_each(|it| self.stack.push(SolverBoardItem::Prepare(Rc::clone(&board), Rc::clone(&excludes), Rc::clone(&actions), it.0)))
} }
self.cache.insert(array) Some((*board).clone())
} }
} }
impl Iterator for SolverBoardIterator { impl Iterator for SolverBoardIterator {

Loading…
Cancel
Save