배꼽파지 않도록 잘 개발해요

[프로그래머스] 입문 Day 11 수학, 반복문 (Javascript) 본문

코딩테스트/프로그래머스

[프로그래머스] 입문 Day 11 수학, 반복문 (Javascript)

꼽파 2023. 12. 21. 12:04


주사위의 개수

문제 설명

  • 머쓱이는 직육면체 모양의 상자를 하나 가지고 있는데 이 상자에 정육면체 모양의 주사위를 최대한 많이 채우고 싶습니다. 상자의 가로, 세로, 높이가 저장되어있는 배열 box와 주사위 모서리의 길이 정수 n이 매개변수로 주어졌을 때, 상자에 들어갈 수 있는 주사위의 최대 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • box의 길이는 3입니다.
  • box[0] = 상자의 가로 길이
  • box[1] = 상자의 세로 길이
  • box[2] = 상자의 높이 길이
  • 1 ≤ box의 원소 ≤ 100
  • 1 ≤ n ≤ 50
  • n ≤ box의 원소
  • 주사위는 상자와 평행하게 넣습니다.

입출력 예

box  n result
[1, 1, 1] 1 1
[10, 8, 6] 3 12

 

풀이 1

상자의 각 길이를 n으로 나눌 때 Math.floor메소드 활용

function solution(box, n) {
    // 상자의 각 길이를 n으로 나누어 몫을 구함
    var a = Math.floor(box[0] / n); // 가로 길이를 각 변을 n으로 나눈 몫
    var b = Math.floor(box[1] / n); // 세로 길이를 각 변을 n으로 나눈 몫
    var c = Math.floor(box[2] / n); // 높이 길이를 각 변을 n으로 나눈 몫
    
    // 나눈 몫들의 곱을 계산
    var answer = Math.floor(a * b * c);
    return answer;
}

 

풀이 2

구조분해 할당을 먼저 해준 후 계산

function solution(box, n) {
    let [width, length, height] = box;

    return Math.floor(width / n) * Math.floor(length / n) * Math.floor(height / n);

}

 

주의할 점

  • 구조분해 할당은 정말 깔끔하고 편리한 문법이지만 손에 익지 않아서 그런가 잘 안 쓰게 됨.

합성수 찾기

문제 설명

  • 약수의 개수가 세 개 이상인 수를 합성수라고 합니다. 자연수 n이 매개변수로 주어질 때 n이하의 합성수의 개수를 return하도록 solution 함수를 완성해주세요.

제한사항

  • 1 ≤ n ≤ 100

입출력 예

n result
10 5
15 8

 

풀이 1

나누어 떨어지는 수의 개수를 세는 함수로 합성수를 판별함

function solution(n) { 
    var answer = 0;
    // 합성수 : 1과 자기자신 외 1개 이상을 약수로 가져야 함
    // 2부터 n미만까지 수 중에서 n의 약수가 있으면 개수 추가
    
    // 합성수인지 판단해주는 함수
    function findComposite(number) {
        let count = 0;  // 반드시 함수 안에서 초기화 해야함
        for (let i = 1; i <= number; i++) {
            if (number % i == 0) {
                count += 1;
            }
        } 
        if (count >= 3) {
            return true;
        } else {
            return false;
        }
    }
    
    // 합성수의 개수 출력
    for (let i = 2; i <= n; i++) {
        if (findComposite(i) == true) {
            answer += 1;
        }
    }
    return answer;
}

 

풀이 2

에라토스테네스의 체
· 소수를 찾는 알고리즘
· 2부터 시작해서 소수의 배수가 되는 수를 지워나가는 방식으로 N이하의 소수를 찾는다.

