연습장

Summer/Winter Coding(~2018) > 소수 만들기

anothel 2021. 11. 16. 19:06

문제 설명

주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하려고 합니다. 숫자들이 들어있는 배열 nums가 매개변수로 주어질 때, nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.
  • nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.

 

입출력 예

nums result
[1,2,3,4] 1
[1,2,7,6,4] 4

 

입출력 예 설명

입출력 예 #1
[1,2,4]를 이용해서 7을 만들 수 있습니다.

입출력 예 #2
[1,2,4]를 이용해서 7을 만들 수 있습니다.
[1,4,6]을 이용해서 11을 만들 수 있습니다.
[2,4,7]을 이용해서 13을 만들 수 있습니다.
[4,6,7]을 이용해서 17을 만들 수 있습니다.

 

Solution

#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;

bool isSosoo(int n) {
  bool result = true;
  for (int i = 2; i <= sqrt(n); i++) {
    if (n % i == 0) {
      result = false;
    }
  }
  return result;
}

int solution(vector<int> nums) {
  int answer = 0;
  sort(nums.begin(), nums.end());
  for (int i = 0; i < nums.size() - 2; i++)
    for (int j = i + 1; j < nums.size() - 1; j++)
      for (int k = j + 1; k < nums.size(); k++) {
        int sum = nums[i] + nums[j] + nums[k];
        if (isSosoo(sum)) answer++;
      }
  return answer;
}

 

이도연의 코드

#include <vector>
#include <algorithm>
using namespace std;
#define MAXSUM 3001
bool prime[3001]; //1000이하의 자연수이므로

//소수 구하기는 에라토스테네스의 방법을 사용한다
void CheckPrime(){
    fill(prime, prime+MAXSUM, 1);
    for(int i = 2;i < MAXSUM;i++){
        if(prime[i] == 0) continue;
        for(int j = i+i;j <= MAXSUM;j += i)
            prime[j] = 0;
    }
}
/*
void Combination(vector<int> &nums, int pos, int r, int sum, int &answer){
    if(r == 0){ //3개를 다 선택함
        if(prime[sum]){
            answer++;
            return;
        }
    }
    if(pos == nums.size()) return; //끝까지 확인함

    Combination(nums, ++pos, r, sum, answer); //현재 숫자를 선택하지 않음
    sum += nums[pos-1]; //하나를 선택함
    Combination(nums, pos, --r, sum, answer);   
}
*/

void Combination(vector<int> nums, int &answer){
    int sum = 0;
    int s = nums.size();
    vector<int> per(s-3);
    for(int i = 0;i < 3;i++) per.push_back(1);

    do{
        sum = 0;
        for(int i = 0;i < per.size();i++)
            if(per[i] == 1) sum += nums[i];
        if(prime[sum]) answer++;
    }while(next_permutation(per.begin(), per.end()));
}


int solution(vector<int> nums) {
    int answer = 0; int pos = 0;
    int sum = 0; int r = 3;

    CheckPrime();
    Combination(nums, answer);
    return answer;
}

 

후기

여러 개의 숫자들 중 3개의 수를 골라야 했고, 그 수들은 중복이 되지 않아야 했다. 그 방법이 도저히 생각나지 않아서 조합을 구하는 코드를 검색해봤다. 조합이라 함은 수열에서 내가 원하는 몇 개의 수를 뽑아내는 것인데, 이 방법은 중복이 너무 많았다. 이번 카타는 실패작이라고 생각한다. 왜냐하면 소수 문제를 여러 번 풀었음에도 소수를 골라내는 방법이 익숙하지 않았고, 에라토 스테네의 체를 기억해내지 못했으며, 수열에서 중복 없이 3개의 수를 뽑아내지도 못했다. 다 못했다. 이번 판 실패.

 

(url: https://programmers.co.kr/learn/courses/30/lessons/12977, https://velog.io/@neity16/Programers-%EC%86%8C%EC%88%98-%EB%A7%8C%EB%93%A4%EA%B8%B0, https://ansohxxn.github.io/algorithm/combination/, 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)

 

728x90