49 lines
1.1 KiB
Elixir
49 lines
1.1 KiB
Elixir
defmodule Atbash do
|
|
@letters ?a..?z
|
|
|> Enum.to_list
|
|
|> to_string
|
|
|> String.graphemes()
|
|
|
|
@digits ?0..?9
|
|
|> Enum.to_list
|
|
|> to_string
|
|
|> String.graphemes()
|
|
|
|
@table Map.new(Enum.zip(@letters, Enum.reverse(@letters)))
|
|
|
|
defguardp is_letter(char) when char in @letters
|
|
defguardp is_digit(char) when char in @digits
|
|
|
|
@doc """
|
|
Encode a given plaintext to the corresponding ciphertext
|
|
|
|
## Examples
|
|
|
|
iex> Atbash.encode("completely insecure")
|
|
"xlnko vgvob rmhvx fiv"
|
|
"""
|
|
@spec encode(String.t()) :: String.t()
|
|
def encode(plaintext) do
|
|
plaintext
|
|
|> transpose()
|
|
|> String.graphemes()
|
|
|> Enum.chunk_every(5)
|
|
|> Enum.join(" ")
|
|
end
|
|
|
|
@spec decode(String.t()) :: String.t()
|
|
def decode(cipher), do: transpose(cipher)
|
|
|
|
defp transpose(string) do
|
|
string
|
|
|> String.downcase()
|
|
|> String.graphemes()
|
|
|> Enum.map(&code/1)
|
|
|> Enum.join()
|
|
end
|
|
|
|
defp code(char) when is_digit(char), do: char
|
|
defp code(char) when is_letter(char), do: @table[char]
|
|
defp code(_char), do: nil
|
|
end
|