-
Notifications
You must be signed in to change notification settings - Fork 0
/
19.awk
123 lines (98 loc) · 1.73 KB
/
19.awk
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
BEGIN {
FS = "[{:=,}]"
}
parsing_parts {
sum = 0
delete part
for (i = 2; i < NF; i += 2)
sum += part[$i] = $(i+1)
if (is_accepted(part))
sum1 += sum
next
}
!NF {
parsing_parts = 1
next
}
{
j = 1
for (i = 2; i < NF-1; i += 2) {
op[$1, j] = substr($i, 2, 1)
lhs[$1, j] = substr($i, 1, 1)
rhs[$1, j] = substr($i, 3)
rule[$1, j] = $(i+1)
j++
}
rule[$1, j] = $(NF-1)
nrules[$1] = j
}
END {
FS = " "
split("x m a s", tmp)
for (i in tmp)
cat[tmp[i]] = i
range[1] = "in,1 1 1 1,4000 4000 4000 4000"
nranges = 1
for (i = 1; i <= nranges; i++) {
split(range[i], p, ",")
wf = p[1]
if (wf == "R")
continue
split(p[2], min)
split(p[3], max)
if (wf == "A") {
sum2 += num_combs()
continue
}
for (j = 1; j < nrules[wf]; j++) {
k = wf SUBSEP j
if (op[k] == ">")
split_range(k, min, max, 1)
else
split_range(k, max, min, -1)
}
enqueue(rule[wf, j])
delete ranges[i]
}
print sum1
print sum2
}
function split_range(rulei, lim1, lim2, dir, c, tmp) {
c = cat[lhs[rulei]]
tmp = lim1[c]
lim1[c] = rhs[rulei]+dir
enqueue(rule[rulei])
lim1[c] = tmp
lim2[c] = rhs[rulei]
}
function is_accepted(part, wf, i, l, r, o) {
for (wf = "in"; wf !~ /A|R/; wf = rule[wf, i])
for (i = 1; i < nrules[wf]; i++) {
l = part[lhs[wf, i]]
r = rhs[wf, i]+0
o = op[wf, i]
if ((o == "<" && l < r) || (o == ">" && l > r))
break
}
return (wf == "A")
}
function num_combs( ret, i) {
ret = 1
for (i in min) {
if (min[i] > max[i])
return 0
ret *= max[i]-min[i]+1
}
return ret
}
function join(a, ret, i) {
for (i = 1; i <= length(a); i++) {
ret = ret sep a[i]
sep = " "
}
return ret
}
function enqueue(wf) {
nranges++
range[nranges] = wf "," join(min) "," join(max)
}