AdventOfCode 2024 Day 25

Part One

with origin AS (
    SELECT row_number() over () as rn, line
    FROM lance_input
), empty AS (
    SELECT coalesce(lag(rn) over (order by rn), 0) as pre_rn, rn 
    FROM (
        SELECT rn
        FROM origin
        WHERE line is null

        UNION ALL

        SELECT max(rn) + 1 as rn
        FROM origin
    ) t
), matrix AS (
    SELECT empty.pre_rn as rn, origin.rn :: INTEGER as _row, x.idx :: INTEGER as _col, x.pos
    FROM origin, regexp_split_to_table(line, '') with ordinality as x(pos, idx), empty
    WHERE origin.rn between empty.pre_rn and empty.rn
), rows AS (
    SELECT rn, _row, string_agg(pos, '' order by _col) as line
    FROM matrix
    GROUP BY rn, _row
), cols AS (
    SELECT rn, _col, string_agg(pos, '' order by _row) as line
    FROM matrix
    GROUP BY rn, _col
), lock_key AS (
    SELECT rn, CASE WHEN line like '%.%' THEN 'key' ELSE 'lock' END as type
    FROM (
        SELECT rn, row_number() over (partition by rn order by _row) as seq, line
        FROM rows
    ) t
    WHERE t.seq = 1
)
SELECT COUNT(*)
FROM (
    SELECT b.rn as lock, d.rn as key, min(case when length(replace(a.line, '.', '')) + length(replace(c.line, '.', '')) - 2 <= 5 then 1 else 0 end) as result
    FROM cols a
    JOIN lock_key b 
    ON a.rn = b.rn
    AND b.type = 'lock'
    JOIN cols c
    ON a._col = c._col
    JOIN lock_key d
    ON c.rn = d.rn
    AND d.type = 'key'
    GROUP BY b.rn, d.rn
) t
WHERE result = 1

Part Two

发表评论