-
Notifications
You must be signed in to change notification settings - Fork 5
/
stack.ex
92 lines (66 loc) · 1.97 KB
/
stack.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
defmodule ExAlgo.Stack do
@moduledoc """
A basic Stack implementation
"""
@doc """
The Stack struct.
"""
defstruct container: []
@type value_type :: any()
@type t :: %__MODULE__{container: [value_type()]}
@doc """
Create a new empty stack
## Example
iex> alias ExAlgo.Stack
iex> Stack.new()
%Stack{container: []}
"""
@spec new() :: t()
def new, do: %__MODULE__{}
@doc """
Create a new stack from an enumerable. Note that the stack container has the order inversed as each element of the
iterable is pushed into the stack, thereby putting the last element on top.
## Example
iex> Stack.from(1..3)
%Stack{container: [3, 2, 1]}
"""
@spec from([value_type()]) :: t()
def from(enumerable), do: enumerable |> Enum.into(%__MODULE__{})
@doc """
Puts an element on top of stack.
## Example:
iex> %Stack{} |> Stack.push(10) |> Stack.push(20)
%Stack{container: [20, 10]}
"""
@spec push(t(), value_type()) :: t()
def push(%__MODULE__{container: container}, item) do
%__MODULE__{container: [item | container]}
end
@doc """
Extract an element from top of stack.
## Example:
iex> stack = %Stack{} |> Stack.push(10) |> Stack.push(20)
iex> {20, %Stack{container: [10]}} = stack |> Stack.pop()
iex> {:error, :underflow} = %Stack{} |> Stack.pop()
"""
@spec pop(t()) :: {value_type(), t()} | {:error, :underflow}
def pop(%__MODULE__{container: []}) do
{:error, :underflow}
end
def pop(%__MODULE__{container: [top | rest]}) do
{top, %__MODULE__{container: rest}}
end
@doc """
Extract an element from top of stack.
## Example:
iex> stack = %Stack{} |> Stack.push(10) |> Stack.push(20)
iex> 20 = stack |> Stack.peek()
iex> %Stack{} |> Stack.peek()
{:error, :underflow}
"""
@spec peek(t()) :: value_type() | {:error, :underflow}
def peek(%__MODULE__{container: []}) do
{:error, :underflow}
end
def peek(%__MODULE__{container: [top | _]}), do: top
end