Skip to content

Instantly share code, notes, and snippets.

@diogovk
Created December 9, 2014 16:05
Show Gist options
  • Save diogovk/4bca024e23c9a715c41b to your computer and use it in GitHub Desktop.
Save diogovk/4bca024e23c9a715c41b to your computer and use it in GitHub Desktop.
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