How many seats are occupied after the seating game?
Lazy solution:
const input = `
L.LL.LL.LL
LLLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLLL
L.LLLLLL.L
L.LLLLL.LL
`.trim()
let previousArrangement = input
const finalSeats = input.split('\n').reduce(reducer, [])
const occupiedSeats = finalSeats.join('').match(/(#)/g).length
console.log(occupiedSeats)
function reducer(newRows, row, y, currentRows) {
const newRow = [...row].reduce((newSeats, seat, x, currentSeats) => {
if (seat === '.') {
return newSeats + seat
}
const neighbors = [
currentRows[y - 1]?.[x - 1],
currentRows[y - 1]?.[x],
currentRows[y - 1]?.[x + 1],
currentSeats[x - 1],
currentSeats[x + 1],
currentRows[y + 1]?.[x - 1],
currentRows[y + 1]?.[x],
currentRows[y + 1]?.[x + 1],
]
if (seat === 'L' && !neighbors.includes('#')) {
return newSeats + '#'
}
if (seat === '#' && neighbors.filter((n) => n === '#').length >= 4) {
return newSeats + 'L'
}
return newSeats + seat
}, '')
newRows.push(newRow)
if (y !== currentRows.length - 1) {
return newRows
}
const newArrangement = newRows.join('\n')
// Calm has ensued 😌
if (previousArrangement === newArrangement) {
return newRows
}
// Has not!
previousArrangement = newArrangement
return newRows.reduce(reducer, [])
}
Play the seating game again, but now with slightly different rules. How many seats are occupied in the end?
We have to change two things from Part 1. First, the neighbors can be more far away, so let's implement a helper function for getting the next visible seat in each direction:
/* Before: */
const neighbors = [
currentRows[y - 1]?.[x - 1],
currentRows[y - 1]?.[x],
currentRows[y - 1]?.[x + 1],
currentSeats[x - 1],
currentSeats[x + 1],
currentRows[y + 1]?.[x - 1],
currentRows[y + 1]?.[x],
currentRows[y + 1]?.[x + 1],
]
/* After: */
// prettier-ignore
const Direction = {
northWest: { x: -1, y: -1 },
north: { x: 0, y: -1 },
northEast: { x: +1, y: -1 },
west: { x: -1, y: 0 },
east: { x: +1, y: 0 },
southWest: { x: -1, y: +1 },
south: { x: 0, y: +1 },
southEast: { x: +1, y: +1 },
}
const neighbors = Object.values(Direction).map((direction) =>
getNextVisibleSeat(currentRows, x, y, direction)
)
function getNextVisibleSeat(currentRows, x, y, direction) {
const seat = currentRows[y + direction.y]?.[x + direction.x]
return !seat || seat === 'L' || seat === '#'
? seat
: getNextVisibleSeat(
currentRows,
x + direction.x,
y + direction.y,
direction
)
}
And second, we need to change this condition:
-if (seat === '#' && neighbors.filter((n) => n === '#').length >= 4) {
+if (seat === '#' && neighbors.filter((n) => n === '#').length >= 5) {
return newSeats + 'L'
}
Nothing, not even after refactoring Part 2, which initially had this ✨ beautiful ✨ solution:
const neighbors = [
getUpperLeftSeat(currentRows, i, j),
getUpperSeat(currentRows, i, j),
getUpperRightSeat(currentRows, i, j),
getLeftSeat(currentRows, i, j),
getRightSeat(currentRows, i, j),
getLowerLeftSeat(currentRows, i, j),
getLowerSeat(currentRows, i, j),
getLowerRightSeat(currentRows, i, j),
]
// ...
function getUpperLeftSeat(currentRows, i, j) {
for (i--, j--; i >= 0 && j >= 0; i--, j--) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getUpperSeat(currentRows, i, j) {
for (i--; i >= 0; i--) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getUpperRightSeat(currentRows, i, j) {
for (i--, j++; i >= 0 && j < currentRows[0].length; i--, j++) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getLeftSeat(currentRows, i, j) {
for (j--; j >= 0; j--) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getRightSeat(currentRows, i, j) {
for (j++; j < currentRows[0].length; j++) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getLowerLeftSeat(currentRows, i, j) {
for (i++, j--; i < currentRows.length && j >= 0; i++, j--) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getLowerSeat(currentRows, i, j) {
for (i++; i < currentRows.length; i++) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
function getLowerRightSeat(currentRows, i, j) {
for (
i++, j++;
i < currentRows.length && j < currentRows[0].length;
i++, j++
) {
const seat = currentRows[i][j]
if (seat === 'L' || seat === '#') return seat
}
}
I'm still so proud. 🤣
Try it out on flems.io because I know you want to!