diff --git a/README.md b/README.md index db17411..2ff4f39 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ This project can also be run using the amazing [CraftOS-PC emulator](https://git ## Progress -#### Stars: 7/24 +#### Stars: 8/24 |Mon|Tue|Wed|Thu|Fri|Sat|Sun| |:-:|:-:|:-:|:-:|:-:|:-:|:-:| -|1
:star::star:|2
:star::star:|3
:star::star:|4
:star:|5
|6
|7
| +|1
:star::star:|2
:star::star:|3
:star::star:|4
:star::star:|5
|6
|7
| |8
|9
|10
|11
|12
||| diff --git a/res/stats.json b/res/stats.json index 1b76e81..21a0983 100644 --- a/res/stats.json +++ b/res/stats.json @@ -13,7 +13,7 @@ }, "day04": { "puzzle1": true, - "puzzle2": false + "puzzle2": true }, "day05": { "puzzle1": false, diff --git a/src/day04/puzzle2.lua b/src/day04/puzzle2.lua index 2f4bc9a..99a9861 100644 --- a/src/day04/puzzle2.lua +++ b/src/day04/puzzle2.lua @@ -1,7 +1,106 @@ +local utils = require "utils" + local puzzle2 = {} +function puzzle2.inGrid(x, y, w, h) + return 1 <= x and x <= w and 1 <= y and y <= h +end + +function puzzle2.countNeighbors(lines, w, h, x, y) + local neighbors = 0 + for dy=-1, 1 do + for dx=-1, 1 do + if dx ~=0 or dy ~= 0 then + local x2 = x + dx + local y2 = y + dy + if puzzle2.inGrid(x2, y2, w, h) then + if lines[y2]:sub(x2, x2) == "@" then + neighbors = neighbors + 1 + end + end + end + end + end + return neighbors +end + +function puzzle2.copyGrid(grid) + local grid2 = {} + for y, row in ipairs(grid) do + local row2 = {} + for x, n in ipairs(row) do + row2[x] = n + end + grid2[y] = row2 + end + return grid2 +end + +function puzzle2.removeRoll(grid, x, y, w, h) + for dy=-1, 1 do + for dx=-1, 1 do + if dx ~= 0 or dy ~= 0 then + local x2 = x + dx + local y2 = y + dy + if puzzle2.inGrid(x2, y2, w, h) then + if grid[y2][x2] > 0 then + grid[y2][x2] = grid[y2][x2] - 1 + end + end + end + end + end + grid[y][x] = -1 +end + +function puzzle2.removeRolls(grid, w, h) + local removed = 0 + local grid2 = puzzle2.copyGrid(grid) + + for y, row in ipairs(grid) do + for x, n in ipairs(row) do + if 0 <= n and n < 4 then + puzzle2.removeRoll(grid2, x, y, w, h) + removed = removed + 1 + end + end + end + + return removed, grid2 +end + function puzzle2.solve(input) - return 0 + local lines = utils.splitLines(input) + + local h = #lines + local w = #lines[1] + + local grid = {} + + for y, line in ipairs(lines) do + local row = {} + for x=1, #line do + local neighbors = -1 + if line:sub(x, x) == "@" then + neighbors = puzzle2.countNeighbors(lines, w, h, x, y) + end + row[x] = neighbors + end + grid[y] = row + end + + local totalRemoved = 0 + + local removed = 0 + while true do + removed, grid = puzzle2.removeRolls(grid, w, h) + if removed == 0 then + break + end + totalRemoved = totalRemoved + removed + end + + return totalRemoved end return puzzle2