Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

나만의 카이사르 암호(Caesar Cipher) 인코더 만드는 방법

카이사르 암호(Caesar Cipher)에 대해 들어본 적 있으신가요?

율리우스 카이사르(Julius Caesar)는 바로 이 기법을 사용해 적에게 보내는 비밀 메시지를 숨겼다고 합니다!

카이사르 암호는 가장 원시적인 암호화 기법 중 하나로, 그 핵심 아이디어는 아주 간단합니다. 바로 알파벳 문자를 x개 위치만큼 회전(밀기)시키는 것입니다.

예를 들어 x = 1이라면 'A'는 'B'로, 'C'는 'D'로 바뀌는 식입니다.

나만의 카이사르 암호(Caesar Cipher) 인코더 만드는 방법

그렇다면 이것을 코드로 어떻게 구현할 수 있을까요?

생각보다 어렵지 않습니다. 핵심은 문자를 숫자(ASCII 코드)로 표현할 수 있다는 점을 활용하는 것입니다. 이렇게 하면 문자를 회전시키는 작업이 단순히 두 숫자를 더하는 문제로 바뀝니다.

나만의 카이사르 암호 변환기 만들기

먼저 입력 문자열을 정수 배열로 변환하는 것부터 시작하겠습니다.

ascii = "test".chars.map(&:ord)

코드를 하나씩 살펴보겠습니다.

chars 메서드는 문자열을 문자 배열로 분리하고 열거자(enumerator)를 반환합니다. 덕분에 그 배열에 바로 map을 호출할 수 있습니다.

map 메서드는 배열의 모든 요소를 일괄적으로 변환하고 싶을 때 매우 유용합니다. map의 반환값은 변환된 요소들로 구성된 새로운 배열입니다.

참고로 이 문법은 Ruby 1.9 이상에서 지원되며, 다음 코드와 동일하게 동작합니다.

ascii = "test".chars.map { |c| c.ord }

모든 문자를 해당 ASCII 값으로 바꾸고 싶기 때문에, 배열의 각 요소에 ord 메서드를 호출합니다.

위 예제의 출력 결과는 다음과 같습니다.

[116, 101, 115, 116]

회전(Rotation) 단계

좋습니다! 이제 다음 단계는 원하는 만큼의 회전 수를 더하는 것입니다. 역시 map을 사용하면 됩니다.

shifted = ascii.map { |c| c + 5 }
=> [121, 106, 120, 121]

이제 숫자들을 다시 문자로 되돌린 뒤 하나로 연결(join)하면, 암호화된 문자열을 얻을 수 있습니다.

shifted.map { |c| c.chr }.join
=> "yjxy"

원래 문자열을 복구하려면 같은 절차를 반대 방향, 즉 왼쪽으로 밀면 됩니다.

여기서 중요한 점은 처음에 사용한 것과 동일한 위치 수만큼 밀어야 한다는 것입니다. 그렇지 않으면 원래 데이터를 제대로 복구할 수 없습니다.

완성 코드와 대안 버전

완성된 카이사르 암호 코드는 여기서 확인할 수 있습니다.

이 코드는 주어진 문자열에 대해 가능한 26가지 모든 반복 결과를 생성하며, 알파벳 끝에서 처음으로 넘어가는 래핑(wrapping)까지 처리합니다. 본문의 예제에는 이 부분이 포함되어 있지 않습니다.

또한 Array#rotate를 활용한 대안 버전도 준비되어 있습니다.

함께 읽으면 좋은 글:
루비 문자열 포매팅(Ruby String Formatting)