Created
January 30, 2014 00:30
-
-
Save diogovk/8700256 to your computer and use it in GitHub Desktop.
compares the speed of concat using append, and recursive version.
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 ListOps do | |
# Please don't use any external modules (especially List) in your | |
# implementation. The point of this exercise is to create these basic functions | |
# yourself. | |
# | |
# Note that `++` is a function from an external module (Kernel, which is | |
# automatically important`) and so shouldn't be used either. | |
@spec count(list) :: non_neg_integer | |
def count(l) do | |
do_count(l,0) | |
end | |
defp do_count([], acc), do: acc | |
defp do_count([_head|tail], acc) do | |
do_count(tail,acc+1) | |
end | |
@spec reverse(list) :: list | |
def reverse(l) do | |
do_reverse(l,[]) | |
end | |
defp do_reverse([], acc), do: acc | |
defp do_reverse([head|tail], acc) do | |
do_reverse(tail, [head|acc]) | |
end | |
@spec map(list, (any -> any)) :: list | |
def map(l, f) do | |
reverse do_map(l, f, []) | |
end | |
defp do_map([],_, acc), do: acc | |
defp do_map([head|tail], f, acc) do | |
do_map(tail, f, [f.(head)|acc]) | |
end | |
@spec filter(list, (any -> as_boolean(term))) :: list | |
def filter(l, f) do | |
reverse do_filter(l, f, []) | |
end | |
defp do_filter([], _, acc), do: acc | |
defp do_filter([head|tail], f, acc) do | |
if f.(head) do | |
do_filter(tail, f, [head|acc]) | |
else | |
do_filter(tail, f, acc) | |
end | |
end | |
@type acc :: any | |
@spec reduce(list, acc, ((any, acc) -> acc)) :: acc | |
def reduce(l, acc, f) do | |
do_reduce(l, acc, f) | |
end | |
defp do_reduce([], acc, _), do: acc | |
defp do_reduce([head|tail], acc, f) do | |
do_reduce(tail, f.(head, acc), f) | |
end | |
@spec append(list, list) :: list | |
def append(a, b) do | |
do_append reverse(a), b | |
end | |
def do_append([], acc), do: acc | |
def do_append([head|tail], acc) do | |
do_append(tail,[head|acc]) | |
end | |
@spec concat([[any]]) :: [any] | |
def concat([]), do: [] | |
def concat(enums) do | |
reverse do_concat(enums, []) | |
end | |
defp do_concat([], acc) do | |
acc | |
end | |
defp do_concat([[]|tail], acc) do | |
do_concat(tail, acc) | |
end | |
defp do_concat([ [first_head|first_tail] | tail ], acc) do | |
do_concat([first_tail | tail], [first_head|acc]) | |
end | |
@spec concat_a([[any]]) :: [any] | |
def concat_a(ll) do | |
reverse(ll) |> | |
reduce([], &(append(&2, &1))) | |
end | |
def test1() do | |
concat(Enum.map(1..50000, &[&1])) | |
end | |
def test2() do | |
concat_a(Enum.map(1..50000, &[&1])) | |
end | |
end | |
IO.inspect(:timer.tc ListOps, :test1, [] ) | |
IO.inspect(:timer.tc ListOps, :test2, [] ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment