Skip to content

Latest commit

 

History

History
235 lines (188 loc) · 14.3 KB

11.md

File metadata and controls

235 lines (188 loc) · 14.3 KB

Day 11

Part 1

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, [])
}

Try it out on flems.io

Part 2

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'
 }

flems

What did I learn?

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!