Skip to content

Commit ce8ca0b

Browse files
committed
Add arrays and matrices modules
1 parent befb83f commit ce8ca0b

13 files changed

Lines changed: 301 additions & 0 deletions

File tree

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ toInt64(s, b=10): Parses string s in base b and returns in int64.
254254

255255
Built-in modules provide additional functions to make validation of input data easier.
256256

257+
##### arrays
258+
259+
Array validation functions.
260+
261+
```
262+
arrays.sorted(A): Returns true if the array is sorted in non-decreasing order.
263+
arrays.distinct(A): Returns true if all elements in the array are unique.
264+
arrays.permutation(N, A): Returns true if A is a permutation of 1..N.
265+
arrays.range(A, lo, hi): Returns true if all elements are in [lo, hi].
266+
```
267+
257268
##### math
258269

259270
Mathematical functions.
@@ -338,6 +349,14 @@ regexp.fullmatch(s, pattern): Returns true if the entire string s matches the pa
338349
regexp.count(s, pattern): Returns the number of non-overlapping matches of pattern in s.
339350
```
340351

352+
##### matrices
353+
354+
Matrix/grid validation functions.
355+
356+
```
357+
matrices.dimensions(G, R, C): Returns true if string array G has R elements, each of length C.
358+
```
359+
341360
## CLI
342361

343362
```

eval/arrays.go

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package eval
2+
3+
func init() {
4+
Functions["arrays.sorted"] = arraysSorted
5+
Functions["arrays.distinct"] = arraysDistinct
6+
Functions["arrays.permutation"] = arraysPermutation
7+
Functions["arrays.range"] = arraysRange
8+
}
9+
10+
// arraysSorted returns true if the array is sorted in non-decreasing order.
11+
func arraysSorted(args ...interface{}) (interface{}, error) {
12+
if len(args) != 1 {
13+
return nil, ErrInvalidArgument{}
14+
}
15+
switch a := args[0].(type) {
16+
case []int:
17+
for i := 1; i < len(a); i++ {
18+
if a[i] < a[i-1] {
19+
return false, nil
20+
}
21+
}
22+
return true, nil
23+
case []int64:
24+
for i := 1; i < len(a); i++ {
25+
if a[i] < a[i-1] {
26+
return false, nil
27+
}
28+
}
29+
return true, nil
30+
case []float32:
31+
for i := 1; i < len(a); i++ {
32+
if a[i] < a[i-1] {
33+
return false, nil
34+
}
35+
}
36+
return true, nil
37+
case []float64:
38+
for i := 1; i < len(a); i++ {
39+
if a[i] < a[i-1] {
40+
return false, nil
41+
}
42+
}
43+
return true, nil
44+
case []string:
45+
for i := 1; i < len(a); i++ {
46+
if a[i] < a[i-1] {
47+
return false, nil
48+
}
49+
}
50+
return true, nil
51+
}
52+
return nil, ErrInvalidArgument{}
53+
}
54+
55+
// arraysDistinct returns true if all elements in the array are unique.
56+
func arraysDistinct(args ...interface{}) (interface{}, error) {
57+
if len(args) != 1 {
58+
return nil, ErrInvalidArgument{}
59+
}
60+
switch a := args[0].(type) {
61+
case []int:
62+
seen := map[int]bool{}
63+
for _, v := range a {
64+
if seen[v] {
65+
return false, nil
66+
}
67+
seen[v] = true
68+
}
69+
return true, nil
70+
case []int64:
71+
seen := map[int64]bool{}
72+
for _, v := range a {
73+
if seen[v] {
74+
return false, nil
75+
}
76+
seen[v] = true
77+
}
78+
return true, nil
79+
case []float32:
80+
seen := map[float32]bool{}
81+
for _, v := range a {
82+
if seen[v] {
83+
return false, nil
84+
}
85+
seen[v] = true
86+
}
87+
return true, nil
88+
case []float64:
89+
seen := map[float64]bool{}
90+
for _, v := range a {
91+
if seen[v] {
92+
return false, nil
93+
}
94+
seen[v] = true
95+
}
96+
return true, nil
97+
case []string:
98+
seen := map[string]bool{}
99+
for _, v := range a {
100+
if seen[v] {
101+
return false, nil
102+
}
103+
seen[v] = true
104+
}
105+
return true, nil
106+
}
107+
return nil, ErrInvalidArgument{}
108+
}
109+
110+
// arraysPermutation returns true if the array is a permutation of 1..N.
111+
func arraysPermutation(args ...interface{}) (interface{}, error) {
112+
if len(args) != 2 {
113+
return nil, ErrInvalidArgument{}
114+
}
115+
n, ok := toInt(args[0])
116+
if !ok {
117+
return nil, ErrInvalidArgument{}
118+
}
119+
a, ok := args[1].([]int)
120+
if !ok {
121+
return nil, ErrInvalidArgument{}
122+
}
123+
if len(a) != n {
124+
return false, nil
125+
}
126+
seen := make([]bool, n+1)
127+
for _, v := range a {
128+
if v < 1 || v > n || seen[v] {
129+
return false, nil
130+
}
131+
seen[v] = true
132+
}
133+
return true, nil
134+
}
135+
136+
// arraysRange returns true if all elements are in [lo, hi].
137+
func arraysRange(args ...interface{}) (interface{}, error) {
138+
if len(args) != 3 {
139+
return nil, ErrInvalidArgument{}
140+
}
141+
switch a := args[0].(type) {
142+
case []int:
143+
lo, ok := toInt(args[1])
144+
if !ok {
145+
return nil, ErrInvalidArgument{}
146+
}
147+
hi, ok := toInt(args[2])
148+
if !ok {
149+
return nil, ErrInvalidArgument{}
150+
}
151+
for _, v := range a {
152+
if v < lo || v > hi {
153+
return false, nil
154+
}
155+
}
156+
return true, nil
157+
case []int64:
158+
lo, ok := toInt64(args[1])
159+
if !ok {
160+
return nil, ErrInvalidArgument{}
161+
}
162+
hi, ok := toInt64(args[2])
163+
if !ok {
164+
return nil, ErrInvalidArgument{}
165+
}
166+
for _, v := range a {
167+
if v < lo || v > hi {
168+
return false, nil
169+
}
170+
}
171+
return true, nil
172+
case []float32:
173+
lo, ok := toFloat32(args[1])
174+
if !ok {
175+
return nil, ErrInvalidArgument{}
176+
}
177+
hi, ok := toFloat32(args[2])
178+
if !ok {
179+
return nil, ErrInvalidArgument{}
180+
}
181+
for _, v := range a {
182+
if v < lo || v > hi {
183+
return false, nil
184+
}
185+
}
186+
return true, nil
187+
case []float64:
188+
lo, ok := toFloat64(args[1])
189+
if !ok {
190+
return nil, ErrInvalidArgument{}
191+
}
192+
hi, ok := toFloat64(args[2])
193+
if !ok {
194+
return nil, ErrInvalidArgument{}
195+
}
196+
for _, v := range a {
197+
if v < lo || v > hi {
198+
return false, nil
199+
}
200+
}
201+
return true, nil
202+
}
203+
return nil, ErrInvalidArgument{}
204+
}

