소소한 블로그

[Greedy] 프로그래머스 42839번 소수찾기 본문

알고리즘/문제풀이

[Greedy] 프로그래머스 42839번 소수찾기

happy_ai 2021. 7. 1. 11:55

이번 문제는 Greedy 문제입니다. 

문제 출처: https://programmers.co.kr/learn/courses/30/lessons/42839

 

코딩테스트 연습 - 소수 찾기

한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다. 각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이

programmers.co.kr


두가지 풀이법이 있습니다. 첫번째는 일반적인 Greedy 풀이법이고 두번째는 에라토스테네스의 체를 이용한 풀이법입니다. 전공시간에 배운 적 있었는데 여기서 보니 반가웠습니다..ㅎ

첫번째 풀이는 특별한 점이 없으니 코드만 적어두고 두번째 풀이에 대해 살펴보겠습니다.

 

[첫번째 풀이]

from itertools import permutations
import math


def is_prime(number):
    if number == 1 or math.sqrt(number) == int(math.sqrt(number)):
        return False

    flag = True
    for d in range(2, int(math.sqrt(number)) + 1):
        if number % d == 0:
            flag = False
            break

    if flag:
        return True
    else:
        return False


def solution(numbers):
    answer = 0

    for len_digit in range(1, len(numbers) + 1):
        list_permutation = list(set(permutations(numbers, len_digit)))
        for permutation in list_permutation:
            if permutation[0] == '0':
                continue
            else:
                # 소수인지 판단
                if is_prime(int(''.join(permutation))):
                    answer += 1

    return answer

 


[두번째 풀이]

에라토스테네스의 체에 대해서는 아래 url을 참고하시기 바랍니다.

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

소수의 배수들을 모두 걸러내고 그 뒤 남은 수들을 소수로 정의하는 방식입니다.

 

이 방식을 코딩하면서 새로 알게된 파이썬 지식이 있습니다.

  1.  |= 연산
    이 연산은 집합(set)에서 유용하게 쓸 수 있습니다.
    '|'는 set의 관점에서 합집합 연산이며, '|='로 쓰게 되면 왼쪽 집합이 두 개의 합집합으로 새로 정의되게 됩니다.
    따라서 왼쪽 집합에 오른쪽 집합의 원소를 추가하고 싶을 때 활용할 수 있습니다.

  2. set 안에 range
    처음에는 for문으로 원소를 하나씩 추가해줬습니다. 하지만 range()를 활용하게 되면 for문을 쓰지 않고 한번에 여러 원소를 추가 가능합니다.

  3. list의 여러 원소들의 값을 동시에 같은 값으로 변경하고 싶을 때
    이때 주의점은 좌변 list는 인덱싱 형태로 접근해야하며,
    우변의 값은 하나의 값이 아닌 좌변의 list와 크기가 같은 배열로 값이 주어져야 합니다.
    (처음에는 우변을 'False'로 하여 에러가 났습니다.)

 

코드는 아래와 같습니다.

from itertools import permutations
import math


def solution(numbers):
    answer = 0

    set_number = set()
    for i in range(1, len(numbers) + 1):
        set_number |= set(map(int, map(''.join, permutations(numbers, i))))
    set_number -= {0, 1}
    max_number = max(set_number)

    list_prime = [True] * (max_number + 1)
    for prime in range(2, int(math.sqrt(max_number)) + 1):
        if list_prime[prime]:
            set_number -= set(range(prime * 2, max_number + 1, prime))
            list_prime[prime * 2:max_number + 1:prime] = [False] * len(list_prime[prime * 2:max_number + 1:prime])

    answer = len(set_number)
    return answer