module day11

function readfile()
    open("$(@__DIR__)/../../input") do f
        read(f, String)
    end
end

function parse_map(m)
    chars = [collect(l) for l in split(strip(m), "\n")]
    hcat(chars...)
end

EMPTY = 'L'
OCCUPIED = '#'
FLOOR = '.'

function count_occupied(m, x, y, neighbours_only = true)
    if m[x, y] == FLOOR
        return 0
    end

    ğ��· = [(x, y) for x = -1:1, y = -1:1]

    occupied = 0

    for (ğ�‘‘x, ğ�‘‘y) in ğ��·
        xáµ¢, yáµ¢ = x, y
        xáµ¢ = xáµ¢ + ğ�‘‘x
        yáµ¢ = yáµ¢ + ğ�‘‘y

        distance = 1

        while 1 <= xáµ¢ <= size(m, 1) &&
                  1 <= yáµ¢ <= size(m, 2) &&
                  (xáµ¢, yáµ¢) != (x, y) &&
                  (neighbours_only && distance == 1 || !neighbours_only)
            s = m[xáµ¢, yáµ¢]
            if s == OCCUPIED
                occupied += 1
                break
            elseif s == EMPTY
                break
            end

            xáµ¢ = xáµ¢ + ğ�‘‘x
            yáµ¢ = yáµ¢ + ğ�‘‘y

            distance += 1
        end
    end
    occupied
end

function evolve(m, limit, count_occupied)
    rv = copy(m)
    for x = 1:size(m, 1), y = 1:size(m, 2)
        if m[x, y] == FLOOR
            continue
        end

        oc = count_occupied(m, x, y)
        if oc == 0
            rv[x, y] = OCCUPIED
        elseif oc >= limit
            rv[x, y] = EMPTY
        end
    end
    rv
end

function evolve_till_stable(m, limit, count_occupied)
    m1 = evolve(m, limit, count_occupied)
    while m1 != m
        m = m1
        m1 = evolve(m, limit, count_occupied)
    end
    m1
end


function run()
    seating = readfile() |> parse_map

    result = count(==(OCCUPIED), evolve_till_stable(seating, 4, count_occupied))
    println("The number of seats ending up occupied is $(result)")
    result = count(
        ==(OCCUPIED),
        evolve_till_stable(seating, 5, (m, x, y) -> count_occupied(m, x, y, false)),
    )
    println("The number of seats ending up occupied with the new visibility method is $(result)")
end
end
