Skip to content

Instantly share code, notes, and snippets.

@petros
Last active August 31, 2022 13:53
Show Gist options
  • Save petros/8c6b0effcd78d9e1b3f1c9f4da7299b9 to your computer and use it in GitHub Desktop.
Save petros/8c6b0effcd78d9e1b3f1c9f4da7299b9 to your computer and use it in GitHub Desktop.
Top Secret - Elixir - Exercism
defmodule TopSecret do
@spec to_ast(String.t()) :: tuple()
def to_ast(string), do: Code.string_to_quoted!(string)
@spec decode_secret_message_part(tuple(), list()) :: tuple()
def decode_secret_message_part(ast, acc) when elem(ast, 0) in [:def, :defp] do
ast
|> elem(2)
|> Enum.at(0)
|> get_function_ast()
|> get_function_name_and_arity()
|> get_sliced_name()
|> get_secret_message_part(ast, acc)
end
def decode_secret_message_part(ast, acc), do: {ast, acc}
defp get_secret_message_part(name, ast, acc), do: {ast, [name | acc]}
defp get_function_ast(ast) when elem(ast, 0) == :when do
ast
|> elem(2)
|> Enum.at(0)
end
defp get_function_ast(ast), do: ast
defp get_function_name_and_arity(function_ast) do
fname =
function_ast
|> elem(0)
|> Atom.to_string()
{fname, get_arity(function_ast)}
end
defp get_arity(function_ast) when elem(function_ast, 2) == nil, do: -1
defp get_arity(function_ast) do
function_ast
|> elem(2)
|> Enum.count()
|> Kernel.-(1)
end
defp get_sliced_name({_fname, arity}) when arity == -1, do: ""
defp get_sliced_name({fname, arity}) when arity > -1, do: fname |> String.slice(0..arity)
@spec decode_secret_message(String.t()) :: String.t()
def decode_secret_message(string) do
string
|> to_ast()
|> Macro.postwalk([], &decode_secret_message_part/2)
|> Tuple.to_list()
|> Enum.at(1)
|> Enum.reverse()
|> Enum.join()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment