diff --git "a/level-2/[3\354\260\250]-\353\260\251\352\270\210\352\267\270\352\263\241.js" "b/level-2/[3\354\260\250]-\353\260\251\352\270\210\352\267\270\352\263\241.js" new file mode 100644 index 0000000..20404da --- /dev/null +++ "b/level-2/[3\354\260\250]-\353\260\251\352\270\210\352\267\270\352\263\241.js" @@ -0,0 +1,42 @@ +// https://github.com/codeisneverodd/programmers-coding-test +// 완벽한 정답이 아닙니다. +// 정답 1 - minjongbaek +function convertString(m) { // 문자열 m에 #이 붙은 음이 있다면 #을 제거하고 소문자로 변경한 후 반환하는 함수 + return m + .replace(/C#/g, 'c') + .replace(/D#/g, 'd') + .replace(/F#/g, 'f') + .replace(/G#/g, 'g') + .replace(/A#/g, 'a'); +} + +function solution(m, musicinfos) { + + // 네오가 기억하고 있는 멜로디가 라디오에서 재생됐는지 확인해야합니다. + // 재생시간이 길면 악보의 멜로디가 반복되어 재생되고, 짧다면 중간에 끊어지게 됩니다. + // #이 붙은 음은 2자리를 차지하기 때문에 #이 붙은 음을 어떻게 처리할지가 중요합니다. + + const listenSound = convertString(m); // #이 붙은 음을 다른 문자로 변환합니다. + + const map = new Map(); // 조건에 일치하는 음악 정보를 저장할 map 변수를 선언합니다. + for (const info of musicinfos) { + const [start, finish, title, _score] = info.split(','); + // 음악 재생이 끝난 시각과 재생된 시각의 차를 구하여 재생시간을 구합니다. + const duration = ((Number(finish.slice(0, 2)) * 60) + (Number(finish.slice(3, 5)))) - ((Number(start.slice(0, 2)) * 60) + (Number(start.slice(3, 5)))); + + const score = convertString(_score); // 악보의 멜로디에서 #이 붙은 음을 다른 문자로 변환합니다. + + // 재생된 멜로디를 구합니다. + // 각 음이 1분에 1개씩 재생되므로, repeat() 메서드를 사용하여 재생시간을 악보의 길이로 나눈 몫 만큼 반복합니다. + // slice() 메서드로 재생시간을 넘어가는 멜로디는 제외합니다. + const playScore = score.repeat(Math.ceil(duration / score.length)).slice(0, duration); + if (playScore.includes(listenSound)) { // 들은 멜로디가 재생된 멜로디에 포함되어 있다면 map에 저장한다. + map.set(title, {score, playScore}); + } + } + + // 조건에 일치하는 음악이 여러개인 경우 재생된 시간이 제일 길고 먼저 입력된 음악 제목을 반환합니다. + // map 객체는 삽입에 대한 순서를 기억하므로 재생된 시간이 제일 긴 음악부터 내림차순으로 정렬합니다. + const filter = [...map.keys()].sort((a,b) => map.get(b).playScore.length - map.get(a).playScore.length); + return filter.length >= 1 ? filter[0] : '(None)'; // 결과가 없다면 '(None)'을 반환하고, 그렇지 않다면 첫 번째 요소를 반환합니다. +} \ No newline at end of file diff --git "a/level-2/k\354\247\204\354\210\230\354\227\220\354\204\234-\354\206\214\354\210\230-\352\260\234\354\210\230-\352\265\254\355\225\230\352\270\260.js" "b/level-2/k\354\247\204\354\210\230\354\227\220\354\204\234-\354\206\214\354\210\230-\352\260\234\354\210\230-\352\265\254\355\225\230\352\270\260.js" new file mode 100644 index 0000000..5425443 --- /dev/null +++ "b/level-2/k\354\247\204\354\210\230\354\227\220\354\204\234-\354\206\214\354\210\230-\352\260\234\354\210\230-\352\265\254\355\225\230\352\270\260.js" @@ -0,0 +1,23 @@ +// https://github.com/codeisneverodd/programmers-coding-test +// 완벽한 정답이 아닙니다. +// 정답 1 - minjongbaek +function isPrime(number) { // 소수를 판별하는 함수 + if (number < 2) return false; + for (let i = 2; i * i <= number; i += 1) { + if (number % i === 0) { + return false; + } + } + return true; +} + +function solution(n, k) { + // 문제를 얼핏 보면 4가지의 경우를 모두 생각해야할 것 같지만, + // 결국은 앞이나 뒤에 0이 하나라도 있거나 아예 없는 경우에 소수인지 확인하면 됩니다. + // 따라서 k진수로 변환 후 0을 기준으로 나누고 각 요소가 소수인지 판별하면 됩니다. + + // (n).toString(k) // n을 k진수로 변환합니다. + // .split('0') // 0을 기준으로 나눕니다. + // .filter((number) => isPrime(+number)).length // 소수가 아닌 요소를 걸러낸 후에 개수를 셉니다. + return (n).toString(k).split('0').filter((number) => isPrime(+number)).length; +} \ No newline at end of file diff --git "a/level-2/\353\271\233\354\235\230-\352\262\275\353\241\234-\354\202\254\354\235\264\355\201\264.js" "b/level-2/\353\271\233\354\235\230-\352\262\275\353\241\234-\354\202\254\354\235\264\355\201\264.js" new file mode 100644 index 0000000..8281b8c --- /dev/null +++ "b/level-2/\353\271\233\354\235\230-\352\262\275\353\241\234-\354\202\254\354\235\264\355\201\264.js" @@ -0,0 +1,76 @@ +// https://github.com/codeisneverodd/programmers-coding-test +// 완벽한 정답이 아닙니다. +// 정답 1 - minjongbaek + +// 빛의 이동을 위한 DX, DY 변수를 선언합니다. +const DX = [-1, 1, 0, 0]; +const DY = [0, 0, -1, 1]; + +function solution(grid) { + + // DFS에 4방향을 고려하여 문제를 풉니다. + // 핵심은 이미 방문한 칸이고 방향이 동일하다면 하나의 사이클이 형성된 것으로 생각해야합니다. + + const answer = []; + + // visited 변수를 선언 후 방문 여부를 확인할 3차원 배열을 할당합니다. [x좌표, y좌표, [하, 상, 좌, 우]] + const visited = Array.from({ length: grid.length }, () => []).map((v) => { + for (let i = 0; i < grid[0].length; i += 1) { + v.push(new Array(4).fill(false)); + } + return v + }); + + for (let x = 0; x < grid.length; x += 1) { + for (let y = 0; y < grid[0].length; y += 1) { + for (let d = 0; d < 4; d += 1) { + // x, y 좌표에 하, 상, 좌, 우 방향으로 방문한 적이 없다면 dfs를 수행합니다. + if (!visited[x][y][d]) { + const stack = []; + stack.push([x, y, d]); + + let cnt = 0; + while (stack.length !== 0) { + const [currentX, currentY, currentD] = stack.pop(); + if (!visited[currentX][currentY][currentD]) { + visited[currentX][currentY][currentD] = true; + cnt += 1; + + const [nextX, nextY] = getNextXY(currentX, currentY, currentD, grid.length, grid[0].length); // 다음으로 이동할 좌표를 구합니다. + const nextD = getNextD(grid[nextX][nextY], currentD) // x, y 칸에 적혀있는 문자열대로 방향을 다음 방향을 구합니다. + + stack.push([nextX, nextY, nextD]) + } + + } + answer.push(cnt); + } + } + } + } + return answer.sort((a, b) => a - b); +} + +// 다음 행선지를 구하는 함수 +function getNextXY(x, y, d, xLength, yLength) { + x += DX[d]; + y += DY[d]; + + // x나 y의 값이 유효하지 않은 경우 값을 재할당합니다. + if (x < 0) x = xLength - 1; + if (x >= xLength) x = 0; + if (y < 0) y = yLength - 1; + if (y >= yLength) y = 0; + + return [x, y]; +} + +// 현재 방향과 칸에 표시된 문자를 기준으로 다음 행선지의 방향을 구하는 함수 +function getNextD(command, d) { + if (command === 'L') { + d = [2, 3, 1, 0][d] + } else if (command === 'R') { + d = [3, 2, 0, 1][d] + } + return d +}