commit
70f02120a4
19 changed files with 264 additions and 272 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@
|
|||
erl_crash.dump
|
||||
*.ez
|
||||
/doc
|
||||
/docs
|
||||
|
|
12
.travis.yml
12
.travis.yml
|
@ -1,8 +1,14 @@
|
|||
language: elixir
|
||||
elixir:
|
||||
- 1.2.2
|
||||
- 1.5.1
|
||||
otp_release:
|
||||
- 18.2.1
|
||||
script: mix espec
|
||||
- 20.0
|
||||
script:
|
||||
- mix test
|
||||
- mix credo --strict
|
||||
- MIX_ENV=docs mix inch --pedantic
|
||||
after_script:
|
||||
- mix deps.get --only docs
|
||||
- MIX_ENV=docs mix inch.report
|
||||
env:
|
||||
- MIX_ENV=test
|
||||
|
|
|
@ -20,7 +20,7 @@ If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
|||
1. Add heap to your list of dependencies in `mix.exs`:
|
||||
|
||||
def deps do
|
||||
[{:heap, "~> 1.0.1"}]
|
||||
[{:heap, "~> 1.1.0"}]
|
||||
end
|
||||
|
||||
## Examples
|
||||
|
|
189
lib/heap.ex
189
lib/heap.ex
|
@ -1,5 +1,5 @@
|
|||
defmodule Heap do
|
||||
defstruct h: nil, n: 0, d: nil
|
||||
defstruct data: nil, size: 0, comparator: nil
|
||||
@moduledoc """
|
||||
A heap is a special tree data structure. Good for sorting and other magic.
|
||||
|
||||
|
@ -9,91 +9,192 @@ defmodule Heap do
|
|||
@type t :: %Heap{}
|
||||
|
||||
@doc """
|
||||
Create an empty min heap.
|
||||
Create an empty min `Heap`.
|
||||
|
||||
A min heap is a heap tree which always has the smallest value at the root.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.min())
|
||||
...> |> Heap.root()
|
||||
1
|
||||
"""
|
||||
@spec min() :: Heap.t
|
||||
def min(), do: Heap.new(:>)
|
||||
@spec min() :: t
|
||||
def min, do: Heap.new(:>)
|
||||
|
||||
@doc """
|
||||
Create an empty max heap.
|
||||
Create an empty max `Heap`.
|
||||
|
||||
A max heap is a heap tree which always has the largest value at the root.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.max())
|
||||
...> |> Heap.root()
|
||||
10
|
||||
"""
|
||||
@spec max() :: Heap.t
|
||||
def max(), do: Heap.new(:<)
|
||||
@spec max() :: t
|
||||
def max, do: Heap.new(:<)
|
||||
|
||||
@doc """
|
||||
Create an empty heap.
|
||||
Create an empty `Heap` with the default comparator (`>`).
|
||||
|
||||
Defaults to `>`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Heap.new()
|
||||
...> |> Heap.comparator()
|
||||
:>
|
||||
"""
|
||||
@spec new() :: Heap.t
|
||||
@spec new(:> | :<) :: Heap.t
|
||||
def new(direction \\ :>), do: %Heap{d: direction}
|
||||
@spec new() :: t
|
||||
def new, do: %Heap{comparator: :>}
|
||||
|
||||
@doc """
|
||||
Test if the heap is empty.
|
||||
Create an empty heap with a specific comparator.
|
||||
|
||||
Provide a `comparator` option, which can be either `:<` or `:>` to indicate
|
||||
that the `Heap` should use Elixir's normal `<` or `>` comparison functions.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Heap.new(:<)
|
||||
...> |> Heap.comparator()
|
||||
:<
|
||||
"""
|
||||
@spec empty?(Heap.t) :: boolean()
|
||||
def empty?(%Heap{h: nil, n: 0}), do: true
|
||||
@spec new(:> | :<) :: t
|
||||
def new(:>), do: %Heap{comparator: :>}
|
||||
def new(:<), do: %Heap{comparator: :<}
|
||||
|
||||
@doc """
|
||||
Test if `heap` is empty.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Heap.new()
|
||||
...> |> Heap.empty?()
|
||||
true
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.empty?()
|
||||
false
|
||||
"""
|
||||
@spec empty?(t) :: boolean()
|
||||
def empty?(%Heap{data: nil, size: 0}), do: true
|
||||
def empty?(%Heap{}), do: false
|
||||
|
||||
@doc """
|
||||
Test if the heap contains the element <elem>
|
||||
Test if the `heap` contains the element `value`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.member?(11)
|
||||
false
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.member?(7)
|
||||
true
|
||||
"""
|
||||
@spec member?(Heap.t, any()) :: boolean()
|
||||
def member?(%Heap{}=heap, value) do
|
||||
@spec member?(t, any()) :: boolean()
|
||||
def member?(%Heap{} = heap, value) do
|
||||
root = Heap.root heap
|
||||
heap = Heap.pop heap
|
||||
has_member? heap, root, value
|
||||
end
|
||||
|
||||
@doc """
|
||||
Push a new element into the heap.
|
||||
Push a new `value` into `heap`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Heap.new()
|
||||
...> |> Heap.push(13)
|
||||
...> |> Heap.root()
|
||||
13
|
||||
"""
|
||||
@spec push(Heap.t, any()) :: Heap.t
|
||||
def push(%Heap{h: h, n: n, d: d}, v), do: %Heap{h: meld(h, {v, []}, d), n: n + 1, d: d}
|
||||
@spec push(t, any()) :: t
|
||||
def push(%Heap{data: h, size: n, comparator: d}, value), do: %Heap{data: meld(h, {value, []}, d), size: n + 1, comparator: d}
|
||||
|
||||
@doc """
|
||||
Pop the root element off the heap and discard it.
|
||||
Pop the root element off `heap` and discard it.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.pop()
|
||||
...> |> Heap.root()
|
||||
2
|
||||
"""
|
||||
@spec pop(Heap.t) :: Heap.t
|
||||
def pop(%Heap{h: nil, n: 0}), do: nil
|
||||
def pop(%Heap{h: {_, q}, n: n, d: d}), do: %Heap{h: pair(q, d), n: n - 1, d: d}
|
||||
@spec pop(t) :: t
|
||||
def pop(%Heap{data: nil, size: 0} = _heap), do: nil
|
||||
def pop(%Heap{data: {_, q}, size: n, comparator: d} = _heap), do: %Heap{data: pair(q, d), size: n - 1, comparator: d}
|
||||
|
||||
@doc """
|
||||
Return the element at the root of the heap.
|
||||
Return the element at the root of `heap`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Heap.new()
|
||||
...> |> Heap.root()
|
||||
nil
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.root()
|
||||
1
|
||||
"""
|
||||
@spec root(Heap.t) :: any()
|
||||
def root(%Heap{h: {v, _}}), do: v
|
||||
def root(%Heap{h: nil, n: 0}), do: nil
|
||||
@spec root(t) :: any()
|
||||
def root(%Heap{data: {v, _}} = _heap), do: v
|
||||
def root(%Heap{data: nil, size: 0} = _heap), do: nil
|
||||
|
||||
@doc """
|
||||
Return the number of elements in the heap.
|
||||
Return the number of elements in `heap`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.size()
|
||||
10
|
||||
"""
|
||||
@spec size(Heap.t) :: non_neg_integer()
|
||||
def size(%Heap{n: n}), do: n
|
||||
@spec size(t) :: non_neg_integer()
|
||||
def size(%Heap{size: n}), do: n
|
||||
|
||||
@doc """
|
||||
Quickly sort an enumerable with a heap.
|
||||
Return the comparator `heap` is using for insert comparisons.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Heap.new(:<)
|
||||
...> |> Heap.comparator()
|
||||
:<
|
||||
"""
|
||||
@spec sort(Enum.t) :: List.t
|
||||
@spec sort(Enum.t, :< | :>) :: List.t
|
||||
def sort(enum, direction \\ :>) do
|
||||
enum
|
||||
|> Enum.into(Heap.new(direction))
|
||||
|> Enum.to_list
|
||||
end
|
||||
@spec comparator(t) :: :< | :>
|
||||
def comparator(%Heap{comparator: d}), do: d
|
||||
|
||||
defp meld(nil, queue, _), do: queue
|
||||
defp meld(queue, nil, _), do: queue
|
||||
|
||||
defp meld({k0,l0}, {k1,_}=r, :>) when k0 < k1, do: {k0, [r | l0]}
|
||||
defp meld({_,_}=l, {k1,r0}, :>), do: {k1, [l | r0]}
|
||||
|
||||
defp meld({k0,l0}, {k1,_}=r, :<) when k0 > k1, do: {k0, [r | l0]}
|
||||
defp meld({_,_}=l, {k1,r0}, :<), do: {k1, [l | r0]}
|
||||
defp meld({k0, l0}, {k1, _} = r, :>) when k0 < k1, do: {k0, [r | l0]}
|
||||
defp meld({_, _} = l, {k1, r0}, :>), do: {k1, [l | r0]}
|
||||
|
||||
defp meld({k0, l0}, {k1, _} = r, :<) when k0 > k1, do: {k0, [r | l0]}
|
||||
defp meld({_, _} = l, {k1, r0}, :<), do: {k1, [l | r0]}
|
||||
|
||||
defp pair([], _), do: nil
|
||||
defp pair([q], _), do: q
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
defimpl Collectable, for: Heap do
|
||||
|
||||
def into heap do
|
||||
@doc """
|
||||
Collect an enumerable into a heap.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..500
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Heap.root
|
||||
1
|
||||
"""
|
||||
@spec into(Heap.t) :: {list, function}
|
||||
def into(heap) do
|
||||
{heap, fn
|
||||
(h, {:cont, v}) -> Heap.push h, v
|
||||
(h, {:cont, v}) -> Heap.push(h, v)
|
||||
(h, :done) -> h
|
||||
(_, :halt) -> :ok
|
||||
end}
|
||||
|
|
|
@ -1,23 +1,63 @@
|
|||
defimpl Enumerable, for: Heap do
|
||||
|
||||
def count heap do
|
||||
@doc """
|
||||
Returns the number of elements in a heap.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..500
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Enum.count()
|
||||
500
|
||||
"""
|
||||
@spec count(Heap.t) :: non_neg_integer
|
||||
def count(heap) do
|
||||
{:ok, Heap.size heap}
|
||||
end
|
||||
|
||||
def member? heap, v do
|
||||
{:ok, Heap.member?(heap, v)}
|
||||
@doc """
|
||||
Returns true if value is a contained in the heap.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..500
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Enum.member?(250)
|
||||
true
|
||||
|
||||
iex> 1..500
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Enum.member?(750)
|
||||
false
|
||||
"""
|
||||
@spec member?(Heap.t, term) :: boolean
|
||||
def member?(heap, value) do
|
||||
{:ok, Heap.member?(heap, value)}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Allows reduction to be applied to Heaps.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..500
|
||||
...> |> Enum.shuffle()
|
||||
...> |> Enum.into(Heap.new())
|
||||
...> |> Enum.filter(&(Integer.mod(&1, 2) == 0))
|
||||
...> |> Enum.count()
|
||||
250
|
||||
"""
|
||||
@spec reduce(Heap.t, Enumerable.acc, Enumerable.reducer) :: Enumerable.result
|
||||
def reduce(_, {:halt, acc}, _fun), do: {:halted, acc}
|
||||
def reduce(heap, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(heap, &1, fun)}
|
||||
def reduce(heap, {:cont, acc}, fun) do
|
||||
case Heap.root heap do
|
||||
case Heap.root(heap) do
|
||||
nil ->
|
||||
{:done, acc}
|
||||
root ->
|
||||
heap = Heap.pop heap
|
||||
heap = Heap.pop(heap)
|
||||
reduce(heap, fun.(root, acc), fun)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
defimpl Inspect, for: Heap do
|
||||
import Inspect.Algebra
|
||||
|
||||
def inspect heap, opts do
|
||||
concat [
|
||||
"#Heap<",
|
||||
to_doc(Enum.to_list(heap), opts),
|
||||
">"
|
||||
]
|
||||
@doc """
|
||||
Format the heap nicely for inspection.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> 1..10
|
||||
...> |> Enum.into(Heap.max())
|
||||
...> |> inspect
|
||||
"#Heap<[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]>"
|
||||
"""
|
||||
@spec inspect(Heap.t, Inspect.Opts.t) :: Inspect.Algebra.t
|
||||
def inspect(heap, opts) do
|
||||
concat(["#Heap<", to_doc(Enum.to_list(heap), opts), ">"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
26
mix.exs
26
mix.exs
|
@ -3,14 +3,13 @@ defmodule Heap.Mixfile do
|
|||
|
||||
def project do
|
||||
[app: :heap,
|
||||
version: "1.0.1",
|
||||
description: description,
|
||||
elixir: "~> 1.2",
|
||||
version: "1.1.0",
|
||||
description: description(),
|
||||
elixir: "~> 1.5",
|
||||
build_embedded: Mix.env == :prod,
|
||||
start_permanent: Mix.env == :prod,
|
||||
preferred_cli_env: [espec: :test],
|
||||
package: package,
|
||||
deps: deps]
|
||||
package: package(),
|
||||
deps: deps()]
|
||||
end
|
||||
|
||||
# Configuration for the OTP application
|
||||
|
@ -21,18 +20,12 @@ defmodule Heap.Mixfile do
|
|||
end
|
||||
|
||||
def description do
|
||||
"""
|
||||
Small composable Heap implementation. Heaps sort elements at insert time.
|
||||
They're good for:
|
||||
* Scientific computing
|
||||
* Statistics
|
||||
* Priority queues
|
||||
"""
|
||||
"Small composable Heap implementation. Heaps sort elements at insert time."
|
||||
end
|
||||
|
||||
def package do
|
||||
[
|
||||
maintainers: [ "James Harton <james@messagerocket.co>" ],
|
||||
maintainers: [ "James Harton <james@automat.nz>" ],
|
||||
licenses: [ "MIT" ],
|
||||
links: %{
|
||||
"GitHub" => "https://github.com/jamesotron/heap",
|
||||
|
@ -52,8 +45,9 @@ defmodule Heap.Mixfile do
|
|||
# Type "mix help deps" for more examples and options
|
||||
defp deps do
|
||||
[
|
||||
{:espec, "~> 0.8.11", only: :test},
|
||||
{:ex_doc, "~> 0.11.4", only: :dev}
|
||||
{:ex_doc, ">= 0.0.0", only: :dev},
|
||||
{:credo, "~> 0.6", only: ~w(dev test)a},
|
||||
{:inch_ex, "~> 0.5", only: :docs}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
10
mix.lock
10
mix.lock
|
@ -1,3 +1,7 @@
|
|||
%{"espec": {:hex, :espec, "0.8.15", "a3427bc1e7984caa5f23dc25316e869260b10c2336bf5bb2b928638ad224c7a8", [:mix], [{:meck, "~> 0.8.4", [hex: :meck, optional: false]}]},
|
||||
"ex_doc": {:hex, :ex_doc, "0.11.4", "a064bdb720594c3745b94709b17ffb834fd858b4e0c1f48f37c0d92700759e02", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]},
|
||||
"meck": {:hex, :meck, "0.8.4", "59ca1cd971372aa223138efcf9b29475bde299e1953046a0c727184790ab1520", [:rebar, :make], []}}
|
||||
%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []},
|
||||
"credo": {:hex, :credo, "0.8.6", "335f723772d35da499b5ebfdaf6b426bfb73590b6fcbc8908d476b75f8cbca3f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]},
|
||||
"espec": {:hex, :espec, "0.8.28", "f002710673d215876c4ca6fc74cbf5e330954badea7389d2284d2050940f1779", [:mix], [{:meck, "~> 0.8.4", [hex: :meck, optional: false]}]},
|
||||
"ex_doc": {:hex, :ex_doc, "0.11.5", "0dc51cb84f8312162a2313d6c71573a9afa332333d8a332bb12540861b9834db", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]},
|
||||
"inch_ex": {:hex, :inch_ex, "0.5.6", "418357418a553baa6d04eccd1b44171936817db61f4c0840112b420b8e378e67", [:mix], [{:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, optional: false]}]},
|
||||
"meck": {:hex, :meck, "0.8.8", "eeb3efe811d4346e1a7f65b2738abc2ad73cbe1a2c91b5dd909bac2ea0414fa6", [:rebar3], []},
|
||||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
defmodule HeapCollectableSpec do
|
||||
use ESpec
|
||||
|
||||
describe "into" do
|
||||
let :source, do: 1..500
|
||||
subject do: source |> Enum.into(Heap.new)
|
||||
|
||||
it "inserts into the heap" do
|
||||
expect(Heap.size subject) |> to(eq 500)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,34 +0,0 @@
|
|||
defmodule HeapEnumerableSpec do
|
||||
use ESpec
|
||||
|
||||
describe "count" do
|
||||
let :heap, do: Enum.into(1..500, Heap.new)
|
||||
subject do: Enum.count heap
|
||||
|
||||
it do: is_expected |> to(eq 500)
|
||||
end
|
||||
|
||||
describe "member?" do
|
||||
let :heap, do: Heap.new
|
||||
subject do: Enum.member? heap, 13
|
||||
|
||||
context "When the value is in the heap" do
|
||||
let :heap, do: Heap.new |> Heap.push(13)
|
||||
|
||||
it do: is_expected |> to(be_true)
|
||||
end
|
||||
|
||||
context "When the value is not in the heap" do
|
||||
it do: is_expected |> to(be_false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "reduce" do
|
||||
let :heap, do: Enum.into(1..500, Heap.new)
|
||||
subject do: Enum.filter heap, fn(i) -> rem(i, 2) == 0 end
|
||||
|
||||
it do: is_expected |> to(have_min 2)
|
||||
it do: is_expected |> to(have_max 500)
|
||||
it do: is_expected |> to(have_count 250)
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
defmodule HeapInspectSpec do
|
||||
use ESpec
|
||||
|
||||
describe "inspect" do
|
||||
let :heap, do: Enum.into(1..5, Heap.new)
|
||||
subject do: inspect heap
|
||||
|
||||
it do: is_expected |> to(eq "#Heap<[1, 2, 3, 4, 5]>")
|
||||
end
|
||||
end
|
|
@ -1,123 +0,0 @@
|
|||
defmodule HeapSpec do
|
||||
use ESpec
|
||||
|
||||
describe "new" do
|
||||
subject do: Heap.new
|
||||
|
||||
it do: is_expected |> to(be_struct Heap)
|
||||
|
||||
it "is empty" do
|
||||
expect(Heap.empty? subject) |> to(be_true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "min" do
|
||||
subject do: Heap.min
|
||||
|
||||
it do: is_expected |> to(be_struct Heap)
|
||||
|
||||
it "is empty" do
|
||||
expect(Heap.empty? subject) |> to(be_true)
|
||||
end
|
||||
|
||||
it "has the correct sort direction" do
|
||||
expect(subject.d) |> to(eq :>)
|
||||
end
|
||||
end
|
||||
|
||||
describe "max" do
|
||||
subject do: Heap.max
|
||||
|
||||
it do: is_expected |> to(be_struct Heap)
|
||||
|
||||
it "is empty" do
|
||||
expect(Heap.empty? subject) |> to(be_true)
|
||||
end
|
||||
|
||||
it "has the correct sort direction" do
|
||||
expect(subject.d) |> to(eq :<)
|
||||
end
|
||||
end
|
||||
|
||||
describe "empty?" do
|
||||
subject do: Heap.empty? heap
|
||||
|
||||
context "When the heap is empty" do
|
||||
let :heap, do: Heap.new
|
||||
|
||||
it do: is_expected |> to(be_true)
|
||||
end
|
||||
|
||||
context "When the heap contains elements" do
|
||||
let :heap, do: Heap.new |> Heap.push(13)
|
||||
|
||||
it do: is_expected |> to(be_false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "member?" do
|
||||
subject do: heap |> Heap.member?(13)
|
||||
|
||||
context "When the heap contains the element" do
|
||||
let :heap, do: Heap.new |> Heap.push(13)
|
||||
|
||||
it do: is_expected |> to(be_true)
|
||||
end
|
||||
|
||||
context "When the heap does not contain the element" do
|
||||
let :heap, do: Heap.new
|
||||
|
||||
it do: is_expected |> to(be_false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "push" do
|
||||
let :heap, do: Heap.new
|
||||
subject do: heap |> Heap.push(13)
|
||||
|
||||
it "adds the element to the heap" do
|
||||
expect(subject |> Heap.member?(13)) |> to(be_true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "pop" do
|
||||
let :heap, do: Heap.new |> Heap.push(13) |> Heap.push(14)
|
||||
subject do: Heap.pop heap
|
||||
|
||||
it "pops the root element off the heap" do
|
||||
expect(Heap.root heap) |> to(eq 13)
|
||||
expect(Heap.root subject) |> to(eq 14)
|
||||
end
|
||||
end
|
||||
|
||||
describe "root" do
|
||||
let :heap, do: Heap.new |> Heap.push(13)
|
||||
subject do: Heap.root heap
|
||||
|
||||
it do: is_expected |> to(eq 13)
|
||||
end
|
||||
|
||||
describe "size" do
|
||||
let :heap, do: Heap.new |> Heap.push(13) |> Heap.push(14)
|
||||
subject do: Heap.size heap
|
||||
|
||||
it do: is_expected |> to(eq 2)
|
||||
end
|
||||
|
||||
describe "sort" do
|
||||
let :source, do: Enum.shuffle(1..500)
|
||||
subject do: Heap.sort source, direction
|
||||
|
||||
context "When the direction is `:>`" do
|
||||
let :direction, do: :>
|
||||
|
||||
it do: is_expected |> to(eq Enum.to_list(1..500))
|
||||
end
|
||||
|
||||
context "When the direction is `:<`" do
|
||||
let :direction, do: :<
|
||||
|
||||
it do: is_expected |> to(eq Enum.to_list(1..500) |> Enum.reverse)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
ESpec.start
|
||||
|
||||
ESpec.configure fn(config) ->
|
||||
config.before fn ->
|
||||
{:shared, hello: :world}
|
||||
end
|
||||
|
||||
config.finally fn(_shared) ->
|
||||
:ok
|
||||
end
|
||||
end
|
4
test/heap/collectable_test.exs
Normal file
4
test/heap/collectable_test.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule CollectableHeapTest do
|
||||
use ExUnit.Case
|
||||
doctest Collectable.Heap
|
||||
end
|
4
test/heap/enumerable_test.exs
Normal file
4
test/heap/enumerable_test.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule EnumerableHeapTest do
|
||||
use ExUnit.Case
|
||||
doctest Enumerable.Heap
|
||||
end
|
4
test/heap/inspect_test.exs
Normal file
4
test/heap/inspect_test.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule InspectHeapTest do
|
||||
use ExUnit.Case
|
||||
doctest Inspect.Heap
|
||||
end
|
4
test/heap_test.exs
Normal file
4
test/heap_test.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule HeapTest do
|
||||
use ExUnit.Case
|
||||
doctest Heap
|
||||
end
|
1
test/test_helper.exs
Normal file
1
test/test_helper.exs
Normal file
|
@ -0,0 +1 @@
|
|||
ExUnit.start()
|
Loading…
Reference in a new issue