KATA는 기술과 기술 향상에 초점을 맞춘 코드 챌린지입니다.
일부는 프로그래밍 기본 사항을 교육하는 반면 다른 일부는 복잡한 문제 해결에 중점을 둡니다.
이 용어는 The Pragmatic Programmer 라는 책의 공동 저자인 Dave Thomas 가
무술에서 일본의 카타 개념을 인정하면서 처음 만들어졌습니다.
Dave의 개념 버전은 코드 카타를 프로그래머가
연습과 반복을 통해 기술을 연마하는 데 도움이 되는 프로그래밍 연습으로 정의합니다.
LAT_N 칼럼의 중앙값을 찾는 문제
✔️ 제출 쿼리
✔️ 쿼리 분석
SELECT ROUND(AVG(LAT_N), 4)
FROM (
SELECT LAT_N
FROM (
SELECT LAT_N,
ROW_NUMBER() OVER(ORDER BY LAT_N) ROWN,
COUNT(*) OVER() TOTALCNT
FROM STATION
) SORTING
WHERE ROWN = FLOOR((TOTALCNT + 1) / 2) OR
ROWN = CEILING((TOTALCNT + 1) / 2)
) MEDIAN
쿼리 작동 세부 내용 정리
INNER 쿼리 (SORTING)
# 순번 부여하고 정렬하기
ROW_NUMBER() OVER(ORDER BY LAT_N) ROWN :
LAT_N 칼럼 내 값을 기준으로 각 행에 오름차순 순번 부여
COUNT(*) OVER() TOTALCNT :
전체 행 수
MIDDLE 쿼리
# 부여된 순번들의 중간에 위치한 값 찾기
WHERE ROWN = FLOOR((TOTALCNT + 1) / 2) OR
ROWN = CEILING((TOTALCNT + 1) / 2) :
# 전체 행 수가 홀수일 경우 1개, 짝수일 경우 2개의 값이 출력
FLOOR((TOTALCNT + 1) / 2), CEILING((TOTALCNT + 1) / 2) :
# 전체 행 수가 5(홀수)일 경우
FLOOR((5 + 1) / 2) = 3, CEILING((5 + 1) / 2) = 3
두 쿼리 모두 3이 된다.
# 전체 행 수가 4(짝수)일 경우
FLOOR((4 + 1) / 2) = 2, CEILING((4 + 1) / 2) = 3
FLOOR 는 2, CEILING 은 3 > 결과로 2와 3이 된다.
OR 조건을 사용해 전체 행 수가 홀수, 짝수에 상관없이
중간에 위치한 하나 또는 두 개의 행을 선택
OUTER 쿼리
# 선택된 행들의 LAT_N 값을 AVG(LAT_N)를 사용해 평균 구하기
AVG(LAT_N) :
짝수 행의 경우 두 값의 평균을 구하고,
홀수 행의 경우 한 개의 값을 출력
ROUND(AVG(LAT_N), 4) :
구해진 중앙값을 소수점 넷째 자리까지 반올림
✔️ 제출 코드
✔️ 코드 분석
def solution(numbers):
# 숫자들을 문자열로 변환
numbers = list(map(str, numbers))
# 문자열을 세 번 반복하여 비교 기준으로 사용, 내림차순 정렬
# key = lambda x : x*3 > x를 세 번 반복한 값이 기준이라는 의미
numbers.sort(key=lambda x: x*3, reverse=True)
# 정렬된 숫자들을 이어붙여 결과 문자열 생성
result = ''.join(numbers)
# '0000'과 같은 경우 '0'으로 변환 (테스트 케이스 조건..)
if result[0] == '0':
return '0'
return result
코드 작동 세부 내용 정리
numbers = list(map(str, numbers))
:
숫자 리스트 numbers 의 각 요소를 문자열로 변환
예) [3, 30, 34, 5, 9] → ["3", "30", "34", "5", "9"]
numbers.sort(key=lambda x: x*3, reverse=True)
:
sort 메서드를 사용하여 문자열 리스트 정렬
key = lambda x: x*3
각 문자열 x를 세 번 반복한 값을 정렬 기준으로 사용
예) "3" → "333"
"30" → "303030"
"34" → "343434"
"5" → "555"
"9" → "999"
문자열을 세 번 반복하는 이유는 자릿수를 맞춰 비교하기 위해,
"34"는 "3"보다 길지만 "34"와 "3"을 비교할 때
"34"가 더 큰 값을 만들도록 하기 위함
reverse=True
내림차순으로 정렬
정렬 후 결과
["9", "5", "34", "3", "30"]
result = ''.join(numbers)
:
정렬된 문자열 리스트를 하나의 문자열로 결합
예) ["9", "5", "34", "3", "30"] → "9534330"
서브쿼리 단계별 작성하기 :
INNER 쿼리 (SORTING)
# 순번 부여하고 정렬하기
ROW_NUMBER() OVER(ORDER BY LAT_N) ROWN :
LAT_N 칼럼 내 값을 기준으로 각 행에 오름차순 순번 부여
COUNT(*) OVER() TOTALCNT :
전체 행 수
MIDDLE 쿼리 (WHERE)
# 부여된 순번들의 중간에 위치한 값 찾기
WHERE ROWN = FLOOR((TOTALCNT + 1) / 2) OR
ROWN = CEILING((TOTALCNT + 1) / 2) :
# 전체 행 수가 홀수일 경우 1개, 짝수일 경우 2개의 값이 출력
FLOOR((TOTALCNT + 1) / 2), CEILING((TOTALCNT + 1) / 2) :
# 전체 행 수가 5(홀수)일 경우
FLOOR((5 + 1) / 2) = 3, CEILING((5 + 1) / 2) = 3
두 쿼리 모두 3이 된다.
# 전체 행 수가 4(짝수)일 경우
FLOOR((4 + 1) / 2) = 2, CEILING((4 + 1) / 2) = 3
FLOOR 는 2, CEILING 은 3 > 결과로 2와 3이 된다.
OR 조건을 사용해 전체 행 수가 홀수, 짝수에 상관없이
중간에 위치한 하나 또는 두 개의 행을 선택
OUTER 쿼리 (SELECT)
# 선택된 행들의 LAT_N 값을 AVG(LAT_N)를 사용해 평균 구하기
AVG(LAT_N) :
짝수 행의 경우 두 값의 평균을 구하고,
홀수 행의 경우 한 개의 값을 출력
ROUND(AVG(LAT_N), 4) :
구해진 중앙값을 소수점 넷째 자리까지 반올림
map()
과 sort()
, 그리고 lambda
:
숫자를 문자열로 변경하기 → 정렬하기 (key 값 정의하기)
numbers = list(map(str, numbers))
:
숫자 리스트 numbers 의 각 요소를 문자열로 변환
예) [3, 30, 34, 5, 9] → ["3", "30", "34", "5", "9"]
numbers.sort(key=lambda x: x*3, reverse=True)
:
sort 메서드를 사용하여 문자열 리스트 정렬
key = lambda x: x*3
각 문자열 x를 세 번 반복한 값을 정렬 기준으로 사용
예) "3" → "333"
"30" → "303030"
"34" → "343434"
"5" → "555"
"9" → "999"
문자열을 세 번 반복하는 이유는 자릿수를 맞춰 비교하기 위해,
"34"는 "3"보다 길지만 "34"와 "3"을 비교할 때
"34"가 더 큰 값을 만들도록 하기 위함
reverse=True
내림차순으로 정렬
정렬 후 결과
["9", "5", "34", "3", "30"]
result = ''.join(numbers)
:
정렬된 문자열 리스트를 하나의 문자열로 결합
예) ["9", "5", "34", "3", "30"] → "9534330"