Skip to content

Instantly share code, notes, and snippets.

@DoggettCK
Last active August 25, 2016 20:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DoggettCK/8c6d8a20b14291ed4710 to your computer and use it in GitHub Desktop.
Save DoggettCK/8c6d8a20b14291ed4710 to your computer and use it in GitHub Desktop.
Generates encode and decode methods for base 2->62
for {base, name} <- (2..62 |> Enum.map(&({&1, "Base#{&1}" |> String.to_atom}))) do
# NOTE: Modules will be named :Base2, :Base3, ..., :Base62
defmodule name do
@moduledoc """
Automatically generated #{name} encode/decode functions
"""
@base base
@alphabet [?0..?9, ?a..?z, ?A..?Z]
|> Enum.flat_map(fn x -> x end)
|> to_string
|> String.split("", trim: true)
|> Enum.take(@base)
@validator Regex.compile!("^[#{ @alphabet |> Enum.join }]+$")
def alphabet, do: @alphabet |> Enum.join
for {char, ix} <- (@alphabet |> Enum.with_index) do
defp index_of(unquote(char)), do: unquote(ix)
defp char_at(unquote(ix)), do: unquote(char)
end
@doc """
Encodes an integer to a #{name} string
## Examples
\tiex> :#{name}.encode(123)
"""
def encode(int) when is_integer(int) do
encode(div(int, @base), rem(int, @base), "")
end
defp encode(0, mod, str), do: char_at(mod) <> str
defp encode(int, mod, str) when is_integer(int) do
encode(div(int, @base), rem(int, @base), char_at(mod) <> str)
end
@doc """
Decodes a #{name} string to an integer
## Examples
\tiex> :#{name}.decode("foo")
"""
def decode(str) when is_binary(str) do
case Regex.match?(@validator, str) do
false ->
{:error, "Not a valid #{unquote(name)} string"}
true ->
{:ok, str
|> String.reverse
|> String.split("", trim: true)
|> Enum.with_index
|> Enum.reduce(0, fn({char, index}, acc) -> acc + index_of(char) * (:math.pow(@base, index) |> round) end)
}
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment