2차 공부/알고리즘

소수 만들기

공대탈출 2024. 6. 12. 15:29

 

입력되는 숫자의 배열 중 세가지 숫자를 더하여 해당 수가 소수인 경우를 모두 더해 리턴하는 문제이다.

 

처음 문제를 봤을 때 세가지 수를 더했을 때 같은 수가 있으면 안된다는 생각으로

3중 반복문을 사용하여 모든 가지수의 합을 배열화시키고, new Set()을 사용하여 중복된 수를 제거한 뒤

중복수가 제거된 배열을 소수판별하여 리턴하는 형식으로 작성했다. 코드는 다음과 같다.

 

처음 작성한 코드

function solution(nums) {
    var answer = 0;
    let sumNums = [];
    
    for (let i=0; i<nums.length-2; i++) {
        for (let j=i+1; j<nums.length-1; j++) {
            for (let k=j+1; k<nums.length; k++) {
                sumNums.push(nums[i]+nums[j]+nums[k])
            }
        }
    }
    
    let set = new Set(sumNums)
    let primeNums = Array.from(set)
    
    for (let l=0; l<primeNums.length; l++) {
        let flag = true;
        for (let m=2; m<primeNums[l]/2; m++) {
            if (primeNums[l]%m === 0) {
                flag = false
                break;
            }
        }
        if (flag) {
            answer++
        }
    }
    return answer
}

하지만 문제에는 중복된 수에대한 예외가 없었다. 단순히 '서로 다른 세가지 수를 더해 나온 수가 소수인지'가 제일 중요한 것이었기 때문에 테스트코드는 잘 작동하였으나, 코드제출에서 많은 실패를 받아 다시 작성하게 되었다.

 

 

 

두번째로 작성한 코드

function isPrimeNum(num) {
    if (num%2===0) return false;
    for (let i = 3; i<=Math.sqrt(num); i+=2) {
        if (num%i === 0) return false
    }
    return true;
}

function solution(nums) {
    var answer = 0;
    
    for (let i=0; i<nums.length-2; i++) {
        for (let j=i+1; j<nums.length-1; j++) {
            for (let k=j+1; k<nums.length; k++) {
                let sum = nums[i]+nums[j]+nums[k]
                if (isPrimeNum(sum)) {
                    answer++
                }
            }
        }
    }
    
    return answer
}

 

처음 풀이가 실패하고 문제부터 다시 보았다. 들어오는 배열에는 중복된 수가 없는 것과 세 수를 더했을 때 중복된 수에 대한 이야기가 없는 점을 이해하였고, 다시 작성하였다.

 

먼저 소수판별하는 함수를 먼저 만들어 두었다.

숫자가 함수로 들어오면 짝수인지 먼저 판별한다. 짝수이라면 false를 리턴한다.

1은 소수가 아니고, 2는 짝수이지만 소수이다. 하지만 문제에서 주어지는 배열 속 숫자들은 1부터 1000까지이고, 세가지 수를 더해 만든 숫자에 대해 소수를 판별하는 것이므로 세가지 수의 최소값은 6이다.

따라서 1과 2에대한 예외처리는 해두지 않았다.

 

다시 코드로 돌아가서, 소수 판별하는 부분에서 2로 나눠지는 것은 짝수이므로 필요가없다. 그러므로 판별문의 반복문을 i=3부터 시작하고, 제곱근까지 증가시키며, 홀수로만 판별하도록 하였다.

반복문 내에서 특정 i로 나눠진다면 바로 false를 리턴한다.

만약 반복문이 끝날때까지 나눠지지 않는다면 true를 리턴한다.

 

그리고 제출코드에서 배열의 합을 구하기 위해 3중 중첩문을 활용하고 각 i, j, k가 이전 중첩문의 인자보다 1만큼 크게하여 중복된 수를 더하지 않도록 하였다.

직관적으로 보이도록 sum변수를 선언해주었고, 미리 작성해두었던 소수판별함수에 넣어 true를 리턴하면 조건문이 실행되어 answer+1을 하도록 작성하였다.

'2차 공부 > 알고리즘' 카테고리의 다른 글

옹알이(2)  (0) 2024.06.17
24.06.13 기사단원의 무기  (0) 2024.06.13
카드 뭉치  (0) 2024.06.10
콜라문제  (0) 2024.06.05
시저암호  (1) 2024.06.04