// 자바스크립트 클린 코드에서 가능한한 함수는 하나의 기능만 수행할 것을 강조하였고,
// 조건문을 최대한 쓰지 않을 것을 권했기에 rotateBorad에서 따로 뺀 함수이다.
// 이 함수가 없었으면 rotateBoard의 중첩 반복문 안에 조건문이 하나 더 있었을 것
const initHash = (hash, lengthOfKey) => {
for (let i = 0; i < lengthOfKey; i++) {
hash[i + 1] = [];
}
return hash;
};
// rotateBoard함수에서 조건문을 빼고 싶어서 만든 함수인데,
// 좋은 선택인지는 잘 모르겠다.
// 함수의 인자는 2개 이하가 이상적이라고 클린 코드에서 권했기 때문.
const pushExceptZero = (hashTable, index, item) => {
if (item != 0) {
hashTable[index].push(item);
}
};
// moves배열의 각 요소가 '열'의 인덱스에 해당하므로,
// 각 열을 스택으로 만들고자 하였다.
// 또한, 배열을 순회하는 것보다 해쉬의 자료구조가 검색이 빠르므로
// 2차원 배열을 만들지 않고 해쉬테이블에 각 스택을 할당하였다.
const rotateBoard = (matrix) => {
const lengthOfRow = matrix.length;
const lengthOfCol = matrix[0].length;
const hashTable = initHash({}, lengthOfCol);
for (let i = lengthOfRow - 1; i >= 0; i--) {
for (let j = 0; j < lengthOfCol; j++) {
const currentElement = matrix[i][j];
pushExceptZero(hashTable, j + 1, currentElement);
}
}
return hashTable;
};
const solution = (board, moves) => {
let count = 0;
const stack = [];
const rotatedBoard = rotateBoard(board);
// 1.각 열을 스택으로 보고 pop을 하는 게 가장 쉽다고 생각했기 때문에
// 그에 맞게 board 배열을 변환해줄 필요가 있었다.
for (let choice of moves) {
const poppedItem = rotatedBoard[choice].pop();
if (poppedItem) {
const topOfStack = stack[stack.length - 1];
if (poppedItem == topOfStack) {
count += 2;
stack.pop();
} else {
stack.push(poppedItem);
}
}
}
return count;
};
가장 좋아요를 많이 받은 풀이를 보니 board 배열을 변환하는 과정이 내 풀이보다 훨씬 간결했다.
해당 풀이는 reduce를 썼는데, 정확하게 이해를 못해서 그런지 나는 reduce는 한 번도 써본 적이 없는 것 같다.
(반성해야 할 점...)
다만 해당 풀이는 결국 2차원 배열을 사용했는데, 이 부분은 해쉬로 만드는 것이 검색의 시간을 줄이는 게 아닌가 싶다.
for of 문에도 continue가 가능한 줄은 몰랐다;;
자바스크립트를 제대로 이해한 것도 아니고, 자료구조를 제대로 공부한 것도 아니니 항상 풀 때마다 찝찝하다.
그렇다고 둘 다 공부하고 오자니 시간이 너무 부족하고...
[1차] 프렌즈4블록 문제를 풀다가 행렬을 회전시킨다는 개념이 비슷해서 참고하려고 돌아와봤더니 오류가 있어서 수정함
const rotateMatrix = (matrix) => {
const rowLength = matrix.length;
const colLength = matrix[0].length;
const newMatrix = [];
for (let i = 0; i < colLength; i++) {
const temp = [];
for (let j = rowLength - 1; j >= 0; j--) {
if (matrix[j][i] != 0) {
temp.push(matrix[j][i]);
}
}
newMatrix.push(temp);
}
return newMatrix;
};
const solution = (board, moves) => {
let count = 0;
const stack = [];
const rotatedBoard = rotateMatrix(board);
for (let choice of moves) {
const poppedItem = rotatedBoard[choice - 1].pop();
if (poppedItem) {
const topOfStack = stack[stack.length - 1];
if (poppedItem == topOfStack) {
count += 2;
stack.pop();
} else {
stack.push(poppedItem);
}
}
}
return count;
};
저번 풀이에서는 검색을 빠르게 하기 위해서 rotateBoard함수에서 해쉬를 만들어 반환한다고 설명했다.
그런데 배열도 index로 접근하는 것은 시간 복잡도가 1이다.
(뭐에 씌였나...)
// 인형을 뽑는 작업을 pop으로 수행하기 위해 2차원 배열 회전시키기
function rotate90(matrix) {
const rotated = [];
for (let col = 0; col < matrix.length; col++) {
const newRow = [];
for (let row = matrix.length - 1; row >= 0; row--) {
if (matrix[row][col] == 0) {
continue;
}
newRow.push(matrix[row][col]);
}
rotated.push(newRow);
}
return rotated;
}
function solution(board, moves) {
const rotated = rotate90(board);
const stack = [];
function reduceHelper(acc, cur) {
const picked = rotated[cur - 1].pop();
if (!picked) {
return acc;
}
const topOfTheStack = stack[stack.length - 1];
if (picked == topOfTheStack) {
stack.pop();
acc += 2;
} else {
stack.push(picked);
}
return acc;
}
return moves.reduce(reduceHelper, 0);
}