rotational_chipher without transliteration table
This commit is contained in:
parent
9adeef7c61
commit
8d8a30b39c
|
@ -1,42 +1,15 @@
|
||||||
defmodule RotationalCipher do
|
defmodule RotationalCipher do
|
||||||
@moduledoc """
|
@lower ?a..?z
|
||||||
Generates a simple Caesar cipher by rotating the alphabet by a given amount.
|
@upper ?A..?Z
|
||||||
Use for that shifted alphabet generation function and transliteration table based on two alphabets.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@alphabet ?a..?z
|
defguard is_lower(char) when char in @lower
|
||||||
|> Enum.to_list()
|
defguard is_upper(char) when char in @upper
|
||||||
|> to_string()
|
defguard is_letter(char) when char in @lower or char in @upper
|
||||||
|> String.split("", trim: true)
|
|
||||||
|
|
||||||
# Generates a shifted alphabet based on the given shift amount.
|
defp rotate_char(char, shift) when is_lower(char) and is_lower(char + shift), do: char + shift
|
||||||
# If swaped is true, the function will return a map with the index as the key and the character as the value,
|
defp rotate_char(char, shift) when is_upper(char) and is_upper(char + shift), do: char + shift
|
||||||
# otherwise the function will return a map with the character as the key and the index as the value.
|
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
|
||||||
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
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Given a plaintext and amount to shift by, return a rotated string.
|
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()
|
@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
|
def rotate(text, shift) do
|
||||||
table = transliterate_table(shift)
|
|
||||||
|
|
||||||
text
|
text
|
||||||
|> String.graphemes()
|
|> to_char_list()
|
||||||
|> Enum.map(&rotate_char(&1, table))
|
|> Enum.map(&rotate_char(&1, shift))
|
||||||
|> Enum.join()
|
|> to_string()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue