[코드카타] Python 알고리즘 21번 ~ 30번
21번. 하샤드 수
양의 정수 x가 하샤드 수이려면 x의 자릿수의 합으로 x가 나누어져야 합니다. 예를 들어 18의 자릿수 합은 1+8=9이고, 18은 9로 나누어 떨어지므로 18은 하샤드 수입니다.
자연수 x를 입력받아 x가 하샤드 수인지 아닌지 검사하는 함수, solution을 완성해주세요.
하샤드 수란?
def solution(x):
answer = sum(list(map(int, str(x)))) # 각 자릿수의 합
return (x % answer) == 0
22번. 두 정수 사이의 합
두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수, solution을 완성하세요.
예를 들어 a = 3, b = 5인 경우, 3 + 4 + 5 = 12이므로 12를 리턴합니다.
def solution(a, b):
if a - b > 0:
return sum(range(b, a+1))
elif a - b == 0:
return a or b
else:
return sum(range(a, b+1))
위의 코드로도 실행하는 데에 별 문제는 없지만, 작성하면서도 느꼈다. '분명히 더 간단한 코드가 있다...'
아니나 다를까, 제출 후 다른 사람의 답을 봤더니
a, b = b, a
이것은 파이썬 입문 강의에서 가장 처음에 배우는 내용이다.
매개변수 얘기하면서 무조건 나오는 내용인데...이 내용을 놓치다니... 정말 이마를 탁 쳤다.(진짜로)
위의 a, b = b, a 를 사용하면 굳이 삼항 조건문을 사용하지 않고도 더 간략하게 작성이 가능하다.
def solution(a, b):
if a > b:
a, b = b, a
return sum(range(a, b + 1))
그리고 또 하나 더 파이썬다운 코드가 있다.
def solution(a, b):
return sum(range(min(a, b), max(a, b) + 1))
굉장히 기초적인 함수 min, max를 사용하여 단 두 줄로 끝나기 때문에 너무 맘에 드는 코드다.
이렇게 기본적인 내장 함수를 사용해서 복잡할 수 있어보이는 코드를 최대한 간결하게 작성해보는(단순히 숏코딩이 아니라) 능력에 좀 더 집중해서 시간을 투자해봐야겠다.
23번. 콜라츠 추측
1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.
1-1. 입력된 수가 짝수라면 2로 나눕니다.
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다.
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다.
예를 들어, 주어진 수가 6이라면 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야 하는지 반환하는 함수, solution을 완성해 주세요. 단, 주어진 수가 1인 경우에는 0을, 작업을 500번 반복할 때까지 1이 되지 않는다면 –1을 반환해 주세요.
def solution(num):
for i in range(501):
if num == 1:
return i
elif num % 2 == 0:
num //= 2
else:
num = (num * 3) + 1
return -1
24번. 서울에서 김서방 찾기
String형 배열(list) seoul의 element중 "Kim"의 위치(index) x를 찾아, "김서방은 x에 있다"는 String을 반환하는 함수, solution을 완성하세요. seoul에 "Kim"은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.
입출력 예
seoul = ["Jane", "Kim"]
return = 김서방은 1에 있다
def solution(seoul):
answer = f'김서방은 {seoul.index("Kim")}에 있다'
return answer
seoul이라는 리스트가 주어지고 이 리스트에서 "Kim"이라는 요소의 index를 찾아 index를 반환하라는 문제다.
문제의 입출력 예가 ""로 묶여 있으나 출력은
김서방은 1에 있다
로 출력되는 게 맞다.
25번. 나누어 떨어지는 숫자 배열
array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요.
divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.
def solution(arr, divisor):
answer = sorted(filter(lambda x: x % int(divisor) == 0, arr))
return answer if answer else [-1]
드디어 lambda를 사용해봤다.
리스트의 요소들을 divisor로 연산을 해야하기 때문에 lambda를 사용했다.
lambda를 사용할 때, 연산 조건이 달려있기 때문에 filter를 사용했고, 오름 차순으로 정렬하기 위해 sorted()를 사용했다.
가장 어려웠던 건 요소가 없을 경우 -1을 반환하는 거였는데,
몰랐던 개념이 나와서 정리한다.
if lst: # lst라는 리스트가 비어있지 않으면(True) 실행, 비어있으면(False) 실행하지 않는다.
따라서, answer가 비어있을 경우 [-1]을 반환하도록 하려면
한 줄 조건문으로 만들어서
return answer if answer else [-1]
# answer가 비어있지 않을 경우 answer를 반환하고 비어있을 경우 [-1]을 반환
위와 같이 작성할 수 있다.
다른 사람들이 작성한 코드를 보니 더 직관적으로 (lambda를 사용하지 않고도..!!) 작성했다.
def solution(arr, divisor):
return sorted([n for n in arr if n % divisor == 0]) or [-1]
바로 리스트 컴프리헨션을 사용해서 더 간결하게 작성을 했고,
or이게 바로 return에 사용가능할거라고는 생각을 못했는데 편견을 깨주었다....
한번 써볼걸..........
괜히 어렵게 생각하지 말고, 쉬운 리스트 컴프리헨션을 사용해보도록 마인드셋을 바꿔야겠다.
26번. 음양 더하기
어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.
def solution(absolutes, signs):
return sum([i if sign else -i for i, sign in zip(absolutes, signs)])
signs라는 리스트는 boolean이라는 참True와 거짓False 두 가지의 값만 가질 수 있는 데이터 타입으로 이루어져 있다.
즉,아래와 같이 if문에 signs 리스트의 요소들을 넣으면 바로 작동한다.
signs = [True, False, True]
for sign in signs:
if sign: # True일 경우
print(1)
else: # False일 경우
print(-1)
# 1, -1, 1 이 출력됨
따라서,
return sum([i if sign else -i for i, sign in zip(absolutes, signs)]
이 부분은 sign(signs 리스트의 개별 요소들)이 True일 경우 i(absolutes 리스트의 개별 요소)가 출력되고, False일 경우 -i가 출력되는 것이다.
27번. 핸드폰 번호 가리기
프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.
def solution(phone_number):
return '*' * (len(phone_number) - 4) + phone_number[-4:]
전화번호 문자열의 길이를 구하고 뒤에서 네 자리만 남기고 전부 *으로 표시해야함.
문자열의 뒤에서부터 추출하려면 [-4:]이다. :앞이 비어 있으면 맨 처음부터, 뒤가 비어있으면 뒤에서부터임
28번. 없는 숫자 더하기
0부터 9까지의 숫자 중 일부가 들어있는 정수 배열 numbers가 매개변수로 주어집니다. numbers에서 찾을 수 없는 0부터 9까지의 숫자를 모두 찾아 더한 수를 return 하도록 solution 함수를 완성해주세요.
def solution(numbers):
return sum(set(range(10)) - set(numbers))
리스트는 곱셈과 덧셈만 가능하지만 집합은 교집합, 차집합의 개념이 있기 때문에 sum이 가능하다.
29번. 제일 작은 수 제거하기
정수를 저장한 배열, arr 에서 가장 작은 수를 제거한 배열을 리턴하는 함수, solution을 완성해주세요. 단, 리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴하세요. 예를들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴 하고, [10]면 [-1]을 리턴 합니다.
def solution(arr):
if len(arr) == 1:
return [-1]
arr.remove(min(arr))
return arr
30번. 가운데 글자 가져오기
단어 s의 가운데 글자를 반환하는 함수, solution을 만들어 보세요. 단어의 길이가 짝수라면 가운데 두글자를 반환하면 됩니다.
def solution(s):
mid = len(s) // 2
if len(s) % 2 == 0:
return s[(mid-1)] + s[mid]
else:
return s[mid]