프로그래머스 문제: https://programmers.co.kr/learn/courses/30/lessons/12930
짝수와 홀수를 판단해야 할 때 나는 항상 2로 나누고 나머지를 판별했다. 초등학교 때부터 배워온 숫자의 개념이 나를 그렇게 만들었다.
그러니 짝수와 홀수를 판별해 "Even" 이나 "Odd"를 리턴하게 한다면 나는 이런 코드를 작성한다:
def solution(num):
return "Even" if num % 2 == 0 else "Odd"
이제야 익숙해진 파이썬의 삼항 연산자를 사용해서 한 줄로 짜고 나니 쉬운 문제지만 해놓고 만족스러웠다고 할 수 있겠다. 그러고 나서 다른 사람들의 풀이를 확인하니 머리가 띵하다.
(num % 2 and 'Odd') or 'Even'
["Even", "Odd"][num & 1]
나: 이건 뭐야?
딱 보자마자 이런 건가? 하고 오는, 그런 게 없더라. 하나하나 차근차근 검색해 가면서 이해하고 나니 조금 허탈하기도 했다. 그래서 잊지 않도록, 또 이런 코드를 내가 짤 수 있도록 블로깅해서 기록하려고 한다.
이 놈이 어려운 건 and와 or 연산자 뒤에 str이 있기 때문이었다. 뭐야? 왜? 하고 읽다 보니 str이 존재하면 True라는 것이 뒤늦게 생각났는데, 그러고 나서야 and, or 연산자가 무엇을 리턴하는지에 좀 더 집중할 수 있었다.
(num % 2 and 'Odd') or 'Even'
먼저 따로 떼어놓고 보자.
num % 2 and 'Odd'
num % 2
의 결과는 0 또는 1이다. 그러니 T/F로 나누어지겠지. 그러면 양 측이 참이어야 하는 and 연산자가 str에 값이 들어있는 "Odd"
부분은 True로 판별하고, num % 2
를 판별할 것이다.
아니, 순서대로 생각해야 한다! 헷갈린 게 이거였다. 기초적인 건데 생각하지 못한 게 부끄럽다.
순서대로, 그리고 홀짝 순으로 확인하자.
and
연산자는 양 측이 다 참이어야 한다. 먼저 온 것을 판별한다. 그러므로 A가 거짓이라면 그 자리에서 연산은 종료되고 A를 출력한다.
A가 참이라면 B를 판별한다. B가 거짓이라면 연산은 종료되고 B를 출력한다.
A와 B 둘 다 참이라면 연산은 종료되고 마지막으로 판별한 B를 출력한다.
이제 다시 보자.
num % 2 and 'Odd'
num % 2
의 결과가 홀수라서 1이라면 값은 True
다. and 연산자이므로 A가 참이니 B를 판별하고, 값이 존재하는 str은 True
니 양 측 다 True이다.
양쪽 다 True
인 것으로 연산은 종료된다. "Odd"
를 리턴한다.
그런데 여기서 끝이 아니다.
(num % 2 and 'Odd') or 'Even'
=>
('Odd') or 'Even'
이렇게 되었다! 양쪽 다 str로 True
이니 이제 or 연산자가 일한다.
or 연산자는 둘 중 하나라도 참이면 된다. 아까와 같이 살펴보자.
or
연산자는 하나라도 참이면 된다. 먼저 온 것을 판별한다. 그러므로 A가 참이라면 연산이 종료되고 마지막으로 판별한 A를 리턴한다.
A가 거짓이라면 B를 판별한다. B가 참이라면 B를 리턴한다.
둘 다 거짓이라면 마찬가지로 마지막으로 판별한 B를 리턴한다.
('Odd') or 'Even'
같은 흐름으로 짝수일 때 "Even"이 리턴되는 것을 살펴보자.
and
연산자는 양 측이 다 참이어야 한다. 먼저 온 것을 판별한다. 그러므로 A가 거짓이라면 그 자리에서 연산은 종료되고 A를 출력한다.
A가 참이라면 B를 판별한다. B가 거짓이라면 연산은 종료되고 B를 출력한다.
A와 B 둘 다 참이라면 연산은 종료되고 마지막으로 판별한 B를 출력한다.
or
연산자는 하나라도 참이면 된다. 먼저 온 것을 판별한다. 그러므로 A가 참이라면 연산이 종료되고 마지막으로 판별한 A를 리턴한다.
A가 거짓이라면 B를 판별한다. B가 참이라면 B를 리턴한다.
둘 다 거짓이라면 마찬가지로 마지막으로 판별한 B를 리턴한다.
(num % 2 and 'Odd') or 'Even'
num % 2
가 0, 즉 짝수라면 False가 된다. and 연산자에서 하나라도 거짓이라면 연산이 종료되니 A, 즉 False
를 리턴한다.
(False) or 'Even'
or 연산자는 하나라도 참이면 되니 A가 False
여도 B를 판별하러 간다. B는 str인 True
를 확인한 후 "Even"을 리턴한다.
이번에는 생각지도 못했던 비트 연산자를 살펴보자.
얼핏 보면 그냥 인덱스다. 그러니까, 리스트다. 앞에 리턴만 붙어 있으니 혼란스럽다.
a[1]
형태가 아니라 그냥 냅다 리스트의 인덱스를 꺼내니 당황스럽다. 잘 살펴보니 아하! 했다.
일단 먼저 보면, ["Even", "Odd"]
는 len()이 2인 리스트다. 그러니 인덱스는 0 또는 1이다.
여기서 정신이 들었다!
["Even", "Odd"][num & 1]
이제 뒷부분을 마저 보자. &
연산자는 비트 연산자다. 이진수로 계산해 둘 다 1이라면 참, 둘 중 하나라도 0이라면 거짓이다.
num & 1
num이 이진수라면, 마지막 자릿수가 1을 더하거나 0을 더한다.
그러니 예를 들어 num이 13이라면, 1101
이므로 1
과 &
연산을 했을 때 양쪽 항이 다 마지막 자리인 1
이므로 곧 참, 1을 리턴한다.
또다시 예를 들어 num이 14라면, 1110
이다. 1
과 &
연산을 하면 마지막 자리가 하나는 0
, 하나는 1
이 되므로 곧 거짓, 0을 리턴한다.
그러니
["Even", "Odd"][0 또는 1]
이런 형태를 가지게 되는 것이다.
유레카!
그렇게 짝수일 때에는 0, "Even"을 리턴하고 홀수일 때에는 1, "Odd"를 리턴한다.
프로그래머스를 풀면 풀수록 내가 얼마나 부족한지 느끼고 동시에 코딩이 얼마나 재미있는지도 느낀다. 와 이런 생각을 할 수 있다니! 부터 나도 이렇게 코딩하고 싶다는 욕심까지.
새~로운 생각을 해내고 싶다. 계속 힘내야지!