create or replace table day04_data as
select
  row_number() over() as row,
  column0
from
  read_csv(
    'inputs/04/input.txt',
    header = false
  );
create or replace table day04_test as
select
  row_number() over() as row,
  column0
from
  read_csv(
    'inputs/04/test.txt',
    header = false
  );

create or replace table day04_clean as
select
  row,
  idx + 1 as col
from
  day04_data
cross join unnest(range(length(column0))) as t(idx)
where substr(column0, idx + 1, 1) = '@';

create or replace table day04_neighbors as
select
  c.row * 1000 + c.col as node,
  a.row * 1000 + a.col as neighbor
from day04_clean as c
left join day04_clean as a
  on a.row between (c.row - 1) and (c.row + 1)
  and a.col between (c.col - 1) and (c.col + 1)
;

with neighbors_count as (
  select node, count(1) as nb_neighbors
  from day04_neighbors
  group by node
)
select count_if(nb_neighbors <= 4) as part1
from neighbors_count
;

with recursive seq as (
  with agg as (
    select
        node,
        count(1) neighbors
    from day04_neighbors
    group by node
    having neighbors > 4
  )
  select
    node,
    s.neighbor,
    (select count(distinct node) from agg) as remaining,
    0 as step
  from day04_neighbors as s
  inner join agg as a1 using (node)
  inner join agg as a2 on a2.node = s.neighbor

  union all

  (
    with agg2 as (
      select node, step, count(distinct neighbor) as neighbors
      from seq
      group by node, step
      having step = (select max(step) from seq)
      and neighbors > 4
    )
    select
      s.node,
      s.neighbor,
      (select count(distinct node) from agg2) as remaining,
      s.step + 1 as step 
    from seq s
    inner join agg2 as a1 using(node)
    inner join agg2 as a2 on a2.node = s.neighbor
    where (
      select count(distinct node) from agg2) < (select min(remaining) from seq
    )
  )
)
select (select count(distinct node) from day04_neighbors) - (select min(remaining) from seq) as part2;

