웹 프론트엔드 공부를 계속하면서 다양한 라이브러리를 써보며 익숙해지는 연습을 계속하고 있다. 그런 와중에 정작 웹 개발의 기초가 되는 자바스크립트에 대한 공부를 소홀히 한 것 같아서 아쉬움을 계속 느끼고 있었다.
문법을 익히기에는 알고리즘 문제를 푸는 것이 가장 좋은 방법인 것 같아서 자바스크립트로 알고리즘 문제들을 풀기로 했다. 지금까지는 알고리즘 문제를 백준에서 풀었지만 백준에서 자바스크립트를 쓸려면 조금 복잡해서 이번엔 자바스크립트를 잘 지원해주는 프로그래머스에서 문제를 풀기로 했다.
프로그래머스는 코딩 테스트 문제를 입문 문제, 기초 문제, 모든 문제로 카테고리화 했는데, 일단은 입문 문제를 풀다가 넘어가도 되겠다싶으면 기초 문제로 넘어갈 것이다. 그리고 하루에 4문제씩 일일 도전 과제 문제들을 카테고리별로 제공해줘서이 루트를 그대로 따라가보려 한다.
프로그래머스는 ‘다른 사람의 풀이’ 페이지를 제공해서 다른 사람이 어떻게 풀었는지 쉽게 확인할 수 있다. 밑의 작성된 풀이 중에서 ‘다른 사람의 풀이’에서 본 내 코드보다 나은, 배울 점이 있는 코드들도 많다.
Day 1
두 수의 곱
https://school.programmers.co.kr/learn/courses/30/lessons/120804
const solution = (num1, num2) => num1 * num2
이렇게 화살표 함수를 통한 간단한 풀이도 가능하다.
몫 구하기
https://school.programmers.co.kr/learn/courses/30/lessons/120805
const solution = (num1, num2) => Math.floor(num1 / num2)
Math.floor(버림)을 쓰거나 parseInt를 쓴다.
Day 2
두 수의 나눗셈
https://school.programmers.co.kr/learn/courses/30/lessons/120806
function solution(num1, num2) {
return Math.trunc(num1 / num2 * 1000);
}
Math.trunc()는 소수점 이하는 다 버린다. ex) Math.trunc(23.3) = 23, Math.trunc(-23.3) = -23
Math.floor()는 소수점을 내림한다. ex) Math.floor(23.3) = 23, Math.floor(-23.3) = -24가 된다. 음수인 경우도 생각해서 소수점을 이하 수를 없애고 싶을때는 Math.trunc를 사용하는 것이 좋다.
숫자 비교하기
https://school.programmers.co.kr/learn/courses/30/lessons/120807
function solution(num1, num2) {
var answer = num1 === num2 ? 1 : -1;
return answer;
}
삼항 연산자를 활용하여 쉽게 풀 수 있다.
분수의 덧셈
https://school.programmers.co.kr/learn/courses/30/lessons/120808
꽤 시간이 걸린, 애를 먹은 문제이다.
이 풀이는 틀린 풀이이다.
// 최대공약수를 구하는 함수(유클리드 호제법 사용)
function gcd(a, b) {
return b === 0 ? a : gcd(b, a % b);
}
function solution(numer1, denom1, numer2, denom2) {
let sum = (numer1 / denom1) + (numer2 / denom2); // 분수끼리 더하기
let sum_to_compare = sum; // 더한 값을 sum_to_compare 변수에 옮기기
let count = 0; // 더한 값(분수)의 분모의 0의 자릿수
// 먼저 분수로 나타내기
while (sum_to_compare < 1) {
sum_to_compare = sum_to_compare * 10; // 소수가 1 이상이 될 때 까지 곱해주고
count++; // 그 횟수를 센다.
}
let numer_temp = sum_to_compare;
let denom_temp = Math.pow(10, count);
// 이제 기약분수로 만들어야 한다.
// 분모와 분자의 최대공약수를 구해서 각각을 최대공약수로 나눠주자.
let gcd_denom = gcd(numer_temp, denom_temp);
let answer = [];
answer[0] = numer_temp / gcd_denom;
answer[1] = denom_temp / gcd_denom;
return answer;
}
입력값 〉 | 9, 2, 1, 3 |
기댓값 〉 | [29, 6] |
실행 결과 〉 | 실행한 결괏값 [5441849549739349,1125899906842624]이 기댓값 [29,6]과 다릅니다. |
이렇게 에러가 난다.
(문제는 JavaScript에서 부동 소수점 연산으로 인한 정밀도 손실로 인해 발생합니다. 부동 소수점 숫자는 컴퓨터에서 정확하게 표현하기 어렵기 때문에 이런 문제가 발생할 수 있습니다. 라고 chatGPT는 설명했다.)
정답 풀이
부동 소수점 연산을 피하기 위해 분수들을 곱하는 방식을 사용했더니 정답이 나왔다.
// 최대공약수를 구하는 함수(유클리드 호제법 사용)
function gcd(a, b) {
return b === 0 ? a : gcd(b, a % b);
}
function solution(numer1, denom1, numer2, denom2) {
// 분모끼리 곱한다.
let denom_times = denom1 * denom2;
// 분자1 * 분모2
let numer_temp1 = numer1 * denom2;
// 분자2 * 분모1
let numer_temp2 = numer2 * denom1;
// 새로 만들어진 분자들을 더해준다.
let numer_sum = numer_temp1 + numer_temp2;
// 최대공약수를 구해준다.
let gcd_num = gcd(numer_sum, denom_times);
let answer = [];
answer[0] = numer_sum / gcd_num;
answer[1] = denom_times / gcd_num;
return answer;
}
배열 두 배 만들기
https://school.programmers.co.kr/learn/courses/30/lessons/120809
1. reduce를 사용한다.
function solution(numbers) {
return numbers.reduce((a, b) => [...a, b * 2], []);
}
JavaScript에서 reduce의 역할 (by chatGPT)
JavaScript의 reduce 메서드는 배열의 각 요소에 대해 주어진 콜백 함수를 실행하고 하나의 누적된 결과를 반환하는 배열 메서드입니다. reduce는 배열을 단일 값으로 줄이는 데 사용되며, 합계, 평균, 최댓값, 최솟값 등을 계산하는 데 유용합니다.
reduce 메서드는 다음과 같은 구조를 가집니다:
array.reduce(callback(accumulator, currentValue, currentIndex, array) {
// 콜백 함수의 로직
}, initialValue);
- accumulator: 누적된 결과 또는 중간 결과를 저장하는 변수입니다.
- currentValue: 현재 처리 중인 배열 요소의 값입니다.
- currentIndex (선택 사항): 현재 처리 중인 배열 요소의 인덱스입니다.
- array (선택 사항): reduce를 호출한 배열 자체입니다.
- initialValue (선택 사항): 누적 변수 accumulator의 초기값으로 사용됩니다. 생략할 경우 배열의 첫 번째 요소가 초기값이 됩니다.
간단한 예제로 reduce를 살펴보겠습니다. 아래 코드는 배열의 모든 요소의 합을 계산하는 예제입니다:
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0);
console.log(sum); // 출력: 15
이 예제에서는 초기값으로 0을 사용하고, 각 요소를 더하여 누적된 결과를 반환합니다. reduce를 사용하면 반복문 없이도 배열의 모든 요소를 처리하면서 누적된 값을 계산할 수 있습니다.
2. map을 사용한다.
const solution = (numbers) => numbers.map((number) => number * 2)
JavaScript에서 Map의 역할 (by ChatGPT)
JavaScript의 배열 객체에서 제공하는 map() 메서드는 배열의 각 요소에 대해 주어진 함수를 호출하고, 그 함수의 반환값으로 새로운 배열을 생성합니다. 기존 배열은 변경되지 않습니다.
map() 메서드의 구조는 다음과 같습니다:
const newArray = array.map((currentValue, index, array) => {
// currentValue: 현재 요소의 값
// index: 현재 요소의 인덱스
// array: map을 호출한 배열 자체
// 반환값은 새로운 배열의 해당 인덱스에 들어갈 값
});
간단한 예시를 살펴보겠습니다. 아래 코드는 배열의 각 요소에 대해 제곱한 새로운 배열을 생성합니다:
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map((num) => {
return num ** 2;
});
console.log(squaredNumbers); // 출력: [1, 4, 9, 16, 25]
이 코드에서 map()은 각 숫자를 제곱하여 새로운 배열을 생성합니다. map()은 새로운 배열을 반환하며, 기존 배열은 변경되지 않습니다. 이러한 특성 덕분에 함수형 프로그래밍에서 매우 유용하게 사용됩니다.
Day 3
나머지 구하기
https://school.programmers.co.kr/learn/courses/30/lessons/120810
const solution = (num1, num2) => num1 % num2
중앙값 구하기
https://school.programmers.co.kr/learn/courses/30/lessons/120811
틀린 풀이
function solution(array) {
let sortedArray = array.sort();
let answer = sortedArray[array.length / 2];
return answer;
}
정답 풀이
function solution(array) {
let sortedArray = array.slice().sort((a, b) => a - b);
let answer = sortedArray[Math.floor(array.length / 2)];
return answer;
}
sort에 (a,b) ⇒ a-b)를 넣는 것이 중요하다.
이유 (by chatGPT)
이러한 비교 함수가 중요한 이유는 sort() 메서드가 기본적으로 문자열 기반으로 정렬을 수행하기 때문입니다. 문자열 기반으로 정렬하면 예상치 못한 결과가 나올 수 있습니다. 예를 들어, [10, 2, 5, 1] 배열을 기본적으로 정렬하면 **[1, 10, 2, 5]**와 같은 결과가 나올 수 있습니다.
**(a, b) => a - b**를 사용하면 숫자를 기반으로 정렬하므로 원하는 오름차순 정렬이 이루어집니다. 만약 내림차순으로 정렬하고 싶다면 **(a, b) => b - a**와 같이 사용하면 됩니다.
이런 방식의 비교 함수를 사용하지 않으면 정렬 결과가 원하는 대로 나오지 않을 수 있습니다. 비교 함수를 제공하지 않으면 sort() 메서드는 각 요소를 문자열로 변환하여 정렬하게 되기 때문입니다.
최빈값 구하기
https://school.programmers.co.kr/learn/courses/30/lessons/120812
function solution(array) {
// 배열의 최대 길이로 초기화된 array2 배열 생성
// 각 인덱스는 해당 숫자의 빈도수를 나타냄
var array2 = new Array(1001).fill(0);
// 배열을 순회하며 각 숫자의 빈도수를 array2에 기록
for(var i = 0; i < array.length; i++) {
array2[array[i]]++;
}
// 최대 빈도수와 해당 숫자를 저장하는 변수 초기화
var max = 0;
var max_i = 0;
// array2를 순회하며 최빈값을 찾음
for(var i = 0; i < array2.length; i++) {
if(array2[i] > max) {
max = array2[i];
max_i = i;
}
// 최빈값이 중복되는 경우 max_i를 -1로 설정
else if(array2[i] !== 0 && array2[i] === max) {
max_i = -1;
}
}
// 중복된 최빈값이 있는 경우 -1 반환, 아닌 경우 최빈값 반환
if(max_i === -1) {
return -1;
}
else {
return max_i;
}
}
짝수는 싫어요
https://school.programmers.co.kr/learn/courses/30/lessons/120813
function solution(n) {
// 반환할 배열 초기화
var answer = [];
// 배열에 값을 채울 인덱스 초기화
var array_num = 0;
// 1부터 n까지의 홀수를 배열에 저장
for(var i = 1; i <= n; i = i + 2) {
answer[array_num++] = i;
}
// 결과 배열 반환
return answer;
}
'Programmers(JavaScript)' 카테고리의 다른 글
[프로그래머스 자바스크립트] '폰켓몬' 풀어보기 (2) | 2024.07.16 |
---|---|
[프로그래머스 자바스크립트] 코딩테스트 입문 Day 9,10 풀어보기 (0) | 2024.02.14 |
[프로그래머스 자바스크립트] 코딩테스트 입문 Day 8 풀어보기 (0) | 2024.02.13 |
[프로그래머스 자바스크립트] 코딩테스트 입문 Day 6,7 풀어보기 (1) | 2024.02.13 |
[프로그래머스 자바스크립트] 코딩테스트 입문 Day 4,5 풀어보기 (1) | 2024.02.10 |