Created
December 9, 2014 16:05
-
-
Save diogovk/4bca024e23c9a715c41b to your computer and use it in GitHub Desktop.
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(enums) do | |
reverse do_concat(enums, []) | |
end | |
def concat(l1, l2) when is_list(l1) and is_list(l2) do | |
l1 ++ l2 | |
end | |
def concat(l1, l2) do | |
concat([l1,l2]) | |
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 | |
def measure_concat_time(enumerable) do | |
# perc_faster = fn (x,y) -> Float.round((x-y)/(x/100),1) end | |
#{time_new , result_new} = :timer.tc(ListOps, :concat, [enumerable]) | |
{time_orig, result_orig} = :timer.tc(Enum, :concat, [enumerable]) | |
IO.inspect time_orig | |
#if result_orig == result_new do | |
# IO.puts "Results Match" | |
#else | |
# IO.puts "Results Differ" | |
#end | |
#IO.puts("Original: #{time_orig}, New:#{time_new}, %Faster:#{perc_faster.(time_orig, time_new)}%") | |
end | |
end | |
#ListOps.measure_concat_time([]) | |
#ListOps.measure_concat_time([[]]) | |
#ListOps.measure_concat_time([[1,2,3],[4,5,6]]) | |
#ListOps.measure_concat_time([[1,2,3],[4,5,6],[],[],[],[],[],[7],[],[],[9],[10]]) | |
ListOps.measure_concat_time(Enum.map(0..30, &Enum.to_list((&1*100_000+1)..((&1+1)*100_000)))) | |
#ListOps.measure_concat_time(Enum.map(1..1_000_000, &[&1])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment