컴퓨터의 빠른 계산 능력을 이용해 가능한 모든 경우의 수를 찾아서 답을 찾는 방법. '무식하게 푼다'는 의미로 Brute-Force라고 불리기도 한다.
고대 그리스 수학자 에라토스테네스가 만들어 낸 소수를 찾는 방법.
O(Nlog(logN))
의 시간 복잡도를 가진다.
def prime_list(n):
# 에라토스테네스의 체 초기화: n개 요소에 True 설정(소수로 간주)
sieve = [True] * n
# n의 최대 약수가 sqrt(n) 이하이므로 i=sqrt(n)까지 검사
m = int(n ** 0.5)
for i in range(2, m + 1):
if sieve[i] == True: # i가 소수인 경우
for j in range(i+i, n, i): # i이후 i의 배수들을 False 판정
sieve[j] = False
# 소수 목록 산출
return [i for i in range(2, n) if sieve[i] == True]
def prime_list(n):
prime = [True] * (n + 1)
prime[0] = prime[1] = False
for i in range(2, int(n ** 0.5) + 1):
if prime[i]:
for j in range(i*i, len(prime), i):
prime[j] = False
return prime
한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.
각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.
numbers | return |
---|---|
"17" | 3 |
"011" | 2 |
흩어진 종이 조각을 조합해서 만들 수 있는 수 중 소수의 개수를 구하는 문제이다.
제한 조건으로 주어진 numbers의 길이가 7이하이기 때문에 시간 복잡도를 크게 고려할 필요가 없어 비교적 쉽게 풀 수 있는 문제였다. 하지만, 풀이하는 과정에서 라이브러리 의존도가 높았기 때문에 라이브러리를 사용하지 않고 구현하는 것도 연습이 필요할 것 같다.
완전 탐색 문제이기때문에 처음 접근은 종이 조각을 통해 만들 수 있는 모든 수를 구한 후 에라토스테네스의 체를 사용하여 소수를 판별하고자 했다. 풀이 과정은 다음과 같다.
- 종이 조각으로 만들 수 있는 모든 수 구하기 =>
permutations
라이브러리 활용- 앞서 구한 수 중 중복을 제거하기 =>
set
활용- 소수 판별 => 에라토스테네스의 체
permutations
를 사용하여numbers
를 가지고 만들 수 있는 모든 수를 구한다.- 위의 결과값을
join
을 활용하여 하나의 문자열로 만든다.- 각각의 문자열들을
int
형으로map
해준다.- 중복을 제거하기 위해 위의 결과값을
set
에 넣어준다.
set
추가 방식으로는 update
or |
or union
이 있다.map
은 리스트의 요소를 지정된 함수로 처리해주는 함수이다.from itertools import permutations
def solution(numbers):
numbers = list(numbers)
number_set = set()
# 가능한 모든 경우의 수 (순열) => set 사용해서 중복 제거
for i in range(len(numbers)):
number_set |= set(map(int, map(''.join, permutations(numbers, i+1))))
- 에라토스테네스의 체를 사용하여
number_set
의 최댓값까지 소수 판별 리스트를 만든다.number_set
을 순회하면서 해당number
가 소수인 경우answer
의 값을 1 증가 시킨다.
# 에라토스테네스의 체
def prime_list(n):
prime = [True] * (n + 1)
prime[0] = prime[1] = False
for i in range(2, int(n ** 0.5) + 1):
if prime[i]:
for j in range(i*i, len(prime), i):
prime[j] = False
return prime
# 에라토스테네스의 체로 소수 판별 리스트 생성
prime = prime_list(max(number_set))
# 소수 판별
answer = 0
for number in number_set:
if prime[number]:
answer += 1
return answer
from itertools import permutations
# 에라토스테네스의 체
def prime_list(n):
prime = [True] * (n + 1)
prime[0] = prime[1] = False
for i in range(2, int(n ** 0.5) + 1):
if prime[i]:
for j in range(i*i, len(prime), i):
prime[j] = False
return prime
def solution(numbers):
numbers = list(numbers)
number_set = set()
# 가능한 모든 경우의 수 (순열) => set 사용해서 중복 제거
for i in range(len(numbers)):
number_set |= set(map(int, map(''.join, permutations(numbers, i+1))))
# 에라토스테네스의 체로 소수 판별 리스트 생성
prime = prime_list(max(number_set))
# 소수 판별
answer = 0
for number in number_set:
if prime[number]:
answer += 1
return answer
앞의 방식과 기본적인 부분은 동일하지만 에라토스테네스의 체를 이용할 때 별도의 리스트를 생성하지 않고, set
을 활용하여 소수가 아닌 수를 제거하는 방식이다.
시간이나 메모리 측면에서 더 효율적이지 않을까 기대했는데, 실제로 실행 결과를 보니 위의 방식보다 오히려 효율이 안 좋아졌다. 아마 반복문에서set
을 사용한 것 때문에 그런 것 같다고 추측만 해보았다..(실제로 그런지는 잘 모르겠다..)
number_set
에서 0~1까지 제거한다.- 2부터 √n까지 반복하며 소수가 아닌 수들을 제거한다.
number_set
의 길이를 반환한다.
n = max(number_set)
# 0~1 제거
number_set -= set(range(0, 2))
for i in range(2, int(n ** 0.5) + 1):
# 소수 아닌 수 제거
number_set -= set(range(i*i, n+1, i))
return len(number_set)
from itertools import permutations
def solution(numbers):
numbers = list(numbers)
number_set = set()
# 가능한 모든 경우의 수 (순열) => set 사용해서 중복 제거
for i in range(len(numbers)):
number_set |= set(map(int, map(''.join, permutations(numbers, i+1))))
n = max(number_set)
# 0~1 제거
number_set -= set(range(0, 2))
for i in range(2, int(n ** 0.5) + 1):
# 소수 아닌 수 제거
number_set -= set(range(i*i, n+1, i))
return len(number_set)
from itertools import permutations
def prime_list(n):
prime = [True] * (n + 1)
prime[0] = prime[1] = False
for i in range(2, int(n ** 0.5) + 1):
if prime[i]:
for j in range(i*i, len(prime), i):
prime[j] = False
return prime
def solution(numbers):
numbers = list(numbers)
number_set = set()
for i in range(len(numbers)):
number_set |= set(map(int, map(''.join, permutations(numbers, i+1))))
prime = prime_list(max(number_set))
answer = 0
for number in number_set:
if prime[number]:
answer += 1
return answer
permutations
set
과 map