비밀

비밀

학습 연습 문제

소개

Crystal에는 이진 수준에서 Int를 조작하기 위한 비트 연산자가 있어요.

시프트 연산자

Crystal에는 비트를 왼쪽(<<)이나 오른쪽(>>)으로 옮기는 시프트 연산자가 있어요.

왼쪽 시프트(<<)

왼쪽 시프트 연산자(<<)는 비트를 왼쪽으로 옮겨요. 옮길 값은 왼쪽에, 옮길 자릿수는 오른쪽에 적어요.

0b0010 << 1
# => 0b0100

0b0010 << 2
# => 0b1000

수가 음수라면, 대신 오른쪽으로 옮겨요.

0b0010 << -1
# => 0b0001

오른쪽 시프트(>>)

오른쪽 시프트 연산자(>>)는 비트를 오른쪽으로 옮겨요. 왼쪽 시프트 연산자와 마찬가지로, 옮길 값은 왼쪽에, 옮길 자릿수는 오른쪽에 적어요.

0b0100 >> 1
# => 0b0010

0b0100 >> 2
# => 0b0001

마찬가지로, 수가 음수라면 왼쪽으로 옮겨요.

0b0100 >> -1
# => 0b1000

이항 연산자

Crystal에는 비트 연산을 수행하는 3개의 이항 연산자(&, |, ^)와 ~ 연산자가 있어요.

비트 AND(&)

이항 AND 연산자(&)는 두 값에 대해 비트 AND를 수행해요. 첫 번째 값의 각 비트를 두 번째 값의 같은 위치에 있는 비트와 비교해요. 두 비트가 모두 1이면 결과 비트는 1이 돼요. 그렇지 않으면 0이 돼요.

0b0011 & 0b1010
# => 0b0010

비트 OR(|)

이항 OR 연산자(|)는 두 값에 대해 비트 OR을 수행해요. 이 연산자도 첫 번째 값의 각 비트를 두 번째 값의 같은 위치에 있는 비트와 비교해요. 둘 중 하나라도 1이면 결과 비트는 1이 돼요. 그렇지 않으면 0이 돼요.

0b0011 | 0b1010
# => 0b1011

비트 XOR(^)

이항 XOR 연산자(^)는 비트 XOR을 수행해요. 비트 AND, 비트 OR 연산자와 마찬가지로, 첫 번째 값의 각 비트를 두 번째 값의 같은 위치에 있는 비트와 비교해요. 둘 중 하나만 1이면 결과 비트는 1이 돼요. 그렇지 않으면 0이에요.

0b0011 ^ 0b1010
# => 0b1001

비트 NOT(~)

마지막으로, 비트 NOT 연산자(~)는 값의 각 비트를 뒤집어요. 다른 이항 연산자와 달리, 이 연산자는 단항 연산자로, 오른쪽에 있는 값에만 작용해요.

~0b1110_0010
# => 0b0001_1101

지침

친구가 중요한 비밀을 담은 메시지를 방금 보냈어요. 다른 사람들이 쉽게 읽지 못하게 하려고, 메시지는 일련의 비트 조작을 이용해 암호화되었어요. 메시지를 복호화할 프로그램을 작성해야 해요.

1. 비트를 다시 시프트하기

메시지를 복호화하는 첫 단계는 암호화 과정에서 시프트한 것을 비트를 왼쪽으로 되돌려 원래대로 돌리는 거예요. 시프트할 자릿수는 메시지마다 다를 수 있어요.

값과 왼쪽으로 시프트할 자릿수를 받는 Secrets.shift_back 메서드를 구현해 보세요.

Secrets.shift_back(0b0001, 2)
# => 0b0100

2. 비트 마스크 적용하기

다음 단계는 특정 비트의 값을 추출하기 위해 비트 마스크를 적용하는 거예요. 마스크는 값과 마스크 사이에서 비트 AND 연산을 수행해 적용해요.

값을 받아 마스크를 적용하는 Secrets.apply_mask 메서드를 구현해 보세요.

Secrets.apply_mask(0b0110, 0b0101)
# => 0b0100

3. 일부 비트 설정하기

비트를 왼쪽으로 시프트하면 새로운 0 비트가 몇 개 추가돼요. 이 새로운 비트 중 일부는 1로 설정해야 해요. 비트 OR 연산은 나머지는 그대로 두면서 특정 비트를 1로 설정할 때 유용해요.

두 값을 받아 비트 OR 연산을 수행하는 Secrets.set_bits 메서드를 구현해 보세요.

Secrets.set_bits(0b0110, 0b0101)
# => 0b111

4. XOR 되돌리기

암호화 과정의 일부는 약속된 값과 XOR을 적용해요. 원래 값으로 돌아가려면, 암호화된 값을 약속된 값과 다시 XOR하면 돼요. 그런데 오해 때문에 친구가 XOR을 적용하기 전에 약속된 값의 비트를 뒤집었어요 (즉, 약속된 값에 비트 NOT 연산을 적용했어요).

암호화된 값과 약속된 값을 받아 원래 값을 계산하는 Secrets.reverse_xor 메서드를 구현해 보세요.

Secrets.reverse_xor(0b1100, 0b0101)
# => 0b(0110)
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Crystal Exercism

비밀 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Crystal 트랙을 개념 26개연습 문제 142개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.