eval/matrices.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package eval
2+
3+
func init() {
4+
Functions["matrices.dimensions"] = matricesDimensions
5+
}
6+
7+
// matricesDimensions returns true if the string array G has exactly R elements,
8+
// each of length C.
9+
func matricesDimensions(args ...interface{}) (interface{}, error) {
10+
if len(args) != 3 {
11+
return nil, ErrInvalidArgument{}
12+
}
13+
g, ok := args[0].([]string)
14+
if !ok {
15+
return nil, ErrInvalidArgument{}
16+
}
17+
r, ok := toInt(args[1])
18+
if !ok {
19+
return nil, ErrInvalidArgument{}
20+
}
21+
c, ok := toInt(args[2])
22+
if !ok {
23+
return nil, ErrInvalidArgument{}
24+
}
25+
if len(g) != r {
26+
return false, nil
27+
}
28+
for _, row := range g {
29+
if len(row) != c {
30+
return false, nil
31+
}
32+
}
33+
return true, nil
34+
}

testdata/arraysperm/inputs/01.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
3
2+
1
3+
2
4+
3

testdata/arraysperm/inputs/02.err

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
11:1~4:1: check error arrays.sorted(A) (A=[]int{3, 1, 2})

testdata/arraysperm/inputs/02.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
3
2+
3
3+
1
4+
2

testdata/arraysperm/inputs/03.err

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10:1~4:1: check error arrays.permutation(N... (N=3, A=[]int{1, 1, 3})

testdata/arraysperm/inputs/03.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
3
2+
1
3+
1
4+
3

testdata/arraysperm/scanspec

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var N int
2+
scan N
3+
check N >= 1, N <= 100
4+
eol
5+
var A [N]int
6+
for i := 0 ... N
7+
scan A[i]
8+
eol
9+
end
10+
check arrays.permutation(N, A)
11+
check arrays.sorted(A)
12+
eof

testdata/matricesdim/inputs/01.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2 3
2+
abc
3+
def

0 commit comments

Comments
 (0)