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::board::Board;
use crate::utils::*;
use std::borrow::Borrow;
use std::rc::Rc;
use std::hash::{Hash, Hasher};
const NUM : usize = 3;
@ -24,7 +26,7 @@ struct Point {
pub s: usize,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
enum Action {
Trivial(Point, u16),
Logic(Point, u16),
@ -41,13 +43,13 @@ struct SolverBoard {
}
enum SolverBoardItem {
Recursive(Vec<Action>),
Initial,
Prepare(Rc<SolverBoard>, Rc<HashSet<Action>>, Rc<Vec<Action>>, usize),
Process(Rc<SolverBoard>, Rc<HashSet<Action>>, Action),
Initial(SolverBoard),
}
struct SolverBoardIterator {
cache: HashSet<[[u16; VALUES]; VALUES]>, // to avoid processing the same board twice
board: SolverBoard,
stack: Vec<SolverBoardItem>,
}
@ -68,20 +70,25 @@ impl HechtSolver {
return HechtSolver {};
}
pub fn test(&self, board: &Board) -> bool {
pub fn test(&self, board: &Board) {
let mut invalid_counter = 0;
let mut unsolved_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)
.filter(|x| x.valid)
.inspect(|_| unsolved_counter += 1)
.filter(|x| x.is_solved())
.inspect(|_| solved_counter += 1)
.inspect(|x| x.to_board().unwrap().print() )
.nth(1024).and_then(|_| {println!("I: {}, U: {}, S: {}", invalid_counter, unsolved_counter, solved_counter); Some(true)})
.is_some()
.filter_map(|x| x.to_board() )
.take(1024)
.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();
assert!(spg.valid);
spg
}
@ -150,11 +154,9 @@ impl SolverBoard {
for x in 0..VALUES {
for y in 0..VALUES {
let value = self.arr[y][x];
if value.count_ones() != 1 {
return None
if value.count_ones() == 1 {
pg.set_value(x, y, (value.trailing_zeros() + 1) as u8);
}
pg.set_value(x, y, (value.trailing_zeros() + 1) as u8);
}
}
@ -164,7 +166,7 @@ impl SolverBoard {
fn solve_logically(&mut self) {
while self.valid {
if let Some(action) = self.get_simple_action() {
self.apply(&action);
self.apply(action);
} else {
break;
}
@ -213,16 +215,6 @@ impl SolverBoard {
}
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 {
let other = Point::from_index(idx);
@ -241,7 +233,7 @@ impl SolverBoard {
let point_value = self.arr[p.y][p.x];
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,
_ => {}
}
@ -254,7 +246,7 @@ impl SolverBoard {
Some(Action::Logic(p.clone(), bit_value))
}
fn apply(&mut self, action : &Action) {
fn apply(&mut self, action : Action) {
let (point, value) = action.get();
self.set_bit_value(point, value);
@ -262,7 +254,7 @@ impl SolverBoard {
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)))
.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| CELLS as u32 - action.1.count_ones());
vec.sort_unstable_by_key(|action| action.1.count_ones());
// println!(" {} --> {:?} has only {} possibilities", self.todos.len(), vec[0].0, vec[0].1.count_ones());
return vec.iter()
.map(|action| SolverBoard::get_bitvalue_sequence().iter()
@ -339,97 +332,87 @@ impl 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> {
let mut result;
while let Some(item) = self.stack.pop() {
if let SolverBoardItem::Recursive(actions) = item {
result = self.push_actions(&actions);
} else {
// initial
result = self.push_actions(&Vec::new());
}
if result.is_some() {
return result;
// println!("Stack size {}, cache size {}", self.stack.len(), self.cache.len());
if let Some(board) = self.pop_board(item) {
return Some(board);
}
}
None
}
fn push_actions(&mut self, actions: &Vec<Action>) -> Option<SolverBoard> {
if self.already_processed(actions) {
println!("Early hit! Stack: {}, Cache: {}", self.stack.len(), self.cache.len());
return None;
}
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);
fn pop_board(&mut self, item : SolverBoardItem) -> Option<SolverBoard> {
match item {
SolverBoardItem::Initial(board) => {
self.handle_initial(board)
}
}
if !new_board.valid {
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);
}
SolverBoardItem::Process(board, excludes, action) => {
self.handle_process(board, excludes, action)
}
return None
}
if self.insert_to_cache(new_board.arr) {
if !new_board.is_solved() {
let mut actions_copy = actions.to_vec();
for action in new_board.get_all_actions() {
actions_copy.push(action);
self.stack.push(SolverBoardItem::Recursive(actions_copy.to_vec()));
actions_copy.pop();
}
SolverBoardItem::Prepare(board, excludes, actions, index) => {
self.handle_prepare(board, excludes, actions, index)
}
return Some(new_board);
} else {
println!("Late hit! Stack: {}, Cache: {}", self.stack.len(), self.cache.len())
}
None
}
fn handle_initial(&mut self, board: SolverBoard) -> Option<SolverBoard> {
if board.valid {
return self.handle_board(Rc::new(board), Rc::new(HashSet::with_capacity(CELLS * VALUES)))
}
None
}
/**
* Check if we can find a board in the cache, where all actions in the
* vector have been applied.
* The preparation step is quite memory and time consuming.
* 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 {
for board in self.cache.iter() {
let applied = actions.iter()
.map(|a| a.get())
.all(|a| board[a.0.y][a.0.x] == a.1);
if applied {
return true
}
fn handle_prepare(&mut self, board_ref: Rc<SolverBoard>, excludes_ref: Rc<HashSet<Action>>, actions: Rc<Vec<Action>>, index : usize) -> Option<SolverBoard> {
let mut excludes_ref = excludes_ref; // re-label
let excludes = Rc::make_mut(&mut excludes_ref);
// extend the current exclude list by the exceeded actions in the list (before the own index)
actions.iter().rev().take(index)
.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()
.flatten()
.filter(|value| value.count_ones() != 1) {
*x = 0;
fn handle_board(&mut self, board: Rc<SolverBoard>, excludes: Rc<HashSet<Action>>)-> Option<SolverBoard> {
if !board.is_solved() {
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 {

Loading…
Cancel
Save