DEV Community

Discussion on: AoC Day 24: Immune System Simulator 20XX

Collapse
 
mustafahaddara profile image
Mustafa Haddara • Edited

Yeah, a parser generator was definitely the right way to do it. I was stubborn and stuck to the naive way of doing it, which only worked because I noticed the only variable part was the special weaknesses/immunities bit. So I yanked that out:

specials = r"\(.*\)"
m = match(specials, line)

if m == nothing
    specials_chunk = ""
    simplified = line
else
    specials_chunk = m.match[2:end-1]  # remove ()
    simplified = line[1:m.offset-1] * line[m.offset+1+length(m.match):end]
end

tokens = split(simplified, " ")

and then processed the simple tokens the simple way:

units = parse(Int, tokens[1])  # this is the easy one
health = parse(Int, tokens[5])
damage = parse(Int, tokens[13])
attack_type = tokens[14]
initiative = parse(Int, tokens[end])

and then processed the special tokens separately:

if specials_chunk != ""
    chunks = split(specials_chunk, "; ")
    for c in chunks
        bits = split(c, " ")
        for i in 3:length(bits)
            if endswith(bits[i], ',')
                item = bits[i][1:end-1]
            else
                item = bits[i]
            end
            if bits[1] == "weak"
                push!(weakness, item)
            else
                push!(immunities, item)
            end
        end
    end
end

by the end I kinda ran out of good variable names was just using bits as a name, heh.

And then at the end, I could just return a new Group object...the first arg is the team, and the second arg is the number, more on that below

return Group("",0, units, health, damage, attack_type, initiative, weakness, immunities)

Assigning teams was done in a parent method that knew about the entire input:

function parse_input(input)
    groups::Array{Group} = []
    team = "Immune System"
    number = 1
    for line in input
        if line == ""
            continue
        end
        if line == "Immune System:"
            continue
        end
        if line == "Infection:"
            team = "Infection"
            number = 1
            continue
        end
        g = parse_group(line)
        g.number = number
        g.team = team
        push!(groups, g)
        number += 1
    end
    return groups
end

I also assigned a group number so I could get similar output to the sample output.