본문 바로가기
Programing/프로그래머스 오답노트

[프로그래머스] k진수에서 소수 개수 구하기 - ( sqrt(n)+1까지 조사 )

by yooom 2023. 9. 27.
문제 설명

 

양의 정수 n이 주어집니다. 이 숫자를 k진수로 바꿨을 때, 변환된 수 안에 아래 조건에 맞는 소수(Prime number)가 몇 개인지 알아보려 합니다.
0P0처럼 소수 양쪽에 0이 있는 경우P0처럼 소수 오른쪽에만 0이 있고 왼쪽에는 아무것도 없는 경우0P처럼 소수 왼쪽에만 0이 있고 오른쪽에는 아무것도 없는 경우P처럼 소수 양쪽에 아무것도 없는 경우단, P는 각 자릿수에 0을 포함하지 않는 소수입니다.예를 들어, 101은 P가 될 수 없습니다.
예를 들어, 437674을 3진수로 바꾸면 211020101011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 왼쪽부터 순서대로 211, 2, 11이 있으며, 총 3개입니다. (211, 2, 11을 k진법으로 보았을 때가 아닌, 10진법으로 보았을 때 소수여야 한다는 점에 주의합니다.) 211은 P0 형태에서 찾을 수 있으며, 2는 0P0에서, 11은 0P에서 찾을 수 있습니다.
정수 n과 k가 매개변수로 주어집니다. n을 k진수로 바꿨을 때, 변환된 수 안에서 찾을 수 있는 위 조건에 맞는 소수의 개수를 return 하도록 solution 함수를 완성해 주세요.

 

풀이
def prime(n):
    arr =[]
    num = set(range(2,n+1))
    for i in range(2,n+1):
        num -= set(range(i*2,n+1,i))
    num = list(map(str,num))   # 소수를 찾은 뒤 str 변환
    arr = [i for i in num if '0' not in i]  # 0이 들어가는 소수는 제외 ex) 101, 103
    return arr

def changer(n, k):
    num=''
    arr, arr_ = [],[]
    while n>0:   # k 진수로 변환
        num = str(n%k) + num 
        n = n//k
    arr = num.split('0') # '0'으로 구분, ex) 110011 -> ['11','','11']
    arr_ = [i for i in arr if i !='']  # '' 를 제외
    return arr_  # 110011 -> ['11','','11'] -> ['11','11']

def solution(n, k):
    chg_num = []
    prime_arr=[]
    cnt = 0
    chg_num = changer(n,k)   # k진수 변환 후, '0'으로 끊은 수 반환
    max_num = max(list(map(int,chg_num))) # 문자열 리스트 -> int 변환, 가장 큰 수 반환
    prime_arr = prime(max_num)  # 가장 큰 수까지 0없는 소수 반환

    for i in chg_num:
        if i in prime_arr: # 반환 된 수에서 소수 리스트 중 있는지 확인
            cnt +=1
    
    answer = cnt
    return answer

마지막 과정에서 소수 리스트에 있는지 비교해야하는 과정이 길게 걸릴 것 같으니, 소수 리스트를 dict로 바꿔보자.

max() 도 쓰지 않아야겠다.

 

 

def prime(n):
    arr =[]
    num = set(range(2,n+1))
    max_num = 0
    dict_ = {}
    for i in range(2,n+1):
        num -= set(range(i*2,n+1,i)) # 소수 값을 모두 물러온 뒤
    for i in num:
        if '0' not in str(i): # 0이 없는 소수를 dict로 반환
            dict_[i] = 1      # dict.keys()인 i는 int 값이다
    return dict_

def changer(n, k):
    num=''
    arr, arr_ = [],[]
    while n>0:   # k 진수로 변환
        num = str(n%k) + num 
        n = n//k
    arr = num.split('0') # '0'으로 구분, ex) 110011 -> ['11','','11']
    arr_ = [i for i in arr if i !='']  # '' 를 제외
    arr_.sort()
    return arr_, int(arr_[-1])  # 숫자 리스트와, 최댓값을 반환. max() 사용x

def solution(n, k):
    chg_num = []
    max_num = 0
    prime_arr={}
    cnt = 0
    
    chg_num, max_num = changer(n,k)   # 숫자와 최댓값을 반환
    prime_arr = prime(max_num)  # 소수 dict을 얻음

    for i in chg_num:
        if int(i) in prime_arr.keys():
            cnt +=1
    
    answer = cnt
    return answer

시간이 더 늘어났고, 코드에 뭔가 오류가 생겼다.

 

 

def prime(n):
    if n <= 1:# n이 30000 이상인 경우도 있음. 30000이하의 소수를 모두 찾으면 낭비.
        return 0
    i = 2
    while i != n:
        if n%i == 0:
            return 0
        i+=1
    return 1

def changer(n, k):
    num=''
    arr = []
    while n>0: 
        num = str(n%k) + num 
        n = n//k
    arr = [i for i in num.split('0') if i !=''] 
    return arr     

def solution(n, k):
    cnt = 0
    
    chg_num = changer(n,k)
    for i in chg_num:
        cnt += prime(int(i))

    answer = cnt
    return answer

1번 케이스가 문제다, 시간을 더 줄일 수 있는 방법을 생각해야된다.

 

 

def prime(n):
    if n <= 1:
        return 0
    for i in range(3,int(n**(1/2))+1,2):  # 검색 범위를 줄여줬다
        if n%i == 0:
            return 0
    return 1

def changer(n, k):
    num=''
    arr = []
    while n>0: 
        num = str(n%k) + num 
        n = n//k
    arr = [i for i in num.split('0') if i !=''] 
    return arr     

def solution(n, k):
    cnt = 0
    
    chg_num = changer(n,k)
    for i in chg_num:
        cnt += prime(int(i))

    answer = cnt
    return answer

52ms...정답 조건이 빡빡한 것 같다 ㅜ

합성수, 소수를 판별할 때, sqrt(n) + 1 까지 검색하면 충분히 탐색가능하므로, 자주 이용하도록 하자.

 

다만 dict() 을 썼을 때, 시간초과 외의 오류가 난 것은 고민을 해봐야 한다. 

 

출처

https://school.programmers.co.kr/learn/courses/30/lessons/92335

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

728x90

댓글