-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathproblem025.go
79 lines (71 loc) · 1.87 KB
/
problem025.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
package problem025
type state struct {
success bool
defaultShift *state
shiftMap map[rune]*state
}
func (currentState *state) defaultTo(nextState *state) *state {
currentState.defaultShift = nextState
return currentState
}
func (currentState *state) register(indicator rune, nextState *state) *state {
currentState.shiftMap[indicator] = nextState
return currentState
}
func (currentState *state) shift(indicator rune) *state {
if currentState.shiftMap[indicator] == nil {
return currentState.defaultShift
}
return currentState.shiftMap[indicator]
}
func newState(success bool) *state {
return &state{
success: success,
defaultShift: nil,
shiftMap: make(map[rune]*state),
}
}
func compileRegex(regex string) *state {
characters := []rune(regex)
doomedState, blessedState := newState(false), newState(true)
doomedState.defaultTo(doomedState)
blessedState.defaultTo(blessedState)
initialState := newState(false).defaultTo(doomedState)
cursor := initialState
for index, character := range characters {
if index == len(characters)-1 {
switch character {
case '.':
cursor.defaultTo(newState(true).defaultTo(doomedState))
case '*':
cursor.success = true
default:
cursor.defaultTo(doomedState)
cursor.register(character, newState(true).defaultTo(doomedState))
}
} else {
nextGoodState := newState(false)
if nextCharacter := characters[index+1]; nextCharacter == '*' {
nextGoodState = cursor
}
switch character {
case '.':
cursor.defaultTo(nextGoodState)
cursor = nextGoodState
case '*':
default:
cursor.register(character, nextGoodState)
cursor = nextGoodState
}
}
}
return initialState
}
func TestRegex(regex string, value string) bool {
fsm := compileRegex(regex)
characters := []rune(value)
for _, character := range characters {
fsm = fsm.shift(character)
}
return fsm.success
}