Skip to content

Commit 93d7eca

Browse files
committedSep 19, 2019
search code
1 parent 65aa439 commit 93d7eca

File tree

5 files changed

+202
-25
lines changed

5 files changed

+202
-25
lines changed
 

‎rule/rule.go

+17-17
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ package rule
22

33
import "github.com/epsalon/decryptid/board"
44

5-
type BoardRule []bool
6-
type Rule func (*board.Board) BoardRule
5+
type BoardRule struct {
6+
RuleSpec
7+
arr []bool
8+
}
9+
10+
type Rule func (*board.Board) []bool
711

812
type hexRule func (board.Hex) bool
913

@@ -23,16 +27,6 @@ type coord = struct {
2327
Y int
2428
}
2529

26-
// -A-
27-
// 3 3 3 3
28-
// -F- 3 2 2 2 3 -B-
29-
// 3 2 1 1 2 3 1, 7, 19, 37
30-
// 3 2 1 0 1 2 3
31-
// 3 2 1 1 2 3 -C-
32-
// -E- 3 2 2 2 3
33-
// 3 3 3 3
34-
// -D-
35-
3630
func max(a int, b int) int {
3731
if a > b {
3832
return a
@@ -69,7 +63,7 @@ func rCoord (c coord) int {
6963
}
7064

7165
func distanceRule(hr hexRule, d int) Rule {
72-
return func (b *board.Board) BoardRule {
66+
return func (b *board.Board) []bool {
7367
out := make([]bool, 12 * 9)
7468
for y, row := range *b {
7569
for x, hex := range row {
@@ -85,7 +79,7 @@ func distanceRule(hr hexRule, d int) Rule {
8579
}
8680

8781
func negate(r Rule) Rule {
88-
return func (b *board.Board) BoardRule {
82+
return func (b *board.Board) []bool {
8983
br := r(b)
9084
for i, v := range br {
9185
br[i] = !v
@@ -94,16 +88,18 @@ func negate(r Rule) Rule {
9488
}
9589
}
9690

97-
func FromSpec(rs RuleSpec) Rule {
91+
func (rs RuleSpec) OnBoard(b *board.Board) BoardRule {
92+
br := BoardRule{RuleSpec:rs}
9893
r := distanceRule(rs.hr, rs.d)
9994
if rs.neg {
10095
r = negate(r)
10196
}
102-
return r
97+
br.arr = r(b)
98+
return br
10399
}
104100

105101
func Apply(br BoardRule, b *board.Board, p int) {
106-
for i, v := range br {
102+
for i, v := range br.arr {
107103
h := &b[i / 12][i % 12]
108104
if v {
109105
h.Discs = h.Discs | (1 << (p-1))
@@ -115,4 +111,8 @@ func Apply(br BoardRule, b *board.Board, p int) {
115111
h.Cube = p
116112
}
117113
}
114+
}
115+
116+
func (b BoardRule) ToBoolSlice() []bool {
117+
return b.arr
118118
}

‎rules_main.go

+23-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package main
22

33
import "fmt"
4-
import "github.com/epsalon/decryptid/rule"
54
import "github.com/epsalon/decryptid/board"
5+
import "github.com/epsalon/decryptid/rule"
6+
import "github.com/epsalon/decryptid/search"
67

78
var testSpec = board.BoardSpec {
89
Tiles: [3][2]board.TileId {
@@ -23,17 +24,31 @@ var testSpec = board.BoardSpec {
2324
func main () {
2425
b := board.MakeBoard(testSpec)
2526
rs := rule.AllRules()
27+
brs := make([]search.Rule, 0, len(rs))
2628
fmt.Println(rs)
2729
for _, r := range rs {
2830
fmt.Println(r)
29-
br := rule.FromSpec(r)(&b)
31+
br := r.OnBoard(&b)
32+
brs = append(brs, search.Rule(br))
3033
rule.Apply(br, &b, 1)
3134
fmt.Println(b)
3235
}
33-
rule.Apply(rule.FromSpec(rule.D1Landscape(board.Water))(&b), &b, 1)
34-
rule.Apply(rule.FromSpec(rule.OnLandscapes(board.Forest, board.Mountain))(&b), &b, 2)
35-
rule.Apply(rule.FromSpec(rule.D1Landscape(board.Swamp))(&b), &b, 3)
36-
rule.Apply(rule.FromSpec(rule.OnLandscapes(board.Forest, board.Swamp))(&b), &b, 4)
37-
rule.Apply(rule.FromSpec(rule.D3Color(board.Blue))(&b), &b, 5)
38-
fmt.Println(b)
36+
srs := search.RuleSet(brs)
37+
fmt.Println(srs)
38+
results := search.FindRuleSets(srs)
39+
for _, r := range results {
40+
b := board.MakeBoard(testSpec)
41+
fmt.Printf("(%v) %v\n", len(r), r)
42+
for p, rl := range r {
43+
rule.Apply(rl.(rule.BoardRule), &b, p+1)
44+
}
45+
fmt.Println(b)
46+
}
47+
48+
//rule.Apply(rule.FromSpec(rule.D1Landscape(board.Water))(&b), &b, 1)
49+
//rule.Apply(rule.FromSpec(rule.OnLandscapes(board.Forest, board.Mountain))(&b), &b, 2)
50+
//rule.Apply(rule.FromSpec(rule.D1Landscape(board.Swamp))(&b), &b, 3)
51+
//rule.Apply(rule.FromSpec(rule.OnLandscapes(board.Forest, board.Swamp))(&b), &b, 4)
52+
//rule.Apply(rule.FromSpec(rule.D3Color(board.Blue))(&b), &b, 5)
53+
//fmt.Println(b)
3954
}

‎search/search.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package search
2+
3+
import "fmt"
4+
import "log"
5+
import "github.com/epsalon/decryptid/uint128"
6+
7+
type Rule interface {
8+
ToBoolSlice() []bool
9+
fmt.Stringer
10+
}
11+
12+
type RuleSet []Rule
13+
14+
type rule = uint128.Uint128
15+
type ruleSet = []uint128.Uint128
16+
17+
func FindRuleSets (xrs RuleSet) []RuleSet {
18+
rs := make(ruleSet, 0, len(xrs))
19+
for _, r := range xrs {
20+
bs := r.ToBoolSlice()
21+
u := uint128.FromBoolSlice(bs)
22+
log.Printf("rule = %v slice = %v", bs, u)
23+
rs = append(rs, u)
24+
}
25+
idxSet, posLoc := findRulesets(rs)
26+
log.Printf("Possible locations = %v\n", posLoc)
27+
out := make([]RuleSet, 0, len(idxSet))
28+
for _, s := range idxSet {
29+
ors := make([]Rule, 0, len(s))
30+
for _, r := range s {
31+
ors = append(ors, xrs[r])
32+
}
33+
out = append(out, RuleSet(ors))
34+
}
35+
return out
36+
}
37+
38+
func consistent(rs ruleSet, is []int) bool {
39+
for i, _ := range is {
40+
m := uint128.Ones(9 * 12)
41+
for j, r := range is {
42+
if i != j {
43+
m = m.And(rs[r])
44+
}
45+
}
46+
if m.OnesCount() == 1 {
47+
return false
48+
}
49+
}
50+
return true
51+
}
52+
53+
func findRulesets (rs ruleSet) ([][]int, rule) {
54+
log.Printf("ruleset = %v", rs)
55+
out := [][]int{}
56+
cur := []int{}
57+
posloc := uint128.Uint128{}
58+
mask := uint128.Ones(9 * 12)
59+
masks := []rule{}
60+
for i := 0; ; {
61+
// log.Printf("External loop i=%v cur=%v mask=%v masks=%v", i, cur, mask, masks)
62+
for ; i < len(rs); i++ {
63+
cur = append(cur, i)
64+
masks = append(masks, mask)
65+
mask = mask.And(rs[i])
66+
// log.Printf(" Inner loop i=%v cur=%v mask=%v masks=%v", i, cur, mask, masks)
67+
if (mask.IsZero()) {
68+
// Dead end
69+
cur = cur[:len(cur) - 1]
70+
mask, masks = masks[len(masks) - 1], masks[:len(masks) - 1]
71+
// log.Printf(" Zero mask pop!")
72+
continue
73+
}
74+
if (mask.OnesCount() == 1) {
75+
// Found possible solution!
76+
if consistent(rs, cur) {
77+
// log.Printf(" Found solution: %v", cur)
78+
posloc = posloc.Or(mask)
79+
out = append(out, append([]int(nil), cur...))
80+
}
81+
cur = cur[:len(cur) - 1]
82+
mask, masks = masks[len(masks) - 1], masks[:len(masks) - 1]
83+
continue
84+
}
85+
if len(cur) > 4 {
86+
cur = cur[:len(cur) - 1]
87+
mask, masks = masks[len(masks) - 1], masks[:len(masks) - 1]
88+
continue
89+
}
90+
// Recurse deeper
91+
}
92+
if len(cur) == 0 {
93+
break
94+
}
95+
i, cur = cur[len(cur) - 1] + 1, cur[:len(cur) - 1]
96+
mask, masks = masks[len(masks) - 1], masks[:len(masks) - 1]
97+
}
98+
return out, posloc
99+
}

‎search/search_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package search
2+
3+
import "log"
4+
import "reflect"
5+
import "testing"
6+
import "github.com/epsalon/decryptid/uint128"
7+
8+
var consitencyTests = []struct {
9+
idx []int
10+
result bool
11+
}{
12+
{[]int{0,1,2}, true},
13+
{[]int{4,0,1,2}, false},
14+
{[]int{4,2}, true},
15+
{[]int{4,3}, true},
16+
{[]int{1,4,2}, false},
17+
{[]int{1,4,3}, false},
18+
}
19+
20+
func getRuleSet() ruleSet {
21+
var testSet = []uint64{0xf0, 0x33, 0x55, 0x0f, 0x81}
22+
us := make([]rule, 0, len(testSet))
23+
for _, tr := range(testSet) {
24+
us = append(us, uint128.Uint128{Lo:tr})
25+
}
26+
log.Printf("us = %v", us)
27+
return us
28+
}
29+
30+
func TestConsistent (t *testing.T) {
31+
us := getRuleSet()
32+
for _, tc := range(consitencyTests) {
33+
r := consistent(us, tc.idx)
34+
if r != tc.result {
35+
t.Errorf("consistent(%v). Want: %v, Got: %v", tc.idx, tc.result, r)
36+
}
37+
}
38+
}
39+
40+
func TestFindRulesets (t *testing.T) {
41+
us := findRulesets(getRuleSet())
42+
expected := [][]int{{0,1,2},{0,4},{1,2,3},{1,4},{2,4},{3,4}}
43+
if !reflect.DeepEqual(us, expected) {
44+
t.Errorf("Rulesets: Want: %v, Got: %v", expected, us)
45+
}
46+
}

‎uint128/uint128.go

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package uint128
22

3+
import "fmt"
34
import "math/bits"
45

56
type Uint128 struct {
@@ -18,6 +19,10 @@ func (u Uint128) And(o Uint128) Uint128 {
1819
return Uint128{u.Hi & o.Hi, u.Lo & o.Lo}
1920
}
2021

22+
func (u Uint128) Or(o Uint128) Uint128 {
23+
return Uint128{u.Hi | o.Hi, u.Lo | o.Lo}
24+
}
25+
2126
func (u Uint128) Not() Uint128 {
2227
return Uint128{^u.Hi, ^u.Lo}
2328
}
@@ -30,6 +35,14 @@ func (u Uint128) Equals(o Uint128) bool {
3035
return u.Hi == o.Hi && u.Lo == o.Lo
3136
}
3237

38+
func Ones(l int) Uint128 {
39+
if l < 64 {
40+
return Uint128{0, (uint64(1) << l) - 1}
41+
} else {
42+
return Uint128{(uint64(1) << (l-64)) - 1, ^uint64(0)}
43+
}
44+
}
45+
3346
func FromBoolSlice(s []bool) Uint128 {
3447
var sh, hi, lo uint64
3548
sh = 1
@@ -67,4 +80,8 @@ func (u Uint128) ToBoolSlice(l int) []bool {
6780
sh = sh << 1
6881
}
6982
return s
83+
}
84+
85+
func (u Uint128) String() string {
86+
return fmt.Sprintf("%016x%016x", u.Hi, u.Lo)
7087
}

0 commit comments

Comments
 (0)
Please sign in to comment.