diff --git a/src/day9/puzzle1.typ b/src/day9/puzzle1.typ index 4c0a000..9f7ab9d 100644 --- a/src/day9/puzzle1.typ +++ b/src/day9/puzzle1.typ @@ -1,5 +1,28 @@ #import "/src/utils.typ": * +#let parse-input(input) = { + let blocks = () + let holes = () + + let block-i = 0 + let is-block = true + let pos = 0 + for c in input { + let block = (pos, int(c)) + if is-block { + block.push(block-i) + block-i += 1 + blocks.push(block) + } else { + holes.push(block) + } + pos += int(c) + is-block = not is-block + } + + return (blocks, holes) +} + #let compute-checksum(blocks) = { let total = 0 for (i0, l, id) in blocks { @@ -20,24 +43,7 @@ } #let solve(input) = { - let blocks = () - let holes = () - - let block-i = 0 - let is-block = true - let pos = 0 - for c in input { - let block = (pos, int(c)) - if is-block { - block.push(block-i) - block-i += 1 - blocks.push(block) - } else { - holes.push(block) - } - pos += int(c) - is-block = not is-block - } + let (blocks, holes) = parse-input(input) for (hi, hl) in holes { while hl > 0 { @@ -66,6 +72,70 @@ return compute-checksum(blocks) } +#let visualize(input) = { + let (blocks, holes) = parse-input(input) + let max-id = blocks.last().last() + + let col-gradient = gradient.linear(red, orange, yellow, green, aqua, blue, purple) + + let show-fs(size, blocks) = { + let cells = () + for (bi, bl, bid) in blocks { + cells.push( + grid.cell( + x: bi, + colspan: bl, + fill: col-gradient.sample(bid * 100% / max-id), + str(bid) + ) + ) + } + grid( + columns: (1fr,) * size, + align: center + horizon, + stroke: black, + inset: 0.3em, + ..cells + ) + } + + let last-block = blocks.last() + let last-holes = holes.last() + let show-fs = show-fs.with( + calc.max( + last-block.first() + last-block.at(1), + last-holes.first() + last-holes.last() + ) + ) + let steps = () + steps.push(show-fs(blocks)) + + for (hi, hl) in holes { + while hl > 0 { + if blocks.last().first() < hi + hl { + break + } + let (bi, bl, bid) = blocks.pop() + let len = calc.min(hl, bl) + blocks.insert(0, (hi, len, bid)) + if len < bl { + blocks = insert(blocks, (bi, bl - len, bid)) + } + hl -= len + hi += len + } + if hl > 0 { + break + } + steps.push(show-fs(blocks)) + } + + stack( + spacing: 0.5em, + ..steps + ) +} + #show-puzzle( 9, 1, solve, @@ -73,7 +143,8 @@ "1": 60, "2": 1928 ), - only-example: true + only-example: true, + visualize: visualize ) // Too long to recompile everytime diff --git a/src/day9/puzzle2.typ b/src/day9/puzzle2.typ index 75198ee..2048d90 100644 --- a/src/day9/puzzle2.typ +++ b/src/day9/puzzle2.typ @@ -27,13 +27,12 @@ let is-block = true let pos = 0 for c in input { - let block = (pos, int(c)) + let size = int(c) if is-block { - block.push(block-i) + blocks.push((pos, size, block-i)) block-i += 1 - blocks.push(block) } else { - holes.push(block) + holes.push((pos, size)) } pos += int(c) is-block = not is-block @@ -46,6 +45,9 @@ bi = hi holes.at(i).first() += bl holes.at(i).last() -= bl + if bl == hl { + holes.remove(i) + } break } } diff --git a/src/main.pdf b/src/main.pdf index f9b932a..7a62a2f 100644 Binary files a/src/main.pdf and b/src/main.pdf differ