[코딩테스트] 프로그래머스 - k진수에서 소수 개수 구하기 (2022 KAKAO BLIND RECRUITMENT)

Jenna·2023년 4월 3일
0

Programmers

목록 보기
6/7
post-thumbnail

k진수에서 소수 개수 구하기

문제 설명

양의 정수 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 함수를 완성해 주세요.

제한사항

  • 1 ≤ n ≤ 1,000,000
  • 3 ≤ k ≤ 10

입출력 예

nkresult
43767433
110011102

입출력 예 설명

입출력 예 #1
문제 예시와 같습니다.

입출력 예 #2
110011을 10진수로 바꾸면 110011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 11, 11 2개입니다. 이와 같이, 중복되는 소수를 발견하더라도 모두 따로 세어야 합니다.


⭐처음에 구현한 코드

import string

tmp = string.digits+string.ascii_lowercase
def convert(num, base) :
    q, r = divmod(num, base)
    if q == 0 :
        return tmp[r] 
    else :
        return convert(q, base) + tmp[r]
    
def is_decimal(n):
    if n == 1:
        return False
    else:
        for i in range(2,n):
            if n%i == 0:
                return False
        return True
    
def solution(n, k):
    answer = 0
    arr = []
    convert_num = convert(n,k)
    arr = convert_num.split("0")
    for num in arr:
        if num == "":
            arr.remove("")
    
    for num in arr:
        n = int(num)
        if is_decimal(n) is True:
            answer += 1
                
    return answer

입력된 nk진수로 변환하기 위해 convert() 함수를 구현했다. n진수로 바꾸는 코드는 가져온거라서 어떻게 구현해야하는지 살펴봐야 할 것 같다. 그리고 소수인지 판별하기 위해 is_decimal 함수를 구현했다. True 가 반환된다면 소수인걸로 구현했다.


🤔오답노트


테스트 케이스1에서 시간초과, 12에서 런타임 에러가 났다... 왜지...

숫자의 용량 문제인 것 같다. 하지만 파이썬에는 long형 자료형이 없는데..? ㅜㅜ

def is_decimal(n):
    if n == 1:
        return False
    else:
        for i in range(2,int(math.sqrt(n))+1):
            if n%i == 0:
                return False
        return True

소수인지 판별하는 코드를 int(math.sqrt(n))+1 까지로 바꿔줬다. 소수 판별을 위해서는 해당 수 n의 제곱근까지만 나눠봐도 판별이 가능하다. 따라서 k진수로 바꾼다면 n이 int자료형을 넘어서기 때문에 제곱근까지만 나눠보는 것으로 시간 초과를 막는 것이다.

12번 런타임 에러는 질문을 보고 해결했다. 예를 들어, 36을 3진수로 바꾸는 경우에는 1100이 되는데 해당 경우에 remove()를 한다면 뒤의 빈칸 하나는 없어지지 않는다.

테스트 케이스를 추가해서 확인하면 이런식으로 된다. 따라서 빈칸은 int형으로 취급되지 못하기 때문에 런타임 에러가 나는 것이다.

 new_arr = []
    for num in arr:
        if num == "":
            continue
        else:
            new_arr.append(num)
    arr = new_arr

해결하기 위해 전에 했던 것 처럼 빈칸이 아닌 경우에 새 배열에 저장을 해서 해당 배열로 바꿔줬다.


✔수정코드

import string
import math

tmp = string.digits+string.ascii_lowercase
def convert(num, base) :
    q, r = divmod(num, base)
    if q == 0 :
        return tmp[r] 
    else :
        return convert(q, base) + tmp[r]
    
def is_decimal(n):
    if n == 1:
        return False
    else:
        for i in range(2,int(math.sqrt(n))+1):
            if n%i == 0:
                return False
        return True
    
def solution(n, k):
    answer = 0
    arr = []
    convert_num = convert(n,k)
    arr = convert_num.split("0")
    
    new_arr = []
    for num in arr:
        if num == "":
            continue
        else:
            new_arr.append(num)
    arr = new_arr
    
    for num in arr:
        n = int(num)
        if is_decimal(n) is True:
            answer += 1
                
    return answer

소수 판별은 제곱근 까지만 판별한다는 그런거는 힌트를 보지 않는다면 풀 수 없었을 것이다.. ㅜㅜ.. 그런게 나오면 어떡한담.. 많이 푸는 수 밖에 없는 것일까,,
그리고 그냥 제곱근까지만 하면 안되고 +1을 해줘야 제대로 된 정답이 나오드라,,
실패 케이스를 찾아내는게 너무 어려운거 같다🥲


🤓다른 코드

# n을 k진법으로 나타낸 문자열 반환
def conv(n, k):
    s = ''
    while n:
        s += str(n%k)
        n //= k
    return s[::-1]

# n이 소수인지 판정
def isprime(n):
    if n <= 1: return False
    i = 2
    while i*i <= n:
        if n%i == 0: return False
        i += 1
    return True

def solution(n, k):
    s = conv(n,k)
    cnt = 0
    for num in s.split('0'):
        if not num: continue # 빈 문자열에 대한 예외처리
        if isprime(int(num)): cnt += 1
    return cnt

깔끔하고 괜찮은 코드인 것 같다. 내가 사용한 방법처럼 어렵게 k진수로 바꾸는 것이 아닌 나누는 방법으로 나누는 코드가 더 괜찮은 것 같다. 그리고 sqrt를 사용한게 아니라 i*i <= n 을 사용한게 괜찮은 것 같다. 음 결국 같은 코드이긴 한데 왜 저기서는 +1을 안해도 제대로 나오는거지? 흐음..

profile
FE/Game Dev.

0개의 댓글