“ 당신이 6개월 이상 한 번도 보지 않은 코드는 다른 사람이 다시 만드는 게 훨씬 더 나을 수 있다. ”
코딩테스트 입문 Day 22 dp, 수학, 조건문, 배열
출처 : https://programmers.co.kr/
저주의 숫자 3
문제
3x 마을 사람들은 3을 저주의 숫자라고 생각하기 때문에 3의 배수와 숫자 3을 사용하지 않습니다. 3x 마을 사람들의 숫자는 다음과 같습니다.
10진법 | 3x 마을에서 쓰는 숫자 | 10진법 | 3x 마을에서 쓰는 숫자 |
1 | 1 | 6 | 8 |
2 | 2 | 7 | 10 |
3 | 4 | 8 | 11 |
4 | 5 | 9 | 14 |
5 | 7 | 10 | 16 |
정수 n이 매개변수로 주어질 때, n을 3x 마을에서 사용하는 숫자로 바꿔 return하도록 solution 함수를 완성해주세요.
제한사항
- 1 ≤ n ≤ 100
입출력 예
n | result |
15 | 25 |
40 | 76 |
입출력 예 설명
입출력 예 #1
- 15를 3x 마을의 숫자로 변환하면 25입니다.
입출력 예 #2
- 40을 3x 마을의 숫자로 변환하면 76입니다.
solution.js
function solution(n) {
let arr = [];
let num = 0;
while (arr.length !== n && ++num) if (num%3!==0 && !(''+num).includes('3')) arr.push(num);
return arr.pop();
}
- 먼저 빈 배열 arr을 선언합니다.
- 변수 num을 0으로 초기화합니다.
- arr의 길이가 n과 같지 않을 때까지 반복합니다.
- 반복문에서 num을 1씩 증가시킵니다.
- 만약 num이 3의 배수가 아니고, 문자열로 변환한 후에 '3'을 포함하지 않는다면, 조건이 참이 되어 arr에 num을 추가합니다.
- 반복문이 종료되면 arr의 마지막 요소를 반환합니다.
평행
문제
점 네 개의 좌표를 담은 이차원 배열 dots가 다음과 같이 매개변수로 주어집니다.
- [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.
제한사항
- dots의 길이 = 4
- dots의 원소는 [x, y] 형태이며 x, y는 정수입니다.
- 0 ≤ x, y ≤ 100
- 서로 다른 두개 이상의 점이 겹치는 경우는 없습니다.
- 두 직선이 겹치는 경우(일치하는 경우)에도 1을 return 해주세요.
- 임의의 두 점을 이은 직선이 x축 또는 y축과 평행한 경우는 주어지지 않습니다.
입출력 예
dots | result |
[[1, 4], [9, 2], [3, 8], [11, 6]] | 1 |
[[3, 5], [4, 1], [2, 4], [5, 10]] | 0 |
입출력 예 설명
입출력 예 #1
- 점 [1, 4], [3, 8]을 잇고 [9, 2], [11, 6]를 이으면 두 선분은 평행합니다.
입출력 예 #2
- 점을 어떻게 연결해도 평행하지 않습니다.
solution.js
function solution(dots) {
const [p1, p2, p3, p4] = dots;
const slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0]);
const slope2 = (p3[1] - p2[1]) / (p3[0] - p2[0]);
const parallel1 = slope1 === (p4[1] - p3[1]) / (p4[0] - p3[0]);
const parallel2 = slope1 === (p4[1] - p2[1]) / (p4[0] - p2[0]);
const parallel3 = slope2 === (p4[1] - p1[1]) / (p4[0] - p1[0]);
if (parallel1 || parallel2 || parallel3) {
return 1;
} else {
return 0;
}
}
- 주어진 4개의 점을 p1, p2, p3, p4로 분해하여 변수에 할당합니다.
- 두 개의 점으로 만들어지는 선분의 기울기를 계산합니다. 이를 위해 slope1은 p1과 p2의 기울기를, slope2는 p2와 p3의 기울기를 계산합니다.
- 각 점을 기준으로 다른 두 개의 점과의 기울기를 계산하여 평행 여부를 확인합니다. 총 3개의 변수 parallel1, parallel2, parallel3를 계산합니다.
- parallel1, parallel2, parallel3 중 하나라도 true인 경우, 즉 어느 한 선분이 다른 선분과 평행한 경우 1을 반환합니다.
- 위의 조건이 모두 false인 경우, 즉 세 개의 선분이 모두 평행하지 않은 경우 0을 반환합니다.
겹치는 선분의 길이
문제
선분 3개가 평행하게 놓여 있습니다. 세 선분의 시작과 끝 좌표가 [[start, end], [start, end], [start, end]] 형태로 들어있는 2차원 배열 lines가 매개변수로 주어질 때, 두 개 이상의 선분이 겹치는 부분의 길이를 return 하도록 solution 함수를 완성해보세요.
lines가 [[0, 2], [-3, -1], [-2, 1]]일 때 그림으로 나타내면 다음과 같습니다.
선분이 두 개 이상 겹친 곳은 [-2, -1], [0, 1]로 길이 2만큼 겹쳐있습니다.
제한사항
- lines의 길이 = 3
- lines의 원소의 길이 = 2
- 모든 선분은 길이가 1 이상입니다.
- lines의 원소는 [a, b] 형태이며, a, b는 각각 선분의 양 끝점 입니다.
- -100 ≤ a < b ≤ 100
입출력 예
lines | result |
[[0, 1], [2, 5], [3, 9]] | 2 |
[[-1, 1], [1, 3], [3, 9]] | 0 |
[[0, 5], [3, 9], [1, 10]] | 8 |
입출력 예 설명
입출력 예 #1
- 두 번째, 세 번째 선분 [2, 5], [3, 9]가 [3, 5] 구간에 겹쳐있으므로 2를 return 합니다.
입출력 예 #2
- 겹친 선분이 없으므로 0을 return 합니다.
입출력 예 #3
- 첫 번째와 두 번째 선분이 [3, 5] 구간에서 겹칩니다.
- 첫 번째와 세 번째 선분 [1, 5] 구간에서 겹칩니다.
- 두 번째와 세 번째 선분 [3, 9] 구간에서 겹칩니다.
- 따라서 [1, 9] 구간에 두 개 이상의 선분이 겹쳐있으므로, 8을 return 합니다.
solution.js
function solution(lines) {
let line = new Array(200).fill(0);
lines.forEach(([a, b]) => {
for(; a < b; a++) line[a+100]++;
});
return line.reduce((a, c) => c > 1 ? a + 1 : a, 0)
}
- 길이가 200이고 모든 요소가 0인 배열 line을 생성합니다.
- lines 배열을 forEach 메서드를 사용하여 각 선분을 순회합니다.
- 각 선분을 [a, b] 형태로 받아와서, a부터 b까지의 구간을 반복합니다.
- 구간 내의 인덱스에 해당하는 line 배열의 요소 값을 1씩 증가시킵니다. 인덱스 a+100은 -100부터 99까지의 범위를 나타냅니다.
- 모든 선분에 대한 처리가 완료되면, line 배열을 reduce 메서드를 사용하여 요소를 순회합니다.
- 각 요소 c가 1보다 큰 경우, 즉 겹치는 구간이 있다면 a에 1을 더하고 그렇지 않으면 그대로 유지합니다.
- reduce 메서드가 완료되면 최종 결과값 a를 반환합니다.
유한소수 판별하기
문제
소수점 아래 숫자가 계속되지 않고 유한개인 소수를 유한소수라고 합니다. 분수를 소수로 고칠 때 유한소수로 나타낼 수 있는 분수인지 판별하려고 합니다. 유한소수가 되기 위한 분수의 조건은 다음과 같습니다.
- 기약분수로 나타내었을 때, 분모의 소인수가 2와 5만 존재해야 합니다.
두 정수 a와 b가 매개변수로 주어질 때, a/b가 유한소수이면 1을, 무한소수라면 2를 return하도록 solution 함수를 완성해주세요.
제한사항
- a, b는 정수
- 0 < a ≤ 1,000
- 0 < b ≤ 1,000
입출력 예
a | b | result |
7 | 20 | 1 |
11 | 22 | 1 |
12 | 21 | 2 |
입출력 예 설명
입출력 예 #1
- 분수 7/20은 기약분수 입니다. 분모 20의 소인수가 2, 5 이기 때문에 유한소수입니다. 따라서 1을 return합니다.
입출력 예 #2
- 분수 11/22는 기약분수로 나타내면 1/2 입니다. 분모 2는 소인수가 2 뿐이기 때문에 유한소수 입니다. 따라서 1을 return합니다.
입출력 예 #3
- 분수 12/21는 기약분수로 나타내면 4/7 입니다. 분모 7은 소인수가 7 이므로 무한소수입니다. 따라서 2를 return합니다.
Hint
- 분자와 분모의 최대공약수로 약분하면 기약분수를 만들 수 있습니다.
- 정수도 유한소수로 분류합니다.
solution.js
function solution(a, b) {
const gcd = getGCD(a, b);
const numerator = a / gcd;
const denominator = b / gcd;
if (isFiniteFraction(denominator)) {
return 1;
} else {
return 2;
}
}
function getGCD(a, b) {
if (b === 0) {
return a;
} else {
return getGCD(b, a % b);
}
}
function isFiniteFraction(num) {
while (num % 2 === 0) {
num /= 2;
}
while (num % 5 === 0) {
num /= 5;
}
return num === 1;
}
- getGCD 함수를 사용하여 a와 b의 최대공약수(gcd)를 계산합니다.
- gcd를 사용하여 기약분수로 만듭니다. numerator는 a를 gcd로 나눈 값이고, denominator는 b를 gcd로 나눈 값입니다.
- denominator의 소인수를 확인합니다. 이를 위해 isFiniteFraction 함수를 사용합니다.
- isFiniteFraction 함수에서는 num이 2로 나누어질 수 있는 동안 2로 나누고, 5로 나누어질 수 있는 동안 5로 나눕니다.
- num이 1이 되면 denominator는 2와 5를 소인수로 갖지 않으므로 유한한 소수입니다. 따라서 1을 반환합니다.
- 그렇지 않으면 denominator는 2와 5 이외의 다른 소인수를 가지므로 무한한 소수입니다. 따라서 2를 반환합니다.
이 함수의 목표는 입력된 분수 a/b가 유한한 소수인지 무한한 소수인지 판단하는 것입니다. 반환되는 값은 유한한 소수인 경우 1을, 무한한 소수인 경우 2를 나타냅니다.
예를 들어, a가 5이고 b가 2인 경우, 분수 5/2는 무한한 소수입니다. 따라서 solution(5, 2)를 호출하면 2가 반환됩니다.