|
| 1 | +function parseInput(filePath) |
| 2 | + local file = io.open(filePath, "r") -- Open file for reading |
| 3 | + if not file then return nil end -- Return nil if file can't be opened |
| 4 | + |
| 5 | + local array2D = {} |
| 6 | + for line in file:lines() do |
| 7 | + local row = {} |
| 8 | + for char in line:gmatch(".") do -- Iterate over each character in the line |
| 9 | + table.insert(row, char) -- Insert character into the row |
| 10 | + end |
| 11 | + table.insert(array2D, row) -- Insert row into the 2D array |
| 12 | + end |
| 13 | + |
| 14 | + file:close() -- Close the file |
| 15 | + return array2D |
| 16 | +end |
| 17 | + |
| 18 | +function copyRoundedRockPositions(roundedRocks) |
| 19 | + local newArray = {} |
| 20 | + for i, value in ipairs(roundedRocks) do |
| 21 | + newArray[i] = {row = value.row, column = value.column } |
| 22 | + end |
| 23 | + return newArray |
| 24 | +end |
| 25 | + |
| 26 | +function positionsAreEqual(roundedRocks1, roundedRocks2) |
| 27 | + for i = 1, #roundedRocks1 do |
| 28 | + if roundedRocks1[i].row ~= roundedRocks2[i].row then |
| 29 | + return false |
| 30 | + end |
| 31 | + if roundedRocks1[i].column ~= roundedRocks2[i].column then |
| 32 | + return false |
| 33 | + end |
| 34 | + end |
| 35 | + return true |
| 36 | +end |
| 37 | + |
| 38 | +function findRockPositions(history, roundedRocks) |
| 39 | + for i = 1, #history do |
| 40 | + if positionsAreEqual(history[i], roundedRocks) then |
| 41 | + return i |
| 42 | + end |
| 43 | + end |
| 44 | + return -1 |
| 45 | +end |
| 46 | + |
| 47 | +function findRoundedRocks(array2D) |
| 48 | + local positions = {} |
| 49 | + for rowIndex, row in ipairs(array2D) do |
| 50 | + for columnIndex, char in ipairs(row) do |
| 51 | + if char == 'O' then |
| 52 | + table.insert(positions, {row = rowIndex, column = columnIndex}) |
| 53 | + end |
| 54 | + end |
| 55 | + end |
| 56 | + return positions |
| 57 | +end |
| 58 | + |
| 59 | +local function sortByRowDesc(a, b) |
| 60 | + if (a.row == b.row) then |
| 61 | + return a.column > b.column |
| 62 | + end |
| 63 | + return a.row > b.row; |
| 64 | +end |
| 65 | + |
| 66 | +local function sortByRowAsc(a, b) |
| 67 | + if (a.row == b.row) then |
| 68 | + return a.column < b.column |
| 69 | + end |
| 70 | + return a.row < b.row; |
| 71 | +end |
| 72 | + |
| 73 | +local function sortByColDesc(a, b) |
| 74 | + if (a.column == b.column) then |
| 75 | + return a.row > b.row |
| 76 | + end |
| 77 | + return a.column > b.column; |
| 78 | +end |
| 79 | + |
| 80 | +local function sortByColAsc(a, b) |
| 81 | + if (a.column == b.column) then |
| 82 | + return a.row < b.row |
| 83 | + end |
| 84 | + return a.column < b.column; |
| 85 | +end |
| 86 | + |
| 87 | + |
| 88 | +function tiltNorth(array2D, roundedRocks) |
| 89 | + table.sort(roundedRocks, sortByRowAsc) |
| 90 | + for _, pos in ipairs(roundedRocks) do |
| 91 | + while pos.row > 1 and array2D[pos.row - 1][pos.column] == '.' do |
| 92 | + array2D[pos.row][pos.column] = '.' |
| 93 | + pos.row = pos.row - 1 |
| 94 | + array2D[pos.row][pos.column] = 'O' |
| 95 | + end |
| 96 | + end |
| 97 | +end |
| 98 | + |
| 99 | +function tiltSouth(array2D, roundedRocks) |
| 100 | + table.sort(roundedRocks, sortByRowDesc) |
| 101 | + for _, pos in ipairs(roundedRocks) do |
| 102 | + while pos.row < #array2D and array2D[pos.row + 1][pos.column] == '.' do |
| 103 | + array2D[pos.row][pos.column] = '.' |
| 104 | + pos.row = pos.row + 1 |
| 105 | + array2D[pos.row][pos.column] = 'O' |
| 106 | + end |
| 107 | + end |
| 108 | +end |
| 109 | + |
| 110 | +function tiltEast(array2D, roundedRocks) |
| 111 | + table.sort(roundedRocks, sortByColDesc) |
| 112 | + for _, pos in ipairs(roundedRocks) do |
| 113 | + while pos.column < #array2D and array2D[pos.row][pos.column + 1] == '.' do |
| 114 | + array2D[pos.row][pos.column] = '.' |
| 115 | + pos.column = pos.column + 1 |
| 116 | + array2D[pos.row][pos.column] = 'O' |
| 117 | + end |
| 118 | + end |
| 119 | +end |
| 120 | + |
| 121 | +function tiltWest(array2D, roundedRocks) |
| 122 | + table.sort(roundedRocks, sortByColAsc) |
| 123 | + for _, pos in ipairs(roundedRocks) do |
| 124 | + while pos.column > 1 and array2D[pos.row][pos.column - 1] == '.' do |
| 125 | + array2D[pos.row][pos.column] = '.' |
| 126 | + pos.column = pos.column - 1 |
| 127 | + array2D[pos.row][pos.column] = 'O' |
| 128 | + end |
| 129 | + end |
| 130 | +end |
| 131 | + |
| 132 | +function cycle(charArray2D, roundedRocks) |
| 133 | + tiltNorth(charArray2D, roundedRocks) |
| 134 | + tiltWest(charArray2D, roundedRocks) |
| 135 | + tiltSouth(charArray2D, roundedRocks) |
| 136 | + tiltEast(charArray2D, roundedRocks) |
| 137 | +end |
| 138 | + |
| 139 | + |
| 140 | +function calculateWeight(array2D, roundedRocks) |
| 141 | + local totalWeight = 0 |
| 142 | + for _, pos in ipairs(roundedRocks) do |
| 143 | + local weight = (#array2D - pos.row) + 1 |
| 144 | + totalWeight = totalWeight + weight |
| 145 | + end |
| 146 | + return totalWeight |
| 147 | +end |
| 148 | + |
| 149 | +function printArray(array2D) |
| 150 | + for i, row in ipairs(array2D) do |
| 151 | + for j, char in ipairs(row) do |
| 152 | + io.write(char) |
| 153 | + end |
| 154 | + io.write("\n") |
| 155 | + end |
| 156 | + io.write("\n") |
| 157 | + |
| 158 | +end |
| 159 | + |
| 160 | +function solve(pathToFile) |
| 161 | + local charArray2D = parseInput(pathToFile) |
| 162 | + local roundedRocks = findRoundedRocks(charArray2D) |
| 163 | + tiltNorth(charArray2D, roundedRocks) |
| 164 | + io.write(calculateWeight(charArray2D, roundedRocks)) |
| 165 | + io.write("\n") |
| 166 | +end |
| 167 | + |
| 168 | +function solve2(pathToFile) |
| 169 | + local charArray2D = parseInput(pathToFile) |
| 170 | + local roundedRocks = findRoundedRocks(charArray2D) |
| 171 | + |
| 172 | + local historyOfPos = { } |
| 173 | + |
| 174 | + local countUntilRepeats; |
| 175 | + local cycleLength |
| 176 | + for i = 1, 1000000000 do |
| 177 | + cycle(charArray2D, roundedRocks) |
| 178 | + |
| 179 | + local existingPos = findRockPositions(historyOfPos, roundedRocks) |
| 180 | + if existingPos > -1 then |
| 181 | + countUntilRepeats = existingPos |
| 182 | + cycleLength = i - countUntilRepeats |
| 183 | + break |
| 184 | + end |
| 185 | + |
| 186 | + table.insert(historyOfPos, copyRoundedRockPositions(roundedRocks)) |
| 187 | + end |
| 188 | + |
| 189 | + local remainingCycles = (1000000000 - countUntilRepeats) % cycleLength |
| 190 | + |
| 191 | + for i = 1, remainingCycles do |
| 192 | + cycle(charArray2D, roundedRocks) |
| 193 | + end |
| 194 | + |
| 195 | + |
| 196 | + io.write(calculateWeight(charArray2D, roundedRocks)) |
| 197 | + io.write("\n") |
| 198 | +end |
| 199 | + |
| 200 | +local pathToFile = "input" |
| 201 | +solve(pathToFile) |
| 202 | +solve2(pathToFile) |
0 commit comments