diff --git a/elixir/rotational-cipher/lib/rotational_cipher.ex b/elixir/rotational-cipher/lib/rotational_cipher.ex index a00ba8c..a18baf9 100644 --- a/elixir/rotational-cipher/lib/rotational_cipher.ex +++ b/elixir/rotational-cipher/lib/rotational_cipher.ex @@ -1,42 +1,15 @@ defmodule RotationalCipher do - @moduledoc """ - Generates a simple Caesar cipher by rotating the alphabet by a given amount. - Use for that shifted alphabet generation function and transliteration table based on two alphabets. - """ + @lower ?a..?z + @upper ?A..?Z - @alphabet ?a..?z - |> Enum.to_list() - |> to_string() - |> String.split("", trim: true) + 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 - # Generates a shifted alphabet based on the given shift amount. - # If swaped is true, the function will return a map with the index as the key and the character as the value, - # otherwise the function will return a map with the character as the key and the index as the value. - - defp alphabet(shift \\ 0, swaped \\ false) when shift < 26 and shift >= 0 do - @alphabet - |> Enum.with_index(fn char, index -> - position = if index + shift >= 26, do: index + shift - 26, else: index + shift - if swaped == true, do: {position, char}, else: {char, position} - end) - |> Enum.into(%{}) - end - - # Generates a transliteration table based on the given shift amount. - - defp transliterate_table(shift) do - transliterated = alphabet(shift, true) - - alphabet() - |> Enum.reduce(%{}, fn {char, index}, acc -> - Map.merge(acc, %{ - transliterated[index] => char, - String.upcase(transliterated[index]) => String.upcase(char) - }) - end) - end - - defp rotate_char(char, table), do: table[char] || char + 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 @doc """ Given a plaintext and amount to shift by, return a rotated string. @@ -47,14 +20,10 @@ defmodule RotationalCipher do """ @spec rotate(text :: String.t(), shift :: integer) :: String.t() - def rotate(text, shift) when shift == 0 or shift == 26, do: text - def rotate(text, shift) do - table = transliterate_table(shift) - text - |> String.graphemes() - |> Enum.map(&rotate_char(&1, table)) - |> Enum.join() + |> to_char_list() + |> Enum.map(&rotate_char(&1, shift)) + |> to_string() end end