240601_TIL

J Lee·2024년 6월 1일
0

아무리 사소하더라도 배움이 없는 날은 없다.

SQL 코드카타 169번

SELECT e.company_code,
       c.founder,
       Count(DISTINCT lead_manager_code),
       Count(DISTINCT senior_manager_code),
       Count(DISTINCT manager_code),
       Count(DISTINCT employee_code)
FROM   employee e
       LEFT JOIN company c
              ON e.company_code = c.company_code
GROUP  BY 1,2
ORDER  BY 1 

위에서부터 복잡하게 join하면서 내려올 필요 없이,
모든 정보를 다 담고 있는 employee 테이블에서 개수만 count하고 company 테이블하고만 join해서 founder 이름만 받아오면 됨.


알고리즘 코드카타 58번

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

제한사항

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

<1트> : 테스트 케이스 통과, 제출 시 오답(23.1)

def solution(nums):
    x = []                                          #nums에서 세 개 수를 뽑아서 넣을 리스트
    for i in range(len(nums)):
        for j in range(i+1,len(nums)):
            for k in range(j+1,len(nums)):
                x.append(nums[i]+nums[j]+nums[k])
    answer = 0                                      #소수의 개수를 담을 count 선언
    for l in x:
        if l%2 !=0 and l%3 !=0 and l%5 != 0:        #소수의 조건을 충족하면
            count += 1                              #answer에 1씩 더해나가기
    return answer

테스트 케이스는 통과했는데 제출 시 오답이 와장창 떴다.
소수의 조건을 별 생각없이 느슨하게 넣어서 그런 것 같다.

소수는 1과 자신 외에 약수가 없는 수이므로
2부터 자신의 제곱근까지의 수로만 나눠봤을 때 약수로 판명되는 경우가 없으면 된다. 예를 들어 17의 제곱근은 4.xx인데, 17을 2,3,4까지로만 나눠봤을 때 약수인 경우가 없으므로 17은 소수다.

다만 완전제곱수인 경우에는 제곱근까지 확인해 줘야 모든 경우의 수를 검증할 수 있다. 예를 들어 확인해야 할 수가 25라면 2,3,4,5까지의 수로 나눠봐야 5로 나누었을 때 나머지가 0인 경우가 있으므로 소수가 아님을 판정할 수 있는 것. 따라서, 코드상으로는 range(2,int(l**.5)+1)까지로 설정해야 한다.

<2트> : 정답

def solution(nums):
    x = []                                          #nums에서 세 개 수를 뽑아서 넣을 리스트
    for i in range(len(nums)):
        for j in range(i+1,len(nums)):
            for k in range(j+1,len(nums)):
                x.append(nums[i]+nums[j]+nums[k])
    count = 0                                       #x 중 소수의 개수를 셀 count 선언
    for l in x:                                     #x의 모든 요소들을 돌아가면서 검사
        count_divisor = 0                           #약수의 개수를 셀 임시 변수(count_divisor) 선언
        for m in range(2,int(l**.5)+1):             #l의 제곱근+1까지 돌면서 검사
            if l%m == 0:                            #만약 l을 m으로 나눈 나머지가 0(약수)이라면
                count_divisor += 1                  #count_divisor에 1을 더하고
                break                               #반복문 종료 (어차피 소수가 아니므로)
        if count_divisor == 0:                      #만약 반복문이 다 끝났는데도 count_divisor가 0이면
            count += 1                              #소수라는 이야기이므로 count에 1씩 증가
    return count                                    #세 수의 합 x중 소수인 경우의 수를 최종 반환

만약 2부터 x의 원소 l의 제곱근+1까지의 수 중 약수인 경우가 하나라도 있다면 어차피 그 수는 소수가 아니므로 반복문을 더 돌릴 필요가 없다. 따라서 약수의 개수를 세기 위한 count_divisor 변수를 반복문 내에서 변수로 선언해 주고, (1과 자신 외에) 약수가 하나라도 확인되면 count_divisor에 1을 더해주고 반복문을 종료시킨다.

만약 모든 반복문이 다 끝났는데도 count_divisor가 0이라면, 그 수는 1과 자신 외에 약수가 없는 소수에 해당하므로 소수의 개수를 세기 위해 선언해 두었던 count에 1씩 증가시키면 된다.

예전에 코드카타에서 다뤘던 적이 있어서 삼중 반복문까지는 비교적 어렵지 않게 도달했는데, x의 원소 중 소수의 개수를 세는 로직을 반드는 부분이 조금 어려웠다.

어떤 수 l이 소수인지 알아보려면 (대칭의 원리에 의해) 2부터 l의 제곱근까지만 나눠보면 된다는 걸 알게 됐고, 이걸 파이썬에서 반복문으로 구현할 때는 int(제곱근)+1까지 조건으로 명시해야 제곱근까지 포함된다는 것도 새롭게 알게 된 부분. 이제 삼중 반복문은 더 헷갈려서는 안 되겠고, 소수 조건도 한 번 정도만 더 마주쳐 보면 손에 익힐 수 있을 것 같다.

profile
기본기를 소홀히 하지 말자

0개의 댓글