diff --git a/problem-1/problem-1.test.js b/problem-1/problem-1.test.js index c775a02..4006f53 100644 --- a/problem-1/problem-1.test.js +++ b/problem-1/problem-1.test.js @@ -1,4 +1,50 @@ +// 1. 가장 익숙한 방법으로 문제를 해결해 주세요. +// const solution = (numbers) => { +// let answer = 0; +// +// for (let i = 0; i < numbers.length; i += 1) { +// answer += numbers[i]; +// } +// +// return answer; +// }; + +// 2. 이번에는 재귀 함수로 문제를 해결해 주세요. +// const solution = (numbers) => { +// // Base Case +// if (numbers.length === 0) { +// return 0; +// } +// +// // Recursive Case +// return numbers.pop() + solution(numbers); +// }; + +// 3. 꼬리 재귀 함수로 바꿔보세요. +// -> Maximum call stack size exceeded 발생.. +// const solution = (numbers, acc = 0) => { +// if (numbers.length === 0) { +// return acc; +// } +// +// // return solution(numbers.slice(0, numbers.length - 1), acc + numbers[numbers.length - 1]); +// return solution(numbers, acc + numbers.pop()); +// }; + +// 4. 꼬리 재귀 최적화를 통해서 최적화해 보세요. const solution = (numbers) => { + // 1) 계속해서 바뀌는 값을 변수로 선언한다. + let acc = 0; + let index = 0; + + // 3) 반복문을 만든다. + while (index < numbers.length) { + // 2) 재귀 함수 호출로 값을 변경하는 대신에 변수의 값을 할당해서 변경한다. + acc = acc + numbers[index]; + index += 1; + } + + return acc; }; test('빈 배열은 0을 반환한다', () => { diff --git a/problem-2/problem-2.test.js b/problem-2/problem-2.test.js index 458a6b8..e39822e 100644 --- a/problem-2/problem-2.test.js +++ b/problem-2/problem-2.test.js @@ -1,4 +1,67 @@ +// 1. 가장 익숙한 방법으로 문제를 해결해 주세요. +// const solution = (n) => { +// if (n <= 0) { +// return 0; +// } +// +// if (n === 1) { +// return 1; +// } +// +// const fibonacci = [0, 1]; +// +// for (let i = 2; i <= n; i += 1) { +// fibonacci[i] = fibonacci[i - 2] + fibonacci[i - 1]; +// } +// +// return fibonacci[n]; +// }; + +// 2. 이번에는 재귀 함수로 문제를 해결해 주세요. +// const solution = (n) => { +// if (n <= 0) { +// return 0; +// } +// +// if (n === 1) { +// return 1; +// } +// +// return solution(n - 2) + solution(n - 1); +// }; + +// 3. 꼬리 재귀 함수로 바꿔보세요. +// const solution = (n, prev = 0, curr = 1) => { +// if (n <= 0) { +// return prev; +// } +// +// if (n === 1) { +// return curr; +// } +// +// return solution(n - 1, curr, prev + curr); +// }; + +// 4. 꼬리 재귀 최적화를 통해서 최적화해 보세요. const solution = (n) => { + let currentNumber = n; + let previousValue = 0; + let currentValue = 1; + let nextValue; + + while (currentNumber > 0) { + if (currentNumber === 1) { + return currentValue; + } + + nextValue = previousValue + currentValue; + previousValue = currentValue; + currentValue = nextValue; + currentNumber -= 1; + } + + return previousValue; }; test('음수가 주어지면 0을 반환한다', () => { diff --git a/problem-3/problem-3.test.js b/problem-3/problem-3.test.js index 7319eb8..3239e1e 100644 --- a/problem-3/problem-3.test.js +++ b/problem-3/problem-3.test.js @@ -1,4 +1,30 @@ -const solution = (n) => { +// const solution = (n) => { +// if (n === 0) { +// return '0'; +// } +// +// let number = n; +// let binaryString = ''; +// +// while (number > 0) { +// const remainder = number % 2; +// binaryString = remainder + binaryString; +// number = Math.floor(number / 2); +// } +// +// return binaryString; +// }; + +const solution = (n, binaryString = '') => { + if (n === 0) { + return '0'; + } + + if (n === 1) { + return `1${binaryString}`; + } + + return solution(Math.floor(n / 2), (n % 2).toString() + binaryString); }; test('이진수 문자열을 반환한다', () => { diff --git a/problem-4/problem-4.test.js b/problem-4/problem-4.test.js index 19f5cb0..7cfeb63 100644 --- a/problem-4/problem-4.test.js +++ b/problem-4/problem-4.test.js @@ -1,4 +1,67 @@ -const solution = () => { +// const solution = (binaryString) => { +// let decimalNumber = 0; +// for (let bitIndex = 0; bitIndex < binaryString.length; bitIndex += 1) { +// const currentBit = parseInt(binaryString[bitIndex], 10); +// const bitWeight = 2 ** (binaryString.length - 1 - bitIndex); +// +// const currentBitValue = currentBit * bitWeight; +// decimalNumber += currentBitValue; +// } +// +// return decimalNumber; +// }; + +// const solution = ( +// binaryString, +// currentIndex = 0, +// bitWeight = binaryString.length - 1, +// ) => { +// if (binaryString === '0') { +// return 0; +// } +// +// if (binaryString === '1') { +// return 1; +// } +// +// if (bitWeight < 0) { +// return 0; +// } +// +// const currentBit = parseInt(binaryString[currentIndex], 10); +// const currentBitValue = (2 ** bitWeight) * currentBit; +// +// return currentBitValue + solution( +// binaryString, +// currentIndex + 1, +// bitWeight - 1, +// ); +// }; + +const solution = ( + binaryString, + currentIndex = 0, + bitWeight = binaryString.length - 1, + decimalNumber = 0, +) => { + if (binaryString === '0') { + return 0; + } + + if (binaryString === '1') { + return 1; + } + + if (bitWeight < 0) { + return decimalNumber; + } + + return solution( + binaryString, + currentIndex + 1, + bitWeight - 1, + decimalNumber + (2 ** bitWeight) * parseInt(binaryString[currentIndex], 10), + ); }; test('10진수 숫자를 반환한다', () => { diff --git a/problem-5/problem-5.test.js b/problem-5/problem-5.test.js index 20a8fab..e59e56e 100644 --- a/problem-5/problem-5.test.js +++ b/problem-5/problem-5.test.js @@ -1,4 +1,27 @@ -const solution = () => { +/* +const solution = (num1, num2) => { + let smallerNumber = num1; + let largerNumber = num2; + + while (true) { + const remainder = largerNumber % smallerNumber; + + if (remainder === 0) { + return smallerNumber; + } + + largerNumber = smallerNumber; + smallerNumber = remainder; + } +}; +*/ + +const solution = (smallerNumber, largerNumber, remainder = largerNumber % smallerNumber) => { + if (remainder === 0) { + return smallerNumber; + } + + return solution(remainder, smallerNumber); }; test('최대 공약수를 반환한다', () => { diff --git a/problem-6/problem-6.test.js b/problem-6/problem-6.test.js index 059e2b8..c36f19e 100644 --- a/problem-6/problem-6.test.js +++ b/problem-6/problem-6.test.js @@ -1,4 +1,47 @@ -const solution = (n) => { +// const solution = (n) => { +// if (n < 0) { +// return 0; +// } +// +// if (n === 0 || n === 1) { +// return 1; +// } +// +// return solution(n - 3) + solution(n - 2) + solution(n - 1); +// }; + +// 하향식 다이내믹 프로그래밍 (메모이제이션) + +// const solution = (n, memo = []) => { +// if (n < 0) { +// return 0; +// } +// if (n === 0 || n === 1) { +// return 1; +// } +// +// if (!memo[n]) { +// memo[n] = solution(n - 3, memo) + solution(n - 2, memo) + solution(n - 1, memo); +// } +// +// return memo[n]; +// }; + +// 상향식 다이내믹 프로그래밍 +const solution = (n, current = 2, a = 0, b = 1, c = 1) => { + if (n < 0) { + return 0; + } + + if (n === 0 || n === 1) { + return 1; + } + + if (n === current) { + return a + b + c; + } + + return solution(n, current + 1, b, c, a + b + c); }; test('계단에 오를 수 있는 가지 수를 반환한다', () => {