71일차

Suhyeon Lee·2025년 1월 10일

CodeKata

SQL

프로그래머스: 잔챙이 잡은 수 구하기

  • 작성한 쿼리
SELECT
  COUNT(*) AS fish_count
FROM
  fish_info
WHERE
  length IS NULL
;

프로그래머스: 가장 큰 물고기 10마리 구하기

  • 작성한 쿼리
-- 1
SELECT
  id
  , length
FROM
  fish_info
ORDER BY
  length DESC
  , id ASC
LIMIT 10
;

-- 2
WITH length_rank AS (
  SELECT
    *
    , RANK() OVER (ORDER BY length DESC) AS rnk
  FROM
    fish_info
)
SELECT
  id
  , length
FROM
  length_rank
WHERE
  rnk <= 10
ORDER BY
  rnk
  , id
;

Python

80. 예상 대진표

  • 작성한 코드
def solution(n,a,b):
    from math import ceil
    answer = 0

    while a!=b:
        answer += 1
        a, b = ceil(a/2), ceil(b/2)

    return answer

참고할 만한 다른 풀이

  1. ★★★★★
def solution(n,a,b):
    return ((a-1)^(b-1)).bit_length()

1을 빼는 것은 선수의 위치를 0-index 형태로 바꾸기 위함인 것 같고요.
a, b는 각각 선수의 위치이고 이를 2비트 수로 표현했을 때a, b가 인접한 위치로 가려면, 두 비트가 같을 때는 0을 더하고 두 비트가 다를 때는 1을 더하는 XOR 연산으로 생각할 수 있겠네요.
토너먼트 트리를 그렸을 때, 윗단을 최상위 비트, 아래단을 최하위 비트로 생각하면 이해되실 것 같네요. 가령, 5(101)의 가장 앞의 비트값(최상위)가 트리의 꼭대기
(a, b 를 xor 취하는 과정에서 ab 사이의 거리가 가까우면 상위비트는 차이가 나지 않겠죠? 거꾸로 ab 사이의 거리가 멀면 상위비트가 차이 날 거고요. 그래서 xor 연산 결과의 길이를 리턴해주면 라운드가 나오는 아이디어인것으로 보여요.)

def solution(n, a, b):
    answer = 0
    
    while a != b:
        answer += 1
        a, b = (a + 1) // 2, (b + 1) // 2

    return answer

대진표를 그려보면 각 라운드에 진출 할 때마다 숫자가 2로 나누어지는 것을 볼 수 있을 것이다.
a와 b를 나누고 난 값이 같아지는 경우에는 만나서 대결을 진행한 것이라고 볼 수 있기 때문에, 우리는 a와 b의 값이 같아질 때까지 2로 나누어주면 된다.
a와 b에 1을 더하는 이유는, 각 숫자가 홀수일 경우에 잘못 배정되는 경우를 방지하기 위해서이다.
예를 들어서 7을 2로 나누면 3.5가 되어서 정수만 보면 3이 되는데, 이렇게 되면 우리가 기대하는 바와 달라지므로 미리 1을 더해서 2로 나눈다.
그렇게 하면 정상적으로 잘 배치되는 것을 볼 수 있다.

  • 아래에서 올라갈 때 새로 부여받는 번호의 규칙성을 찾는데 주력하신 듯
  • 마지막에 반환할 변수 answer에 초기값 0을 부여
  • a와 b가 서로 다를 경우를 반복하는 while Loop 내에서 시작과 동시에 answer를 1 증가시킴
  • 부여받은 각 번호에 1을 더하여 2로 나눈 몫을 다시 각 변수에 저장
  • 각 번호에 1을 더하는 이유?
    • 1 ~ 8의 번호가 있을 때, 단순히 2로 나눈 몫은 0 1 1 2 2 3 3 4 이지만 1을 더했을 경우 1 1 2 2 3 3 4 4가 되므로 원하고자 하는 결과값을 얻을 수 있음
def solution(n,a,b):
    # 발생할 수 있는 최대 라운드 수 계산
    max_round = 0
    while 2 ** max_round < n:
        max_round += 1
    
    # 이진 탐색 적용
    a, b = min(a, b), max(a, b)  # 큰 수, 작은 수 구분
    mid = n // 2  # 최초 중간값
    lower = 0  # 최초 최소값
    upper = n  # 최초 최대값
    
    while True:
        # 탈출 조건 // 두 수가 포함된 라운드가 서로 다를 경우
        if a <= mid and b > mid:
            break
        # 작은 수가 중간값보다 클 경우(라운드에서 두 수가 같은 그룹에 있을 경우)
        elif a >= mid:
            lower = mid
            mid = (mid + upper) // 2
            max_round -= 1  # 라운드값 -1
        # 큰 수가 중간값보다 작거나 같을 경우(라운드에서 두 수가 같은 그룹에 있을 경우)
        elif b <= mid:
            upper = mid
            mid = (mid + lower) // 2
            max_round -= 1  # 라운드값 -1
            
    return max_round

대진표를 손으로 그려보다가 반으로 나누어 전후를 살핀다는 점이 이진탐색과 동일하다고 생각하여 이진탐색 기법을 적용하기로 결정
발생할 수 있는 최대 라운드의 수를 계산하기 위하여 while Loop을 활용, 2의 x제곱이 n과 같아지는 시점까지 max_round 변수를 1씩 증가시킴.
이진탐색을 적용하기 위하여 주어진 변수 a와 b의 대소를 비교하여 작은 수를 a에, 큰 수를 b에 재할당하고, 최초 중간값/최소값/최대값을 설정
while Loop을 무한 반복하되, 탈출조건으로 두 수가 서로 다른 라운드에 포함되어있을 경우를 설정
이후 라운드에서 두 수가 같은 그룹에 있을 경우를 두 경우로 분할(작은 수가 mid 보다 클 경우, 또는 큰 수가 mid보다 작을 경우)하여 해당 경우에는 max_round를 1씩 뺌

강의

데이터 파이프라인 2회차

QCC

6회차

최종 프로젝트

개인 공부

DataFrame의 중첩과 중첩 리스트
round()

MySQL 데이터 위치 변경하기

  • MySQL의 Data 디렉토리를 원하는 드라이브로 변경하면 됨
  • 주의 사항
    • 옮길 대상이 되는 드라이브명은 반드시 고정적이어야 함
  • 위치 변경 순서
    1) MySQL 서비스 중지: '서비스' 실행 > "MySQL80" 마우스 오른쪽 클릭 후 중지
    2) 'C:\ProgramData\MySQL\MySQL Server 8.0'에서 my.ini 파일 수정:


    3) 데이터 옮기기: C 드라이브 Data 디렉토리 전체 복사에서 D 드라이브 Data 디렉토리에 그대로 옮겨 넣기
    (이후 C 드라이브 데이터 삭제해도 됨)
    4) '서비스' 실행해서 MySQL 재기동하기

회고

  • 파이썬 알고리즘 문제 풀이에는 항상 엄청난 고수가 있다… 비트로 해결할 생각을 하다니 멋지다!
  • 주말에 최종 프로젝트 MySQL까지 연결하기
profile
2 B R 0 2 B

0개의 댓글