Skip to content

Instantly share code, notes, and snippets.

@gvaughn
Created September 27, 2016 14:25
Show Gist options
  • Save gvaughn/0d2c44740f89cb0de192bda76ab21452 to your computer and use it in GitHub Desktop.
Save gvaughn/0d2c44740f89cb0de192bda76ab21452 to your computer and use it in GitHub Desktop.
homework assignment to implement a stack and evaluate a postfix expression
defmodule Stack do
@moduledoc """
Implement a stack using a linked list to back it. The stack should support
peek, push, pop, count
do it in whatever language you want
"""
defstruct llist: []
def peek(%Stack{llist: [head | _]}), do: head
def peek(%Stack{}), do: nil
def push(%Stack{llist: list}, new_item) do
%Stack{llist: [new_item | list]}
end
def push(initial_item), do: %Stack{llist: [initial_item]}
def pop(%Stack{llist: [head | tail]}) do
{head, %Stack{llist: tail}}
end
def pop(%Stack{} = stack), do: {nil, stack}
def count(%Stack{llist: list}) do
Enum.reduce(list, 0, fn(_e, sum) -> sum + 1 end)
end
def is_empty?(%Stack{llist: []}), do: true
def is_empty?(%Stack{}), do: false
def eval(str) do
String.split(str) |> Enum.reduce(%Stack{}, &eval/2) |> peek
end
defp eval("+", stack), do: operate(&Kernel.+/2, stack)
defp eval("x", stack), do: operate(&Kernel.*/2, stack)
defp eval("%", stack), do: operate(&Kernel.rem/2, stack)
defp eval(token, stack), do: push(stack, String.to_integer(token))
defp operate(f, stack) do
{a, stack} = pop(stack)
{b, stack} = pop(stack)
push(stack, f.(b,a))
end
end
ExUnit.start
defmodule StackTest do
use ExUnit.Case
import Stack
setup do: {:ok, stack: push("hello") |> push("world")}
test "push and pop", %{stack: stack} do
assert {"world", stack} = pop(stack)
assert {"hello", stack} = pop(stack)
assert {nil , _stack} = pop(stack)
end
test "peek", %{stack: stack} do
assert "world" = peek(stack)
assert "world" = peek(stack)
end
test "count", %{stack: stack} do
assert 2 = count(stack)
end
test "is_empty?", %{stack: stack} do
assert false == is_empty?(stack)
assert true == is_empty?(%Stack{})
end
test "eval" do
"500 122 29 + 14 x + 30 %" |> eval |> IO.puts
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment