with recursive

raw as (
    select split(content, e'\n') as content from read_text('data/04.in')
),

lines as (
    select
        string_split(unnest(content), '') as line,
        generate_subscripts(content, 1) as row
    from raw
),

grid as (
    select
        unnest(line) as ch,
        generate_subscripts(line, 1) as col,
        row
    from lines
),

rolls as (
    select
        row,
        col
    from grid
    where ch = '@'
),

accessible as (
    select
        pos.row,
        pos.col
    from rolls pos, rolls adj
    where
        adj.row between pos.row - 1 and pos.row + 1
        and adj.col between pos.col - 1 and pos.col + 1
    group by pos.row, pos.col
    having count(*) < 5
),

remove (row, col, present, level) as (
    select
        row,
        col,
        true
    from rolls

    union all

    select
        pos.row,
        pos.col,
        pos.present and 4 < (
            select count(*)
            from remove adj
            where
                adj.present
                and adj.row between pos.row - 1 and pos.row + 1
                and adj.col between pos.col - 1 and pos.col + 1
        )
    from remove pos
    where
        exists (
            select
                pos.row,
                pos.col,
                count(*) as c
            from remove pos, remove adj
            where
                pos.present
                and adj.present
                and adj.row between pos.row - 1 and pos.row + 1
                and adj.col between pos.col - 1 and pos.col + 1
            group by pos.row, pos.col
            having c < 5
        )
),

removed as (
    select
        row,
        col
    from remove
    group by row, col
    having bool_or(not present)
),

part2 as (
    select (select count(*) from removed) as solution
)

select
    (select count(*) from accessible) as p1,
    (select count(*) from removed) as p2;
