diff --git a/lib/list_ops.ex b/lib/list_ops.ex index 3010084..459d299 100644 --- a/lib/list_ops.ex +++ b/lib/list_ops.ex @@ -1,2 +1,16 @@ defmodule ListOps do + def count(l), do: reduce(l, 0, fn(_, acc) -> acc + 1 end) + + def reverse(l), do: reduce(l, [], &([&1|&2])) + + def map(l, f), do: reduce(l, [], &([f.(&1)|&2])) |> reverse + + def filter(l, f), do: reduce(l, [], &(if f.(&1) do [&1|&2] else &2 end)) |> reverse + + def reduce([], acc, _), do: acc + def reduce([h|t], acc, f), do: reduce(t, f.(h, acc), f) + + def append(l1, l2), do: concat([l1, l2]) + + def concat(l), do: reduce(l, [], fn(i, acc) -> reduce(i, acc, &([&1|&2])) end) |> reverse end diff --git a/test/list_ops_test.exs b/test/list_ops_test.exs index c16ecd3..5b83e96 100644 --- a/test/list_ops_test.exs +++ b/test/list_ops_test.exs @@ -1,6 +1,8 @@ defmodule ListOpsTest do use ExUnit.Case + defp odd?(n), do: rem(n, 2) == 1 + test "count of empty list" do assert ListOps.count([]) == 0 end @@ -25,85 +27,85 @@ defmodule ListOpsTest do assert ListOps.reverse(Enum.to_list(1..1_000_000)) == Enum.to_list(1_000_000..1) end - # test "map of empty list" do - # assert ListOps.map([], &(&1+1)) == [] - # end - # - # test "map of normal list" do - # assert ListOps.map([1,3,5,7], &(&1+1)) == [2,4,6,8] - # end - # - # test "map of huge list" do - # assert ListOps.map(Enum.to_list(1..1_000_000), &(&1+1)) == - # Enum.to_list(2..1_000_001) - # end - # - # test "filter of empty list" do - # assert ListOps.filter([], &odd?/1) == [] - # end - # - # test "filter of normal list" do - # assert ListOps.filter([1,2,3,4], &odd?/1) == [1,3] - # end - # - # test "filter of huge list" do - # assert ListOps.filter(Enum.to_list(1..1_000_000), &odd?/1) == - # Enum.map(1..500_000, &(&1*2-1)) - # end - # - # test "reduce of empty list" do - # assert ListOps.reduce([], 0, &(&1+&2)) == 0 - # end - # - # test "reduce of normal list" do - # assert ListOps.reduce([1,2,3,4], -3, &(&1+&2)) == 7 - # end - # - # test "reduce of huge list" do - # assert ListOps.reduce(Enum.to_list(1..1_000_000), 0, &(&1+&2)) == - # Enum.reduce(1..1_000_000, 0, &(&1+&2)) - # end - # - # test "reduce with non-commutative function" do - # assert ListOps.reduce([1,2,3,4], 10, fn x, acc -> acc - x end) == 0 - # end - # - # test "append of empty lists" do - # assert ListOps.append([], []) == [] - # end - # - # test "append of empty and non-empty list" do - # assert ListOps.append([], [1,2,3,4]) == [1,2,3,4] - # end - # - # test "append of non-empty and empty list" do - # assert ListOps.append([1,2,3,4], []) == [1,2,3,4] - # end - # - # test "append of non-empty lists" do - # assert ListOps.append([1,2,3], [4,5]) == [1,2,3,4,5] - # end - # - # test "append of huge lists" do - # assert ListOps.append(Enum.to_list(1..1_000_000), Enum.to_list(1_000_001..2_000_000)) == - # Enum.to_list(1..2_000_000) - # end - # - # test "concat of empty list of lists" do - # assert ListOps.concat([]) == [] - # end - # - # test "concat of normal list of lists" do - # assert ListOps.concat([[1,2],[3],[],[4,5,6]]) == [1,2,3,4,5,6] - # end - # - # test "concat of huge list of small lists" do - # assert ListOps.concat(Enum.map(1..1_000_000, &[&1])) == - # Enum.to_list(1..1_000_000) - # end - # - # test "concat of small list of huge lists" do - # assert ListOps.concat(Enum.map(0..9, &Enum.to_list((&1*100_000+1)..((&1+1)*100_000)))) == - # Enum.to_list(1..1_000_000) - # end + test "map of empty list" do + assert ListOps.map([], &(&1+1)) == [] + end + + test "map of normal list" do + assert ListOps.map([1,3,5,7], &(&1+1)) == [2,4,6,8] + end + + test "map of huge list" do + assert ListOps.map(Enum.to_list(1..1_000_000), &(&1+1)) == + Enum.to_list(2..1_000_001) + end + + test "filter of empty list" do + assert ListOps.filter([], &odd?/1) == [] + end + + test "filter of normal list" do + assert ListOps.filter([1,2,3,4], &odd?/1) == [1,3] + end + + test "filter of huge list" do + assert ListOps.filter(Enum.to_list(1..1_000_000), &odd?/1) == + Enum.map(1..500_000, &(&1*2-1)) + end + + test "reduce of empty list" do + assert ListOps.reduce([], 0, &(&1+&2)) == 0 + end + + test "reduce of normal list" do + assert ListOps.reduce([1,2,3,4], -3, &(&1+&2)) == 7 + end + + test "reduce of huge list" do + assert ListOps.reduce(Enum.to_list(1..1_000_000), 0, &(&1+&2)) == + Enum.reduce(1..1_000_000, 0, &(&1+&2)) + end + + test "reduce with non-commutative function" do + assert ListOps.reduce([1,2,3,4], 10, fn x, acc -> acc - x end) == 0 + end + + test "append of empty lists" do + assert ListOps.append([], []) == [] + end + + test "append of empty and non-empty list" do + assert ListOps.append([], [1,2,3,4]) == [1,2,3,4] + end + + test "append of non-empty and empty list" do + assert ListOps.append([1,2,3,4], []) == [1,2,3,4] + end + + test "append of non-empty lists" do + assert ListOps.append([1,2,3], [4,5]) == [1,2,3,4,5] + end + + test "append of huge lists" do + assert ListOps.append(Enum.to_list(1..1_000_000), Enum.to_list(1_000_001..2_000_000)) == + Enum.to_list(1..2_000_000) + end + + test "concat of empty list of lists" do + assert ListOps.concat([]) == [] + end + + test "concat of normal list of lists" do + assert ListOps.concat([[1,2],[3],[],[4,5,6]]) == [1,2,3,4,5,6] + end + + test "concat of huge list of small lists" do + assert ListOps.concat(Enum.map(1..1_000_000, &[&1])) == + Enum.to_list(1..1_000_000) + end + + test "concat of small list of huge lists" do + assert ListOps.concat(Enum.map(0..9, &Enum.to_list((&1*100_000+1)..((&1+1)*100_000)))) == + Enum.to_list(1..1_000_000) + end end