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
|
rules = {}
function char(c)
return function(s, i)
if s:sub(i,i) == c then
return i+1
else
return nil
end
end
end
function pick(f, g)
return function(s, i)
j = f(s, i)
if j then
return j
else
return g(s, i)
end
end
end
function chain2(fs)
return function (s, i)
for j = 1, #fs do
i = rules[fs[j]](s, i)
if not i then
return nil
end
end
return i
end
end
function chain(f, g)
return function (s, i)
j = rules[f](s, i)
if j then
return rules[g](s, j)
else
return nil
end
end
end
function make_chain(rule)
space_index = rule:find(' ')
if space_index then
return chain2({rule:sub(1, space_index - 1), rule:sub(space_index + 1, -1)})
else
return function (s, i)
return rules[rule](s, i)
end
end
end
function make_function(rule)
if rule:sub(1, 1) == '"' then
return char(rule:sub(2, 2))
end
pipe_index = rule:find('|')
if pipe_index then
left = make_chain(rule:sub(1, pipe_index - 2))
right = make_chain(rule:sub(pipe_index + 2, #rule))
return pick(left, right)
else
return make_chain(rule)
end
end
function parse_rule(rule)
colon_index = rule:find(':')
if colon_index then
rule_number = rule:sub(1, colon_index - 1)
rhs = rule:sub(colon_index + 2, -1)
rules[rule_number] = make_function(rhs)
return true
else
return false
end
end
lines = io.lines('input.txt')
for line in lines do
if not parse_rule(line) then
break
end
end
correct = 0
for line in lines do
j = rules['0'](line, 1)
if j == #line + 1 then
correct = correct + 1
end
end
print(correct)
|