Packages

Berg is a Minimum Heap just for Integers

Current section

Files

Jump to
berg lib berg.ex
Raw

lib/berg.ex

defmodule Berg do
@moduledoc """
A Minimum Heap for Integers
![The Tatra Range](./tatra.jpg)
"""
@typedoc """
A Minimum Heap
"""
@opaque t :: {
value :: :infinity | integer,
children :: list
}
@typedoc """
An Element (just an Integer)
"""
@type element :: integer
@doc """
A _zero_ heap
"""
@spec zero :: __MODULE__.t
def zero do
:heap.zero
end
@doc """
Predicate: is this the _zero_ heap?
## Example
iex> Berg.zero? Berg.zero()
true
"""
@spec zero?(__MODULE__.t) :: boolean
def zero?(x) do
:heap.zero(x)
end
@doc """
A Heap w/ just one element
## Example
iex> Berg.zero? Berg.unary(4)
false
"""
@spec unary(element) :: __MODULE__.t
def unary(x) do
:heap.unary(x)
end
@doc """
The smallest element of the heap
## Example
iex> l = [42, 16, 8, 4, 15, 23]
iex> h = Berg.heapify l
iex> Berg.root h
4
"""
@spec root(__MODULE__.t) :: element
def root(x) do
:heap.peak(x)
end
@doc """
A heap whose smallest element is the minimum of the element in
question and the smallest element of the heap in question
## Example
iex> l = [16, 8, 15, 23]
iex> h = Berg.heapify l
iex> i = h |> Berg.insert(4) |> Berg.insert(42)
iex> Berg.root(i)
4
"""
@spec insert(__MODULE__.t, element) :: __MODULE__.t
def insert(x, y) do
:heap.insert(y, x)
end
@doc """
The heap in question w/o the smallest element
## Example
iex> l = [42, 16, 8, 4, 15, 23]
iex> h = Berg.heapify l
iex> t = Berg.trunk h
iex> Berg.listify(t)
[8, 15, 16, 23, 42]
"""
def trunk(x) do
elem(extract(x), 0)
end
@doc """
A heap alongside an element where that element would be the smallest
if it were in the heap
## Example
iex> l = [42, 16, 8, 4, 15, 23]
iex> h = Berg.heapify l
iex> {t, e} = Berg.extract h
iex> Berg.listify t
[8, 15, 16, 23, 42]
iex> e
4
"""
@spec extract(__MODULE__.t) :: {__MODULE__.t, element}
def extract(x) do
:heap.extract(x)
end
@doc """
A heap with the same elements as the list in question
"""
@spec heapify(list(integer)) :: __MODULE__.t
def heapify(x), do: heapify(x, Berg.zero())
defp heapify([], z) do
z
end
defp heapify([x|y], z) do
heapify(y, Berg.insert(z, x))
end
@doc """
A list in ascending order (w/ all the same elements as the heap)
"""
@spec listify(__MODULE__.t) :: list(integer)
def listify(x), do: listify(x, [])
defp listify(x, y) do
if Berg.zero?(x) do
Enum.reverse(y)
else
listify(trunk(x), [root(x)|y])
end
end
end