기둥과 보 설치 - 2020 kakao blind recruitment
처음 wall 변수를 초기화할 때, 자바스크립트의 fill로 객체를 담은 array로 채워주었다.
문제는 wall의 배열들이 같은 배열의 reference였다는 것이다. 
  const wall = new Array(n + 1).fill(
  new Array(n + 1).fill({ pillar: 0, bo: 0 }));
이 문제를 해결하기 위해 fill()로 임의의 값을 넣어준 후, map()을 돌면서 각 요소들을 변형시켜주었다.
  const wall = new Array(n + 1)
    .fill()
    .map((_) => new Array(n + 1).fill().map((_) => ({ pillar: 0, bo: 0 })));
const a = [1, { hi: "hi" }];
const b = [...a];
console.log(b); //[ 1, { hi: 'hi' } ]
b[0] = 100;
b[1].hi = "bye";
console.log(a); // [ 1, { hi: 'bye' } ]
console.log(b); // [ 100, { hi: 'bye' } ]const PILLAR = 0;
const BO = 1;
const REMOVE = 0;
const INSTALL = 1;
const getInitialWall = (n) => {
  const wall = new Array(n + 1)
    .fill()
    .map((_) =>
      new Array(n + 1).fill().map((_) => ({ pillar: false, bo: false }))
    );
  return wall;
};
const isValidPillar = (wall, x, y) => {
  const isOnFloor = y === 0;
  const isOnBo = wall[y][x].bo || (x - 1 >= 0 && wall[y][x - 1].bo);
  const isOnPillar = y - 1 >= 0 && wall[y - 1][x].pillar;
  return isOnFloor || isOnBo || isOnPillar;
};
const isValidBo = (n) => (wall, x, y) => {
  const checkOneSideOnPillar =
    y - 1 >= 0 &&
    (wall[y - 1][x].pillar || (x + 1 <= n && wall[y - 1][x + 1].pillar));
  const checkBothOnBo =
    x - 1 >= 0 && wall[y][x - 1].bo && x + 1 < n && wall[y][x + 1].bo;
  return checkOneSideOnPillar || checkBothOnBo;
};
const toggleStatusOfWall = (wall, x, y, type) => {
  wall[y][x][type] = !wall[y][x][type];
};
const checkNoEffect = (validFunc, testWall, locList, n, type) => {
  const passAllValidFunc = locList
    .filter((loc) => loc.x >= 0 && loc.y <= n && testWall[loc.y][loc.x][type])
    .every((loc) => validFunc(testWall, loc.x, loc.y));
  return passAllValidFunc;
};
const removeBoIfPossible = (wall, x, y, n) => {
  const boLoc = [
    { x: x - 1, y },
    { x: x + 1, y },
  ];
  const pillarLoc = [
    { x, y },
    { x: x + 1, y },
  ];
  toggleStatusOfWall(wall, x, y, "bo");
  const noEffectOnBo = checkNoEffect(isValidBo(n), wall, boLoc, n, "bo");
  const noEffectOnPillar = checkNoEffect(
    isValidPillar,
    wall,
    pillarLoc,
    n,
    "pillar"
  );
  if (noEffectOnBo && noEffectOnPillar) {
    return;
  }
  toggleStatusOfWall(wall, x, y, "bo");
};
const removePillarIfPossible = (wall, x, y, n) => {
  const boLoc = [
    { x, y: y + 1 },
    { x: x - 1, y: y + 1 },
  ];
  const pillarLoc = [{ x, y: y + 1 }];
  toggleStatusOfWall(wall, x, y, "pillar");
  const noEffectOnBo = checkNoEffect(isValidBo(n), wall, boLoc, n, "bo");
  const noEffectOnPillar = checkNoEffect(
    isValidPillar,
    wall,
    pillarLoc,
    n,
    "pillar"
  );
  if (noEffectOnBo && noEffectOnPillar) {
    return;
  }
  toggleStatusOfWall(wall, x, y, "pillar");
};
const installIfPossible = (validFunc, wall, x, y, type) => {
  if (!validFunc(wall, x, y)) {
    return;
  }
  wall[y][x][type] = true;
};
const getFinalFrame = (wall, n) => {
  const finalFrame = [];
  for (let x = 0; x <= n; x++) {
    for (let y = 0; y <= n; y++) {
      if (wall[y][x].pillar) {
        finalFrame.push([x, y, PILLAR]);
      }
      if (wall[y][x].bo) {
        finalFrame.push([x, y, BO]);
      }
    }
  }
  return finalFrame;
};
function solution(n, build_frame) {
  const wall = getInitialWall(n);
  for (const [x, y, type, action] of build_frame) {
    if (type === PILLAR) {
      if (action === INSTALL) {
        installIfPossible(isValidPillar, wall, x, y, "pillar");
      } else {
        removePillarIfPossible(wall, x, y, n);
      }
    } else {
      // BO
      if (action === INSTALL) {
        installIfPossible(isValidBo(n), wall, x, y, "bo");
      } else {
        removeBoIfPossible(wall, x, y, n);
      }
    }
  }
  const finalFrame = getFinalFrame(wall, n);
  return finalFrame;
}
원래 소감은 안썼지만 이 문제는 소감을 써야겠다...
이 문제는 나한테 얕은 복사와 깊은 복사를 몰랐던 나를 아주 크게 혼내주었다.
초반에 초기화할 때, '='연산자로 할당한 배열의 요소들은 original 배열의 메모리를 참조하고 있었다. 따라서 배열에서 한 요소의 값만 바꿔도 전체 배열의 모든 값들이 변경되는 것처럼 보였다.
두 번째 위기는 배열이 깊은 복사가 된다고 생각해서 문제가 생겼다. 알고리즘 풀면서 javascript 이해가 부족했던 점을 채울 수 있어서 다행인 것 같다.