비밀

비밀

학습 연습 문제

소개

비트 연산

비트 연산을 사용하면 이진수의 개별 자릿수를 조작할 수 있어요.

Elm은 Bitwise 모듈에서 여러 비트 연산자를 제공해요.

기본 연산

숫자의 개별 비트를 수정하는 것을 _마스킹_이라고 해요. _마스크_는 and, or, xor 같은 비트 연산자를 사용해 다른 숫자를 조작하기 위해 특정 비트가 특정한 방식으로 설정된 숫자예요.

and

and는 두 숫자를 결합할 때 두 숫자 모두에서 1인 비트만 남겨요. 이것은 개별 비트가 설정되었는지 확인하는 데 유용해요. 예를 들어, 숫자의 4번째 비트가 1로 설정되었는지 확인하려면 01000(10진수로 8) 마스크와 and 연산을 한 뒤 결과가 0이 아닌지 확인해요:

Bitwise.and 13 8 --> 8
--  13 = 01101
--   8 = 01000
-- and = 01000 = 8
or

or는 두 숫자 중 하나 또는 둘 다에서 1인 비트를 1로 설정해 두 숫자를 결합해요. 이것은 특정 비트를 1로 설정할 때 유용해요. 예를 들어, 10101의 2번째 비트를 설정하려면 마스크 00010과 or 연산을 해요:

Bitwise.or 21 2 --> 23
-- 21 = 10101
--  2 = 00010
-- or = 10111 = 23
배타적 논리합 (xor)

xor는 한 숫자에서는 1이고 다른 숫자에서는 0인 비트를 1로 설정해 두 숫자를 결합해요. 이것은 비트를 반대 값으로 뒤집을 때 유용해요:

Bitwise.xor 20 5 --> 17
--  20 = 10100
--   5 = 00101
-- xor = 10001 = 17
보수

complement는 숫자의 각 비트를 반전시켜요(0은 1이 되고, 1은 0이 돼요).

참고로, 이 연산의 결과 양수는 음수가 되고, 음수는 양수가 돼요. 이진수에서 음수는 가장 왼쪽 위치에 1로 표현되기 때문이에요.

Bitwise.complement 21 --> -22
--         21 = 00000000000000000000000000010101
-- complement = 11111111111111111111111111101010 = -22
비트 시프트

다음 연산자들은 비트를 지정된 위치 수만큼 왼쪽이나 오른쪽으로 이동시켜요. 이는 사실상 2의 거듭제곱을 곱하거나 나누는 것과 같아요.

shiftLeftBy는 비트를 왼쪽으로 이동시키고, 오른쪽에서 0으로 채워요. 예를 들어, 21을 왼쪽으로 3자리 시프트하려면:

Bitwise.shiftLeftBy 3 21 --> 168
--  21 = 10101
-- shiftLeftBy 3 = 10101000 = 168

이것은 21 * 2^3 = 21 * 2 * 2 * 2 = 168과 같아요.

shiftRightBy: 비트를 오른쪽으로 이동시켜요:

Bitwise.shiftRightBy 2 21 --> 5
--  21 = 10101
-- shiftRightBy 2 = 00101 = 5

오른쪽으로 2자리 시프트하는 것은 4로 정수 나눗셈을 하는 것과 같아요.

참고로, 이 함수는 가장 왼쪽 비트에 있는 값을 그대로 복제해요. 따라서 음수는 음수로 남아요:

Bitwise.shiftRightBy 3 -21 --> -3
--  -21 = 111...101011
-- shiftRightBy 3 = 111...11101 = -3

오른쪽으로 시프트하고 0으로 채우고 싶다면 shiftRightZfBy를 사용해요:

Bitwise.shiftRightZfBy 3 -21 --> 536870909
--  -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909

지침

친구가 방금 중요한 비밀이 담긴 메시지를 보냈어요. 다른 사람이 쉽게 읽지 못하게 하려고, 메시지는 일련의 비트 조작을 거쳐 암호화되었어요. 메시지를 복호화할 수 있도록 함수를 작성해야 해요.

1. 비트를 되돌리기

메시지를 복호화하는 첫 단계는, 암호화 과정에서 밀린 비트를 오른쪽으로 다시 밀어 되돌리는 거예요. 복호화 과정의 이후 단계에서는 왼쪽에서 0이 채워진다고 가정해요.

이동할 자릿수와 값을 받아 이동을 수행하는 shiftBack 함수를 구현해 보세요.

shiftBack 2 42 --> 10

2. 비트 설정하기

다음으로, 1로 설정해야 하는 비트가 있어요.

마스크와 값을 받아, 값의 비트를 1로 설정한 결과를 반환하는 setBits 함수를 구현해 보세요. 마스크의 비트가 1인 자리에서는 값의 비트도 1로 설정해야 해요. 나머지 비트는 그대로 유지해요.

setBits 66 212 --> 64

3. 특정 비트 뒤집기

암호화 과정에서 일부 비트는 뒤집혀요. 메시지를 복호화하려면 이 비트들을 다시 뒤집어야 해요.

마스크와 값을 받는 flipBits 함수를 구현해 보세요. 마스크는 값에서 어떤 비트를 뒤집을지 알려줘요. 마스크의 비트가 1이면, 값의 해당 비트를 뒤집어요. 나머지 비트는 그대로 유지해요.

flipBits 23 157 --> 138

4. 특정 비트 지우기

항상 0으로 복호화되는 비트도 있어요.

마스크와 값을 받는 clearBits 함수를 구현해 보세요. 마스크의 비트가 1인 자리에서는 value의 비트를 0으로 설정해야 해요. 나머지 비트는 그대로 유지해요.

clearBits 2 15 --> 13

5. 메시지 복호화하기

이제 필요한 함수를 모두 만들었으니, 친구의 메시지를 해독할 수 있어요. 다음 작업을 수행하는 decrypt 함수를 구현해 보세요:

  1. 친구가 태어난 연도(1996)로 비트를 설정해요
  2. 처음 만난 연도(2009)로 결과를 뒤집어요
  3. 함께 듣는 수업 수(5)만큼 비트를 되돌려 밀어요
  4. 첫 번째와 다섯 번째 비트를 지워요.
decrypt 380182 --> 11840

이전 과제에서 구현한 모든 함수를 사용해 decrypt를 구현해 보세요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Elm Exercism

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

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