function solution(key, lock) {
const keySize = key.length;
const lockSize = lock.length;
const boardSize = lockSize * 3;
let ans = false;
// 배열의 x, y 좌표를 자연수 위치 정보로 변환
const toNumbers = (grid, offset=0, inverted=false) => {
const numbers = new Set();
grid.forEach((row, i) =>
row.forEach((c, j) =>
(c ^ inverted) && numbers.add(i * boardSize + j + offset)))
return numbers;
};
// 자연수 위치 정보를 set으로 전달 받아 board를 기준으로 회전된 set을 리턴
const rotateInBoard = (numbers) => {
const rotated = new Set();
numbers.forEach(num => {
const rotatedNumber = boardSize * (boardSize -1) + Math.floor(num / boardSize) - boardSize * (num %boardSize)
rotated.add(rotatedNumber);
})
return rotated;
}
const keyX = lockSize - keySize + 1;
const lockX = lockSize;
let keyNumbers = toNumbers(key, keyX*(1 + boardSize));
const lockNumbers = toNumbers(lock, lockX*(1 + boardSize));
const lockEmptyNumbers = toNumbers(lock, lockSize*(1 + boardSize), true);
// key 블락의 개수가 lock의 빈 부분보다 작을 경우 false 리턴
if(keyNumbers.size < lockEmptyNumbers.size){
return false;
}
// 회전/평행이동 후 확인
// 회전
for(let i=0; i<4; i++){
const offsetXDir = [1, -1, -1, 1]
const offsetYDir = [-1, -1, 1, 1]
keyNumbers = rotateInBoard(keyNumbers); // 회전된 위치 정보
const lookupSize = lockSize + keySize-1; // 평행 이동할 거리
for(let j=0; j<lookupSize; j++){
for(let k=0; k<lookupSize; k++){
const offset = offsetXDir[i] * j + offsetYDir[i] * k * boardSize;
let emptyCount = lockEmptyNumbers.size; // 채워야할(빈 부분) 개수
for(let keySnippet of keyNumbers){
const movedKeySnippet = keySnippet + offset;
// 평행이동된 열쇠의 위치
if(lockNumbers.has(movedKeySnippet)){
// lock 블락과 겹칠 경우 break
break;
}
if(lockEmptyNumbers.has(movedKeySnippet)){
// lock의 빈 부분을 채울 경우 emptyCount 감소
emptyCount--;
}
}
if(emptyCount===0){ // 모두 채워질 경우 true 반환
return true;
}
}
}
}
return ans;
}
Level
프로그래머스 Lv3
Day
13일
kakao
2020 카카오 블라인드