짝수홀수 판단 : AND 연산자와 OR 연산자, 그리고 비트 연산자 &

solee·2022년 6월 4일
0

TIL

목록 보기
15/20

프로그래머스 문제: 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]

나: 이건 뭐야?

딱 보자마자 이런 건가? 하고 오는, 그런 게 없더라. 하나하나 차근차근 검색해 가면서 이해하고 나니 조금 허탈하기도 했다. 그래서 잊지 않도록, 또 이런 코드를 내가 짤 수 있도록 블로깅해서 기록하려고 한다.



(num % 2 and 'Odd') or 'Even'

이 놈이 어려운 건 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를 판별할 것이다.

아니, 순서대로 생각해야 한다! 헷갈린 게 이거였다. 기초적인 건데 생각하지 못한 게 부끄럽다.
순서대로, 그리고 홀짝 순으로 확인하자.



홀수일 때

  1. A and B
  • 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 연산자는 둘 중 하나라도 참이면 된다. 아까와 같이 살펴보자.


  1. A or B
  • or 연산자는 하나라도 참이면 된다. 먼저 온 것을 판별한다. 그러므로 A가 참이라면 연산이 종료되고 마지막으로 판별한 A를 리턴한다.

  • A가 거짓이라면 B를 판별한다. B가 참이라면 B를 리턴한다.

  • 둘 다 거짓이라면 마찬가지로 마지막으로 판별한 B를 리턴한다.


그러니 아래와 같은 경우에는, 첫 번쨰로 참인 "Odd"를 리턴하게 된다.
('Odd') or 'Even'




짝수일 때

같은 흐름으로 짝수일 때 "Even"이 리턴되는 것을 살펴보자.

  1. A and B
  • and 연산자는 양 측이 다 참이어야 한다. 먼저 온 것을 판별한다. 그러므로 A가 거짓이라면 그 자리에서 연산은 종료되고 A를 출력한다.

  • A가 참이라면 B를 판별한다. B가 거짓이라면 연산은 종료되고 B를 출력한다.

  • A와 B 둘 다 참이라면 연산은 종료되고 마지막으로 판별한 B를 출력한다.


  1. A or 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"을 리턴한다.






이번에는 생각지도 못했던 비트 연산자를 살펴보자.

["Even", "Odd"][num & 1]

얼핏 보면 그냥 인덱스다. 그러니까, 리스트다. 앞에 리턴만 붙어 있으니 혼란스럽다.
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"를 리턴한다.




마치며

프로그래머스를 풀면 풀수록 내가 얼마나 부족한지 느끼고 동시에 코딩이 얼마나 재미있는지도 느낀다. 와 이런 생각을 할 수 있다니! 부터 나도 이렇게 코딩하고 싶다는 욕심까지.
새~로운 생각을 해내고 싶다. 계속 힘내야지!




profile
DA DA DA

0개의 댓글