function solution(n) { 
    // 에라토스테네스의 체로 소수를 구하기
    // 모든 원소를 1로 채워 넣음
    // 2부터 n까지 (n - 1)개 이지만 "인덱스 번호 = 숫자"를 위해 (n + 1)개 배열 생성 
    const arr = new Array(n + 1).fill(1);
    
    // 
    for (let i = 2; i <= n; i++) {
        for (let j = 2; i * j <= n; j++) {
                arr[i * j] = 0;
            }
        }
    // 배열 중 0의 개수만 출력
    return arr.filter((el) => el === 0).length;  // 8

 

https://ko.wikipedia.org/wiki/%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98_%EC%B2%B4

 

에라토스테네스의 체 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 에라토스테네스의 체 수학에서 에라토스테네스의 체는 소수를 찾는 방법이다. 고대 그리스 수학자 에라토스테네스가 발견하였다. 알고리즘[편집] 2부터 소수

ko.wikipedia.org

 

주의할 점

  • 풀이 2의 알고리즘를 활용하여 소수의 개수를 구하고 싶다면 배열의 길이 - 0의 개수 (소수의 개수) - 2 (0과 1 제외) 를 해야함.
  • 소수/합성수 판별 방법으로는 특정 수의 제곱근까지만 반복문으로 순회하여 나누어 떨어지는 수가 있는지 여부를 확인하는 것도 있음.

최댓값 만들기(1)

문제 설명

  • 정수 배열 numbers가 매개변수로 주어집니다. numbers의 원소 중 두 개를 곱해 만들 수 있는 최댓값을 return하도록 solution 함수를 완성해주세요.

제한사항

  • 0 ≤ numbers의 원소 ≤ 10,000
  • 2 ≤ numbers의 길이 ≤ 100

입출력 예

numbers result
[1, 2, 3, 4, 5] 20
[0, 31, 24, 10, 1, 9] 744

 

풀이 1

sort로 정렬하여 큰 수 x 두 번째 큰 수 곱하기

function solution(numbers) {
    // 두 수의 곱 중 최댓값은 가장 큰 수, 그 다음으로 큰 수를 곱했을 경우
    // 내림차순 정렬하여 인덱스 0, 인덱스 1번 수 두 개 곱하기
    
    numbers.sort((a, b) => b - a)
    
    return numbers[0] * numbers[1];
}

 

주의할 점

  • 위 풀이보다 더 좋은 풀이는 없는듯 싶음.

팩토리얼

문제 설명

  • i팩토리얼 (i!)은 1부터 i까지 정수의 곱을 의미합니다. 예를들어 5! = 5 * 4 * 3 * 2 * 1 = 120 입니다. 정수 n이 주어질 때 다음 조건을 만족하는 가장 큰 정수 i를 return 하도록 solution 함수를 완성해주세요.
  • i! ≤ n

제한사항

  • 0 < n ≤ 3,628,800

입출력 예

n result
3628800 10
7 3

 

풀이 1

for of문 활용

function solution(n) {
    
    var answer = 0;
    var factorial = 1;  // 누적곱 (팩토리얼)
    const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    
    for (num of arr) {
        factorial *= num;
        if (factorial <= n) {
            answer = num;
        }}    
    return answer;
}

 

위 문제의 제한사항에 3,628,800이므로 arr을 1부터 10까지의 배열로 선언함.

다소 하드코딩 되어 있어서 이를 일반화한 풀이 방법도 생각해보았음.

 

1부터 입력값 n까지의 길이를 가진 배열 생성

// 1) map으로 활용
const arr = new Array.fill().map( (_, index) => index + 1);

// 2) for문
const arr = [];
for (i = 0; i < n; i++) {
	arr.push(i + 1);
}

n까지의 모든 요소에 접근하므로 시간 복잡도는 O(n)으로 1번과 2번이 모두 같음.

 

참고

배열 생성할 때 fill 메소드에 아무것도 입력하지 않으면 undefined가 채워짐.

let n = 10;

let arr = new Array(n).fill()
console.log(arr)

/* 
[
  undefined, undefined,
  undefined, undefined,
  undefined, undefined,
  undefined, undefined,
  undefined, undefined
]
*/

 

풀이 2

for문에 변수를 2개 사용하여 간단하게 푸는 방법

function solution(n) {
    for(let i = 1, v = 1; true; v *= ++i) if(v > n) return --i;
}
function solution(n) {
// v가 n보다 크면 반복 종료
 for(let i = 1, v = 1; true; v *= ++i) {
    console.log(`i: ${i} v: ${v}, n: ${n}`)
        if (v > n) {
            return --i;
        }
    }
}

길이는 짧은데 꽤 신경써야할 부분이 많은 풀이이다.

v *=  ++i를 한 이유는 초기값이 v = 1, i = 1이라서 만약 i++을 하는 경우 v = 1인 경우가 두 번 발생함.

for문에 변수를 2개 사용한 풀이를 본 것이 처음이라 인상적이었음.

 

주의할 점

  • 반복문과 배열 메소드는 봐도 봐도 새로움!
728x90