PROGRAMMERS - 숫자 짝꿍[Level 1]

GI JUNG·2022년 11월 14일
3

algorithm

목록 보기
5/28
post-thumbnail
post-custom-banner

문제는 여기서 확인할 수 있으며, 이 글을 블로깅하는 이유는 Counter다중 if-else 구문을 한 줄로 쓰는 방법을 터득하여 올린다. 아래 처음 풀이는 그냥 생각흐름대로 바로 짜서 통과한 것이며 다른 풀이는 Counter를 이용하여 풀고 싶어 짠 코드이다.

🍀 처음 풀이

  • X, Y에 대한 숫자 값의 개수를 구한다 -> num1_dict, num2_dict
  • 각각의 숫자의 개수를 dictionary로 구했다면 공통적으로 들어있는 숫자와 그 숫자의 개수(작은 개수를 구해야 서로 동일한 숫자 개수를 얻을 수 있다)를 구한다. -> common_dict
  • 큰 숫자(answer)를 만들기 위해 common_dict의 key 값들을 descending으로 루프를 돌며 key * common_dict[key]를 answer에 더해준다.

문제 풀이 코드

def get_common(str_num1, str_num2):
    num1_dict = {}
    num2_dict = {}
    common_dict = {}
    
    for v in str_num1:
        if v not in num1_dict.keys():
            num1_dict[v] = 0
        
        num1_dict[v] += 1
        
    for v in str_num2:
        if v not in num2_dict.keys():
            num2_dict[v] = 0
        
        num2_dict[v] += 1
        
    for key in num1_dict.keys():
        if key in num2_dict.keys():   # num2_dict의 없는 key에 접근하는 keyError 처리
            common_dict[key] = min(num1_dict[key], num2_dict[key])

    return common_dict

def solution(X, Y):
    answer = ''
    common_dict = get_common(X, Y)
    if not common_dict:
        return "-1"
    elif list(common_dict) == ["0"]:   # 👈 1️⃣
        return "0"
    else:
        for key in sorted(common_dict.keys(), reverse = True):
            answer += key * common_dict[key]
    
    return answer

💡 이 코드를 짜면서 항상 헷갈렸던 것이 있는데 javascript와 달리 key값이 암묵적인 casting이 일어나지 않아 "1"1은 다른 key값으로 생성된다는 것이다. 아래 코드를 살펴보자

증명

d = {}
d[1] = 'something'
d["1"] = 'something'

print(d.keys())   # 출력 -> dict_keys([1, '1'])

key가 1과 '1' 두 개가 생성이 된 것으로 보아 정수형 1과 문자형 1은 key값으로 동일하다고 판단하지 않는다.

🍀 다른 풀이

이 풀이는 Counter를 이용한 풀이로 위의 처음 풀이에서 X, Y에 대한 숫자 값의 개수를 구하는 것을 간단하게 처리할 수 있다.
아래 Counter 예시를 살펴보자

Counter

counter 예시

from collections import Counter

phrase = "hello world"
phrase_counter = Counter(phrase)
print(phrase_counter)

출력

counter method는 dictionary method를 그대로 쓸 수 있으며 유용하다고 생각하는 것은 mose_commonpop method가 있다.

그리고 분기처리를 if-elif-else를 한 줄로 줄일 수 없을까 생각하여 찾아보다가 stackoverflow에서 답을 찾을 수 있었다.

multi if-else state with list comprehension

예시

a = 28

if a >= 20:
	print('adult')
elif a >= 17 and a <= 19:
	print('high school student')
else:
	print('under high school student')

위와 같이 20살 이상이면 성인 17 ~ 19이면 고등학생 16세 이하라면 고등학생이 아님이라는 분기가 있다. 이것을 한 줄로 if-else로 표현하면 아래와 같다.

a = 28

result = 'adult' if a >= 20 \   # 1️⃣
    else 'high school student' if a >= 17 and a <= 19 \   # 2️⃣
    else 'under high school student'   # 3️⃣

print(result)   # 'adult' will be showed!!

각각 1, 2, 3으로 마크한 것은 위의 분기처리한 if-else구문과 매칭되는 코드이다.

- 1️⃣: if a >= 20
- 2️⃣: elif a >= 17 and a <= 19
- 3️⃣: else

풀이

문제 풀이 코드

from collections import Counter

def solution(X, Y):
    answer = ''
    counter_x, counter_y = Counter(X), Counter(Y)
    min_counter = counter_x if len(counter_x) < len(counter_y) else counter_y

    for key in sorted(min_counter.keys(), reverse = True):
        if key in counter_x and key in counter_y:
            answer += str(key) * min(counter_x[key], counter_y[key])
    
    return '-1' if answer == '' else '0' if len(answer) == answer.count('0') else answer

🥳 마치며

문제를 접할 때 A4용지에 5분 정도 끄적이다가 바로 짰는데 통과를 했다. 그러다가 문득 Counter가 있다는 것이 생각나서 counter를 이용했으며 코드가 길어지길래 한 번 줄여보고 싶은 욕심이 생겨 if-else를 한 줄로 쓰는 것을 찾아 공부했다. 항상 느낀 것이지만 주어진 것에서 끝나는 것이 아닌 스스로 문제를 던지고 해결하는 습관이 자신을 많이 향상 시키는 것 같다. 예전에는 스스로 문제를 던지고 해결하지 않고 단지 궁금증에서만 끝났다면 요새는 해결하려는 습관이 갖추어져 가는 것 같다.

참고

multi if else statement in list comprehension
Counter in python

profile
step by step
post-custom-banner

0개의 댓글