diff --git a/README.md b/README.md index 3176ffc..e013b9c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,14 @@ the letters A through Z (either lower or upper case) and whitespace. This way data to be encoded will never contain any numbers and numbers inside data to be decoded always represent the count for the following character. +## Debugging + +- Put `require Logger` at the top of the `RunLengthEncoding` module. +- Log values to the terminal using `Logger.debug inspect `. +- Use the interactive shell to try out things by running `iex -S mix`. +- In `iex` you can reload your module using `r RunLengthEncoding` + + ## Running tests Execute the tests with: @@ -31,13 +39,6 @@ Execute the tests with: $ mix test ``` -## Debugging - -- Put `require Logger` at the top of the `RunLengthEncoding` module. -- Log values to the terminal using `Logger.debug inspect `. -- Use the interactive shell to try out things by running `iex -S mix`. - - ### Pending tests In the test suites, all but the first test have been skipped. diff --git a/lib/run_length_encoding.ex b/lib/run_length_encoding.ex index d32c5a3..242a030 100644 --- a/lib/run_length_encoding.ex +++ b/lib/run_length_encoding.ex @@ -9,8 +9,42 @@ defmodule RunLengthEncoding do require Logger def encode(string) do + string + |> encode_rec(0) end + defp encode_rec(<> <> rest, count) when a == b do + encode_rec(<> <> rest, count + 1) + end + + defp encode_rec(<> <> rest, count) when count == 0 do + <> <> encode_rec(rest, 0) + end + + defp encode_rec(<> <> rest, count) do + to_string(count + 1) <> <> <> encode_rec(rest, 0) + end + + defp encode_rec(rest, _), do: rest + def decode(string) do + string + |> decode_rec(0) end + + defguard is_digit(char) when ?0 <= char and char <= ?9 + + defp decode_rec(<> <> rest, times) when is_digit(a) do + decode_rec(rest, times * 10 + String.to_integer(<>)) + end + + defp decode_rec(<> <> rest, 0) do + <> <> decode_rec(rest, 0) + end + + defp decode_rec(<> <> rest, times) do + String.duplicate(<>, times) <> decode_rec(rest, 0) + end + + defp decode_rec(rest, _), do: rest end diff --git a/test/run_length_encoding_test.exs b/test/run_length_encoding_test.exs index 68ca48c..dc3b826 100644 --- a/test/run_length_encoding_test.exs +++ b/test/run_length_encoding_test.exs @@ -6,64 +6,52 @@ defmodule RunLengthEncodingTest do assert RunLengthEncoding.encode("") === "" end - @tag :pending test "encode single characters only are encoded without count" do assert RunLengthEncoding.encode("XYZ") === "XYZ" end - @tag :pending test "encode string with no single characters" do assert RunLengthEncoding.encode("AABBBCCCC") == "2A3B4C" end - @tag :pending test "encode single characters mixed with repeated characters" do assert RunLengthEncoding.encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB") === "12WB12W3B24WB" end - @tag :pending test "encode multiple whitespace mixed in string" do assert RunLengthEncoding.encode(" hsqq qww ") === "2 hs2q q2w2 " end - @tag :pending test "encode lowercase characters" do assert RunLengthEncoding.encode("aabbbcccc") === "2a3b4c" end - @tag :pending test "decode empty string" do assert RunLengthEncoding.decode("") === "" end - @tag :pending test "decode single characters only" do assert RunLengthEncoding.decode("XYZ") === "XYZ" end - @tag :pending test "decode string with no single characters" do assert RunLengthEncoding.decode("2A3B4C") == "AABBBCCCC" end - @tag :pending test "decode single characters with repeated characters" do assert RunLengthEncoding.decode("12WB12W3B24WB") === "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" end - @tag :pending test "decode multiple whitespace mixed in string" do assert RunLengthEncoding.decode("2 hs2q q2w2 ") === " hsqq qww " end - @tag :pending test "decode lower case string" do assert RunLengthEncoding.decode("2a3b4c") === "aabbbcccc" end - @tag :pending test "encode followed by decode gives original string" do original = "zzz ZZ zZ" encoded = RunLengthEncoding.encode(original)