-
Notifications
You must be signed in to change notification settings - Fork 3
/
18_pattern_matching.go
123 lines (101 loc) · 2.41 KB
/
18_pattern_matching.go
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
package chapter16
import (
"strings"
)
// CheckPatternMatchesBruteForce checks if value matches pattern
func CheckPatternMatchesBruteForce(pattern, value string) bool {
if len(pattern) == 0 {
return len(value) == 0
}
size := len(value)
for mainSize := 0; mainSize < size; mainSize++ {
main := value[0:mainSize]
for altStart := mainSize; altStart <= size; altStart++ {
for altEnd := altStart; altEnd < size; altEnd++ {
alt := value[altStart:altEnd]
candidate := buildFromPatten(pattern, main, alt)
if candidate == value {
return true
}
}
}
}
return false
}
// CheckPatternMatchesOptimized checks if value matches pattern
func CheckPatternMatchesOptimized(pattern, value string) bool {
if len(pattern) == 0 {
return len(value) == 0
}
mainChar := int32(pattern[0])
altChar := 'a'
if mainChar == 'a' {
altChar = 'b'
}
size := len(value)
countOfMain := countOf(pattern, mainChar)
countOfAlt := len(pattern) - countOfMain
firstAlt := strings.Index(pattern, string(altChar))
maxMainSize := size / countOfMain
for mainSize := 0; mainSize <= maxMainSize; mainSize++ {
remainingLength := size - mainSize*countOfMain
if countOfAlt == 0 || remainingLength%countOfAlt == 0 {
altIndex := firstAlt * mainSize
altSize := 0
if countOfAlt != 0 {
altSize = remainingLength / countOfAlt
}
if matches(pattern, value, mainSize, altSize, altIndex) {
return true
}
}
}
return false
}
func matches(pattern string, value string, mainSize int, altSize int, firstAlt int) bool {
stringIndex := mainSize
for i := 1; i < len(pattern); i++ {
size := altSize
if pattern[0] == pattern[i] {
size = mainSize
}
offset := firstAlt
if pattern[i] == pattern[0] {
offset = 0
}
if !isEqual(value, offset, stringIndex, size) {
return false
}
stringIndex += size
}
return true
}
func isEqual(s1 string, offset1 int, offset2 int, size int) bool {
for i := 0; i < size; i++ {
if s1[offset1+i] != s1[offset2+i] {
return false
}
}
return true
}
func countOf(pattern string, char int32) int {
count := 0
for i := 0; i < len(pattern); i++ {
if int32(pattern[i]) == char {
count++
}
}
return count
}
func buildFromPatten(pattern, main, alt string) string {
sb := new(strings.Builder)
first := int32(pattern[0])
for _, char := range pattern {
if char == first {
sb.WriteString(main)
} else {
sb.WriteString(alt)
}
}
return sb.String()
}