exercism/elixir/rotational-cipher/lib/rotational_cipher.ex

30 lines
928 B
Elixir
Raw Normal View History

2024-06-29 04:20:33 +00:00
defmodule RotationalCipher do
@lower ?a..?z
@upper ?A..?Z
2024-06-29 04:20:33 +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
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
|> to_char_list()
|> Enum.map(&rotate_char(&1, shift))
|> to_string()
2024-06-29 04:20:33 +00:00
end
end