총 100,000 비트로 이루어진 이진수 A와 B가 주어진다. 이때, A & B, A | B, A ^ B, ~A, ~B를 한 값을 출력하는 프로그램을 작성하시오.
첫째 줄에 이진수 A, 둘째 줄에 이진수 B가 주어진다. 두 이진수의 길이는 모두 100,000이다. 예제의 경우에만 길이가 10이며, 예제는 채점하지 않는다.
첫째 줄부터 한 줄에 하나씩 차례대로 A & B, A | B, A ^ B, ~A, ~B를 출력한다.
비트마스크에 대한 감각이 아직 부족하게 느껴져서...
기초적인 문제부터 다시 풀어보고자 이 문제를 풀었다.
파이썬 연산으로 웬만한 비트연산은 다 지원되니까 밥일줄 알았는데...
파이썬에선 NOT 연산이 좀 특별하다.
파이썬 NOT
- 비트 반전 후, 2의 보수로 만들어서 리턴
- 비트 반전 -> 1의 보수 -> 2의 보수 -> 음수 부호 붙여서 리턴
결국 정수형으로 다뤄야하기 때문에 굳이 저런 형태로 주는거 같지만
NOT 연산이라 함은 보통 1의 보수를 취한걸 생각한다. 비직관적인건 사실이다...
뭐 어쩌겠나. 따로 연산하자!
파이썬에서 1의 보수 얻는 방법
(A가 원래 이진수, mask는 A의 자릿수만큼 1로 채운 것이다.)
- ~A & mask
- A ^ mask
- mask - A
첫번째 방법은 원래는 의미없는 연산이다. 무조건 ~A 자기 자신이 나오게 되어있기 때문이다.
그런데 알다시피 파이썬은 형태가 특별하므로... 저렇게 마스크로 and 연산을 취해주면 1의 보수만 예쁘게 나온다.
세가지 방법 모두 시도해본 결과, 세번째 뺄셈을 이용한 방식이 가장 빨랐다.
import sys
input = sys.stdin.readline
a,b = int(input(),2), int(input(),2)
n = 100000
mask = 2 ** n - 1
print(f'{a&b:0{n}b}')
print(f'{a|b:0{n}b}')
print(f'{a^b:0{n}b}')
print(f'{mask-a:0{n}b}')
print(f'{mask-b:0{n}b}')