Last active
March 20, 2017 19:46
-
-
Save mcelaney/9c5a480749117c062692d0c3bad55e93 to your computer and use it in GitHub Desktop.
March 20, 2017 PhillyDevSlack #DailyProgrammer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Thing do | |
@moduledoc """ | |
Sort a string by cardinality of repeating characters, then alphabetically within each partition created by cardinality sorting. | |
An example: "abcdddeeeffff" would be sorted "ffffdddeeeabc" | |
In the above, 'f' appears the most(4), so it comes first, followed by 'd's and 'e's (3), in alaphabetical order, since they have equal cardinality. Then follow 'a', 'b', and 'c' in alphabetical order since they all have the same cardinality(1). | |
Another example: "cardinality" would be sorted "aaiicdlnrty" | |
""" | |
@doc """ | |
## Example | |
iex> Thing.perform("cardinality") | |
"aaiicdlnrty" | |
iex> Thing.perform("abcdddeeeffff") | |
"ffffdddeeeabc" | |
""" | |
def perform(word) when is_binary(word) do | |
word |> String.graphemes |> perform | |
end | |
def perform(characters) do | |
characters | |
|> Enum.group_by(fn(letter) -> letter end) | |
|> Enum.reduce(%{}, fn({letter, incidents}, acc) -> | |
map_by_count(letter, Enum.count(incidents), acc) | |
end) | |
|> Enum.reduce("", fn({_, letter_map}, acc) -> | |
cobble_string(letter_map) <> acc | |
end) | |
end | |
@doc """ | |
This will take a letter and a count and then will add them to a given | |
accumulator value. | |
## Example | |
iex> Thing.map_by_count("b", 3, %{3 => %{"i" => "iii"}}) | |
%{3 => %{"b" => "bbb", "i" => "iii"}} | |
iex> Thing.map_by_count("b", 3, %{2 => %{"f" => "fff"}}) | |
%{2 => %{"f" => "fff"}, 3 => %{"b" => "bbb"}} | |
""" | |
def map_by_count(letter, count, acc) do | |
Map.put(acc, count, _map_by_count(letter, count, acc)) | |
end | |
def _map_by_count(letter, count, acc) do | |
if Map.has_key?(acc, count) do | |
Map.merge(acc[count], build_letter_map(letter, count)) | |
else | |
build_letter_map(letter, count) | |
end | |
end | |
@doc """ | |
This will take a letter and a count and return a map with a single key (the | |
letter) with aprintable value. | |
## Example | |
iex> Thing.build_letter_map("a", 3) | |
%{"a" => "aaa"} | |
""" | |
def build_letter_map(letter, count), do: %{letter => String.duplicate(letter, count)} | |
@doc """ | |
Accepts an enumerable which contains keys for each letter and strings as the | |
values. Takes the values for each and concats them. | |
Since enum orders the values this will always print in alphabetical order | |
## Example | |
iex> Thing.cobble_string(%{"l" => "ll", "c" => "cc", "n" => "nn"}) | |
"ccllnn" | |
""" | |
def cobble_string(letter_map) do | |
letter_map | |
|> Map.values | |
|> Enum.join("") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment