trackler 2.0.6.36 → 2.0.6.37

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,238 @@
1
+ // Package forth implements a tiny subset of the Forth language.
2
+ package forth
3
+
4
+ import (
5
+ "errors"
6
+ "strconv"
7
+ "strings"
8
+ "unicode"
9
+ )
10
+
11
+ type operatorFn func(stack *[]int) error
12
+
13
+ type operatorId byte
14
+
15
+ const (
16
+ addOp operatorId = iota
17
+ subOp
18
+ mulOp
19
+ divOp
20
+ dropOp
21
+ dupOp
22
+ swapOp
23
+ overOp
24
+ constOp
25
+ userDefOp
26
+ endDefOp
27
+ )
28
+
29
+ type operatorTyp struct {
30
+ fn operatorFn
31
+ id operatorId
32
+ }
33
+
34
+ func Forth(input []string) (result []int, err error) {
35
+ if len(input) == 0 {
36
+ return []int{}, nil
37
+ }
38
+
39
+ // Allocate an initially empty stack, with arbitrary starting capacity of 8.
40
+ stack := make([]int, 0, 8)
41
+ // Allocate a map for user defined words.
42
+ userDefs := make(map[string][]operatorTyp, 8)
43
+ for _, phrase := range input {
44
+ // Parse one phrase of input, building up an operator list.
45
+ opList, err := parse(phrase, userDefs)
46
+ if err != nil {
47
+ return nil, err
48
+ }
49
+ // Perform any operators from that phrase, updating stack.
50
+ for _, opr := range opList {
51
+ err = opr.fn(&stack)
52
+ if err != nil {
53
+ return nil, err
54
+ }
55
+ }
56
+ }
57
+
58
+ return stack[:len(stack)], nil
59
+ }
60
+
61
+ // parse given phrase, returning an operator list, and updating
62
+ // a userDefs map for any user definifion of words in phrase.
63
+ func parse(phrase string, userDefs map[string][]operatorTyp) (oplist []operatorTyp, err error) {
64
+ words := strings.FieldsFunc(phrase,
65
+ func(r rune) bool {
66
+ return unicode.IsSpace(r) || unicode.IsControl(r)
67
+ })
68
+
69
+ // t is token index into words[]
70
+ for t := 0; t < len(words); t++ {
71
+ w := strings.ToUpper(words[t])
72
+ // Handle reference to user defined word.
73
+ if udef, ok := userDefs[w]; ok {
74
+ oplist = append(oplist, udef...)
75
+ } else if op, ok := builtinOps[w]; ok {
76
+ if op.id == userDefOp {
77
+ // Handle user defined word definition.
78
+ t++
79
+ if t >= len(words)-2 {
80
+ return nil, emptyUserDefErr
81
+ }
82
+ userword := strings.ToUpper(words[t])
83
+ if _, numerr := strconv.Atoi(userword); numerr == nil {
84
+ return nil, invalidUserDefErr
85
+ }
86
+ t++
87
+ var userops []operatorTyp
88
+ for t < len(words) {
89
+ oneOp, err := parse(words[t], userDefs)
90
+ if err != nil {
91
+ return nil, err
92
+ }
93
+ if oneOp[0].id == endDefOp {
94
+ break
95
+ }
96
+ userops = append(userops, oneOp...)
97
+ t++
98
+ }
99
+ if len(userops) == 0 {
100
+ return nil, emptyUserDefErr
101
+ } else {
102
+ userDefs[userword] = userops
103
+ }
104
+ } else {
105
+ // Normal builtin operator.
106
+ oplist = append(oplist, op)
107
+ }
108
+ } else {
109
+ // Handle constant literal.
110
+ var x int
111
+ x, err = strconv.Atoi(w)
112
+ if err != nil {
113
+ return nil, err
114
+ }
115
+ oplist = append(oplist,
116
+ operatorTyp{id: constOp,
117
+ fn: func(stack *[]int) error {
118
+ push(stack, x)
119
+ return nil
120
+ },
121
+ })
122
+ }
123
+ }
124
+ return oplist, nil
125
+ }
126
+
127
+ // builtinOps are the pre-defined operators to support.
128
+ var builtinOps = map[string]operatorTyp{
129
+ "+": {add, addOp},
130
+ "-": {subtract, subOp},
131
+ "*": {multiply, mulOp},
132
+ "/": {divide, divOp},
133
+ "DUP": {dup, dropOp},
134
+ "DROP": {drop, dupOp},
135
+ "SWAP": {swap, swapOp},
136
+ "OVER": {over, overOp},
137
+ ":": {nil, userDefOp},
138
+ ";": {nil, endDefOp},
139
+ }
140
+
141
+ func pop(stack *[]int) (v int, err error) {
142
+ slen := len(*stack)
143
+ if slen >= 1 {
144
+ v = (*stack)[slen-1]
145
+ *stack = (*stack)[:slen-1]
146
+ return v, nil
147
+ }
148
+ return 0, notEnoughOperands
149
+ }
150
+
151
+ func pop2(stack *[]int) (v1, v2 int, err error) {
152
+ v1, err = pop(stack)
153
+ if err != nil {
154
+ return 0, 0, err
155
+ }
156
+ v2, err = pop(stack)
157
+ return v1, v2, err
158
+ }
159
+
160
+ func push(stack *[]int, v int) {
161
+ *stack = append(*stack, v)
162
+ }
163
+
164
+ func binaryOp(stack *[]int, op func(a, b int) int) error {
165
+ v1, v2, err := pop2(stack)
166
+ if err != nil {
167
+ return err
168
+ }
169
+ push(stack, op(v2, v1))
170
+ return nil
171
+ }
172
+
173
+ func add(stack *[]int) (err error) {
174
+ return binaryOp(stack, func(a, b int) int { return a + b })
175
+ }
176
+
177
+ func subtract(stack *[]int) (err error) {
178
+ return binaryOp(stack, func(a, b int) int { return a - b })
179
+ }
180
+
181
+ func multiply(stack *[]int) error {
182
+ return binaryOp(stack, func(a, b int) int { return a * b })
183
+ }
184
+
185
+ func divide(stack *[]int) error {
186
+ v1, v2, err := pop2(stack)
187
+ if err != nil {
188
+ return err
189
+ }
190
+ if v1 == 0 {
191
+ return divideByZero
192
+ }
193
+ push(stack, v2/v1)
194
+ return nil
195
+ }
196
+
197
+ func dup(stack *[]int) error {
198
+ v1, err := pop(stack)
199
+ if err != nil {
200
+ return err
201
+ }
202
+ push(stack, v1)
203
+ push(stack, v1)
204
+ return nil
205
+ }
206
+
207
+ func drop(stack *[]int) error {
208
+ _, err := pop(stack)
209
+ return err
210
+ }
211
+
212
+ func over(stack *[]int) error {
213
+ v1, v2, err := pop2(stack)
214
+ if err != nil {
215
+ return err
216
+ }
217
+ push(stack, v2)
218
+ push(stack, v1)
219
+ push(stack, v2)
220
+ return nil
221
+ }
222
+
223
+ func swap(stack *[]int) error {
224
+ v1, v2, err := pop2(stack)
225
+ if err != nil {
226
+ return err
227
+ }
228
+ push(stack, v1)
229
+ push(stack, v2)
230
+ return nil
231
+ }
232
+
233
+ var notEnoughOperands error = errors.New("not enough operands")
234
+ var divideByZero error = errors.New("attempt to divide by zero")
235
+ var emptyUserDefErr error = errors.New("empty user definition")
236
+ var invalidUserDefErr error = errors.New("invalid user def word")
237
+
238
+ const testVersion = 1
@@ -0,0 +1,99 @@
1
+ // +build ignore
2
+
3
+ package main
4
+
5
+ import (
6
+ "log"
7
+ "text/template"
8
+
9
+ "../../gen"
10
+ )
11
+
12
+ func main() {
13
+ t, err := template.New("").Parse(tmpl)
14
+ if err != nil {
15
+ log.Fatal(err)
16
+ }
17
+ var j js
18
+ if err := gen.Gen("forth", &j, t); err != nil {
19
+ log.Fatal(err)
20
+ }
21
+ }
22
+
23
+ // The JSON structure we expect to be able to unmarshal into
24
+ type js struct {
25
+ ParsingAndNumbers section `json:"parsing and numbers"`
26
+ Addition section
27
+ Subtraction section
28
+ Multiplication section
29
+ Division section
30
+ CombinedArithmetic section `json:"combined arithmetic"`
31
+ Dup section
32
+ Drop section
33
+ Swap section
34
+ Over section
35
+ UserDefinedWords section `json:"user-defined words"`
36
+ }
37
+
38
+ // A grouped section of test cases.
39
+ type section struct {
40
+ Cases []struct {
41
+ Description string
42
+ Input []string
43
+ Expected []int
44
+ }
45
+ }
46
+
47
+ // template applied to above data structure generates the Go test cases
48
+ var tmpl = `package forth
49
+
50
+ // Source: {{.Ori}}
51
+ {{if .Commit}}// Commit: {{.Commit}}
52
+ {{end}}
53
+
54
+ {{/* template for repeated caseSection */}}
55
+
56
+ {{define "caseSection"}} = []testCase{
57
+ {{range $y, $c := .}}{
58
+ {{printf "%q" $c.Description}},
59
+ {{printf "%#v" $c.Input}},
60
+ {{printf "%#v" $c.Expected}},
61
+ },
62
+ {{end}}}{{end}}
63
+
64
+ var parsingGroup{{template "caseSection" .J.ParsingAndNumbers.Cases}}
65
+
66
+ var additionGroup{{template "caseSection" .J.Addition.Cases}}
67
+
68
+ var subtractionGroup{{template "caseSection" .J.Subtraction.Cases}}
69
+
70
+ var multiplicationGroup{{template "caseSection" .J.Multiplication.Cases}}
71
+
72
+ var divisionGroup{{template "caseSection" .J.Division.Cases}}
73
+
74
+ var arithmeticGroup{{template "caseSection" .J.CombinedArithmetic.Cases}}
75
+
76
+ var dupGroup{{template "caseSection" .J.Dup.Cases}}
77
+
78
+ var dropGroup{{template "caseSection" .J.Drop.Cases}}
79
+
80
+ var swapGroup{{template "caseSection" .J.Swap.Cases}}
81
+
82
+ var overGroup{{template "caseSection" .J.Over.Cases}}
83
+
84
+ var userdefinedGroup{{template "caseSection" .J.UserDefinedWords.Cases}}
85
+
86
+ var testSections = []testcaseSection{
87
+ {"parsing", parsingGroup},
88
+ {"addition(+)", additionGroup},
89
+ {"subtraction(-)", subtractionGroup},
90
+ {"multiplication(*)", multiplicationGroup},
91
+ {"division(/)", divisionGroup},
92
+ {"arithmetic", arithmeticGroup},
93
+ {"dup", dupGroup},
94
+ {"drop", dropGroup},
95
+ {"swap", swapGroup},
96
+ {"over", overGroup},
97
+ {"user-defined", userdefinedGroup},
98
+ }
99
+ `
@@ -0,0 +1,64 @@
1
+ package forth
2
+
3
+ // API:
4
+ // func Forth([]string) ([]int, error)
5
+ //
6
+
7
+ import (
8
+ "reflect"
9
+ "testing"
10
+ )
11
+
12
+ const targetTestVersion = 1
13
+
14
+ type testCase struct {
15
+ description string
16
+ input []string
17
+ expected []int // nil slice indicates error expected.
18
+ }
19
+
20
+ type testcaseSection struct {
21
+ name string
22
+ tests []testCase
23
+ }
24
+
25
+ func TestTestVersion(t *testing.T) {
26
+ if testVersion != targetTestVersion {
27
+ t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
28
+ }
29
+ }
30
+
31
+ func runTestCases(t *testing.T, sectionName string, testCases []testCase) {
32
+ for _, tc := range testCases {
33
+ description := sectionName + " - " + tc.description
34
+ if v, err := Forth(tc.input); err == nil {
35
+ var _ error = err
36
+ if tc.expected == nil {
37
+ t.Fatalf("%s\n\tForth(%#v) expected an error, got %v",
38
+ description, tc.input, v)
39
+ } else if !reflect.DeepEqual(v, tc.expected) {
40
+ t.Fatalf("%s\n\tForth(%#v) expected %v, got %v",
41
+ description, tc.input, tc.expected, v)
42
+ }
43
+ } else if tc.expected != nil {
44
+ t.Fatalf("%s\n\tForth(%#v) expected %v, got an error: %q",
45
+ description, tc.input, tc.expected, err)
46
+ }
47
+ }
48
+ }
49
+
50
+ func TestForth(t *testing.T) {
51
+ for _, testSection := range testSections {
52
+ runTestCases(t, testSection.name, testSection.tests)
53
+ }
54
+ }
55
+
56
+ func BenchmarkForth(b *testing.B) {
57
+ for i := 0; i < b.N; i++ {
58
+ for _, testSection := range testSections {
59
+ for _, test := range testSection.tests {
60
+ Forth(test.input)
61
+ }
62
+ }
63
+ }
64
+ }
@@ -7,44 +7,38 @@ public class PhoneNumber {
7
7
  }
8
8
 
9
9
  private String extractDigits(String dirtyNumber) {
10
- return dirtyNumber.replaceAll("[^\\d]", "");
10
+ StringBuilder stringBuilder = new StringBuilder();
11
+ for (char c : dirtyNumber.toCharArray()) {
12
+ if (c == ' ' || c == '.' || c == '(' || c == ')' || c == '-') {
13
+ // Remove spaces, dots, parentheses and hyphens
14
+ continue;
15
+ }
16
+ if (!Character.isDigit(c)) {
17
+ throw new IllegalArgumentException("Illegal character in phone number. "
18
+ + "Only digits, spaces, parentheses, hyphens or dots accepted.");
19
+ }
20
+ stringBuilder.append(c);
21
+ }
22
+ return stringBuilder.toString();
11
23
  }
12
24
 
13
25
  private String normalize(String number) {
14
- if(number.length() > 11 || number.length() < 10){
26
+ if (number.length() > 11 || number.length() < 10) {
15
27
  throw new IllegalArgumentException("Number must be 10 or 11 digits");
16
28
  }
17
29
 
18
- if(number.length() == 11){
19
- if(number.startsWith("1")){
30
+ if (number.length() == 11) {
31
+ if (number.startsWith("1")) {
20
32
  number = number.substring(1, number.length());
21
- }
22
- else{
33
+ } else {
23
34
  throw new IllegalArgumentException("Can only have 11 digits if number starts with '1'");
24
35
  }
25
- }
26
-
36
+ }
37
+
27
38
  return number;
28
39
  }
29
40
 
30
41
  public String getNumber() {
31
42
  return number;
32
43
  }
33
-
34
- public String getAreaCode() {
35
- return number.substring(0, 3);
36
- }
37
-
38
- public String getExchangeCode() {
39
- return number.substring(3, 6);
40
- }
41
-
42
- public String getSubscriberNumber() {
43
- return number.substring(6, 10);
44
- }
45
-
46
- public String pretty() {
47
- return "(" + getAreaCode() + ") " + getExchangeCode() + "-" + getSubscriberNumber();
48
- }
49
-
50
44
  }