m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/19/a.lua
blob: 0f3164c5f7692eb8eba0a8d1465c84c4ef902655 (plain)
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)