2024-06-29 04:20:33 +00:00
|
|
|
defmodule RotationalCipher do
|
2024-06-29 04:38:35 +00:00
|
|
|
@lower ?a..?z
|
|
|
|
@upper ?A..?Z
|
2024-06-29 04:20:33 +00:00
|
|
|
|
2024-06-29 04:38:35 +00:00
|
|
|
defguard is_lower(char) when char in @lower
|
|
|
|
defguard is_upper(char) when char in @upper
|
|
|
|
defguard is_letter(char) when char in @lower or char in @upper
|
2024-06-29 04:20:33 +00:00
|
|
|
|
2024-06-29 04:38:35 +00:00
|
|
|
defp rotate_char(char, shift) when is_lower(char) and is_lower(char + shift), do: char + shift
|
|
|
|
defp rotate_char(char, shift) when is_upper(char) and is_upper(char + shift), do: char + shift
|
|
|
|
defp rotate_char(char, shift) when is_letter(char), do: char + shift - 26
|
|
|
|
defp rotate_char(char, _shift) when not is_letter(char), do: char
|
2024-06-29 04:20:33 +00:00
|
|
|
|
|
|
|
@doc """
|
|
|
|
Given a plaintext and amount to shift by, return a rotated string.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
iex> RotationalCipher.rotate("Attack at dawn", 13)
|
|
|
|
"Nggnpx ng qnja"
|
|
|
|
"""
|
|
|
|
|
|
|
|
@spec rotate(text :: String.t(), shift :: integer) :: String.t()
|
|
|
|
def rotate(text, shift) do
|
|
|
|
text
|
2024-06-29 04:38:35 +00:00
|
|
|
|> to_char_list()
|
|
|
|
|> Enum.map(&rotate_char(&1, shift))
|
|
|
|
|> to_string()
|
2024-06-29 04:20:33 +00:00
|
|
|
end
|
|
|
|
end
|