-
Notifications
You must be signed in to change notification settings - Fork 0
/
puzzle.c
144 lines (122 loc) · 2.58 KB
/
puzzle.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "puzzle.h"
// 0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10!
int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800};
int
idx2h(int idx)
{
return idx % HSIZE;
}
int
idx2v(int idx)
{
return idx / HSIZE;
}
int
hv2idx(int h, int v)
{
return h + v*HSIZE;
}
void
perfhash(int n, int* buf)
{
/*
* calculate permunation from hash
* http://www.ic-net.or.jp/home/takaken/nt/slide/hash.html
*/
int i;
int nth;
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
int availables[10] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int found;
for(i = 0; i < SIZE; i++){
nth = n / fact[8 - i];
found = -1;
while(nth > -1){
found++;
if(availables[found]){
nth--;
}
}
availables[found] = 0;
buf[i] = found - 1;
n = n % fact[8-i];
}
}
bool
rotate(int idx, int* buf)
{
int i;
if(idx == -1){
for(i=0;i<SIZE;i++){
buf[i] = 0;
}
return true;
}
if(buf[idx] >= 3){
return false;
}
buf[idx] ++;
return true;
}
int
get_pattern(int idx, TTile* tiles, TPlacement* p, int direction)
{
return (tiles[p->fPermutation[idx]]).fPattern[direction];
}
bool
ok_up(int idx, TTile* tiles, TPlacement* p)
{
int h, v;
int n;
if(idx < HSIZE)
return true;
h = idx2h(idx);
v = idx2v(idx);
n = hv2idx(h - 1, v);
return ((get_pattern(n, tiles, p, 2) ^ get_pattern(idx, tiles, p, 0) ^ MATCHMASK) & MATCHMASK);
}
bool
ok_left(int idx, TTile* tiles, TPlacement* p)
{
int h, v;
int n;
h = idx2h(idx);
if (h == 0)
return true;
v = idx2v(idx);
n = hv2idx(h - 1, v);
return ((get_pattern(n, tiles, p, 3) ^ get_pattern(idx, tiles, p, 1) ^ MATCHMASK) & MATCHMASK);
}
int
failed_at(TTile* tiles, TPlacement* p)
{
int idx;
for (idx=0; idx < SIZE; idx++){
//testing left to right, top to bottom.
if(!ok_up(idx, tiles, p) ||
!ok_left(idx, tiles, p)){
return idx;//failed at.
}
}
return -1; //success. valid way to place tiles.
}
bool
solve(TTile* tiles, TPlacement* p, int* start, int end)
{
int i;
int at;
for(i = *start; i < end; i++){
perfhash(i, p->fPermutation);
at = -1;
while(rotate(at, p->fRotation)){
at = failed_at(tiles, p);
if (at < 0){
*start = i;
return true;
}
}
// may miss solution after solution.
}
*start = i;
return false;
}