DEV Community

Cover image for Advent of code - Day 17
Quentin Ménoret
Quentin Ménoret

Posted on

Advent of code - Day 17

Are you participating in the Advent of code this year?

If you don't know what the advent of code is, it's a website where you'll find a daily challenge (every day it gets harder). It's a really fun event, you should participate!

I try to solve the exercises using either JavaScript or TypeScript and will share my solutions daily (with one day delay so no one can cheat!). I only share the solution for the second part.

For this one, I'm not going to lie... I cheated!
I actually updated the input manually, and generated a big enough map... So I didn't have to handle infinite size! Since we know that there are at most 6 cycles, then the end size of each size if the original plus and minus 6.

It's definitely not a solution that is easy to extend (far from generic) but... It works in this case!

Here is my solution for day #17:

let input = `.................................................
.................................................
.................................................
.................................................
....................##.####......................
....................#.....#......................
...................#.###.##......................
...................#####.##......................
...................#...##.#......................
...................#######.......................
...................##.#####......................
....................##...#.......................
.................................................
.................................................
.................................................
.................................................
.................................................`
  .split('\n')
  .map((x) => x.split(''))

// Here I'm generating the "bigger" map
input = [
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input,
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
  input.map((x) => x.map((y) => '.')),
]

input = [
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input,
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
  input.map((x) => x.map((y) => y.map((y) => '.'))),
]

function getNeighbours(coordinates) {
  return _getNeighbours(coordinates).filter((n) => !n.every((x, index) => x === coordinates[index]))
}

function _getNeighbours(coordinates) {
  if (coordinates.length === 1) return [-1, 0, 1].map((x) => [coordinates[0] + x])
  const result = _getNeighbours(coordinates.slice(1))

  return [
    ...result.map((r) => [coordinates[0] - 1, ...r]),
    ...result.map((r) => [coordinates[0], ...r]),
    ...result.map((r) => [coordinates[0] + 1, ...r]),
  ]
}

function next(state) {
  return state.map((yLayer, x) => {
    return yLayer.map((zLayer, y) => {
      return zLayer.map((wLayer, z) => {
        return wLayer.map((element, w) => {
          const neighbours = getNeighbours([x, y, z, w])
          const count = neighbours.reduce((acc, [x, y, z, w]) => {
            if (!state[x] || !state[x][y] || !state[x][y][z] || !state[x][y][z][w]) return acc
            if (state[x][y][z][w] === '#') return acc + 1
            return acc
          }, 0)
          if (count === 3) return '#'
          if (element === '#' && count === 2) return '#'
          return '.'
        })
      })
    })
  })
}

const finalState = [0, 1, 2, 3, 4, 5].reduce((state) => {
  let next1 = next(state)
  return next1
}, input)

const count = finalState.reduce(
  (acc, xLayer) =>
    acc +
    xLayer.reduce(
      (acc, yLayer) =>
        acc +
        yLayer.reduce((acc, wLayer) => acc + wLayer.reduce((acc, element) => acc + (element === '#' ? 1 : 0), 0), 0),
      0,
    ),
  0,
)

console.log(count)
Enter fullscreen mode Exit fullscreen mode

Feel free to share your solution in the comments!


Photo by Markus Spiske on Unsplash

Discussion (0)