RosettaCodeData/Task/LZW-compression/Elixir/lzw-compression.elixir

40 lines
1.2 KiB
Text
Raw Permalink Normal View History

2015-11-18 06:14:39 +00:00
defmodule LZW do
2016-12-05 22:15:40 +01:00
@encode_map Enum.into(0..255, Map.new, &{[&1],&1})
@decode_map Enum.into(0..255, Map.new, &{&1,[&1]})
2015-11-18 06:14:39 +00:00
2016-12-05 22:15:40 +01:00
def encode(str), do: encode(to_char_list(str), @encode_map, 256, [])
defp encode([h], d, _, out), do: Enum.reverse([d[[h]] | out])
2015-11-18 06:14:39 +00:00
defp encode([h|t], d, free, out) do
2016-12-05 22:15:40 +01:00
val = d[[h]]
2015-11-18 06:14:39 +00:00
find_match(t, [h], val, d, free, out)
end
defp find_match([h|t], l, lastval, d, free, out) do
2016-12-05 22:15:40 +01:00
case Map.fetch(d, [h|l]) do
2015-11-18 06:14:39 +00:00
{:ok, val} -> find_match(t, [h|l], val, d, free, out)
2016-12-05 22:15:40 +01:00
:error -> d1 = Map.put(d, [h|l], free)
encode([h|t], d1, free+1, [lastval | out])
2015-11-18 06:14:39 +00:00
end
end
defp find_match([], _, lastval, _, _, out), do: Enum.reverse([lastval | out])
def decode([h|t]) do
2016-12-05 22:15:40 +01:00
val = @decode_map[h]
decode(t, val, 256, @decode_map, val)
2015-11-18 06:14:39 +00:00
end
defp decode([], _, _, _, l), do: Enum.reverse(l) |> to_string
defp decode([h|t], old, free, d, l) do
2019-09-12 10:33:56 -07:00
val = if h == free, do: old ++ [List.first(old)], else: d[h]
2015-11-18 06:14:39 +00:00
add = [List.last(val) | old]
2016-12-05 22:15:40 +01:00
d1 = Map.put(d, free, add)
2015-11-18 06:14:39 +00:00
decode(t, val, free+1, d1, val++l)
end
end
str = "TOBEORNOTTOBEORTOBEORNOT"
IO.inspect enc = LZW.encode(str)
IO.inspect dec = LZW.decode(enc)
IO.inspect str == dec