Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution #1

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lib/list_ops.ex
Original file line number Diff line number Diff line change
@@ -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
164 changes: 83 additions & 81 deletions test/list_ops_test.exs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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