Created
April 12, 2021 15:26
-
-
Save aschiavon91/5c33db2e2d35e310e0aaebe5c4f66513 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule Zipper do | |
| defstruct node: nil, focus: [] | |
| @type t :: %__MODULE__{node: BinTree.t(), focus: list({:left | :right, BinTree.t()})} | |
| @doc """ | |
| Get a zipper focused on the root node. | |
| """ | |
| @spec from_tree(BinTree.t()) :: Zipper.t() | |
| def from_tree(bin_tree), do: %__MODULE__{node: bin_tree} | |
| @doc """ | |
| Get the complete tree from a zipper. | |
| """ | |
| @spec to_tree(Zipper.t()) :: BinTree.t() | |
| def to_tree(%__MODULE__{node: node, focus: []}), do: node | |
| def to_tree(%__MODULE__{} = zipper), do: zipper |> up() |> to_tree() | |
| @doc """ | |
| Get the value of the focus node. | |
| """ | |
| @spec value(Zipper.t()) :: any | |
| def value(%__MODULE__{node: %BinTree{value: value}}), do: value | |
| @doc """ | |
| Get the left child of the focus node, if any. | |
| """ | |
| @spec left(Zipper.t()) :: Zipper.t() | nil | |
| def left(%__MODULE__{node: %BinTree{left: nil}}), do: nil | |
| def left(%__MODULE__{node: %BinTree{left: left} = node, focus: focus}), | |
| do: %__MODULE__{node: left, focus: [{:left, node} | focus]} | |
| @doc """ | |
| Get the right child of the focus node, if any. | |
| """ | |
| @spec right(Zipper.t()) :: Zipper.t() | nil | |
| def right(%__MODULE__{node: %BinTree{right: nil}}), do: nil | |
| def right(%__MODULE__{node: %BinTree{right: right} = node, focus: focus}), | |
| do: %__MODULE__{node: right, focus: [{:right, node} | focus]} | |
| @doc """ | |
| Get the parent of the focus node, if any. | |
| """ | |
| @spec up(Zipper.t()) :: Zipper.t() | nil | |
| def up(%__MODULE__{focus: []}), do: nil | |
| def up(%__MODULE__{focus: [{branch, parent} | focus], node: node}), | |
| do: %__MODULE__{node: Map.put(parent, branch, node), focus: focus} | |
| @doc """ | |
| Set the value of the focus node. | |
| """ | |
| @spec set_value(Zipper.t(), any) :: Zipper.t() | |
| def set_value(%__MODULE__{node: node} = zipper, value), | |
| do: %__MODULE__{zipper | node: %BinTree{node | value: value}} | |
| @doc """ | |
| Replace the left child tree of the focus node. | |
| """ | |
| @spec set_left(Zipper.t(), BinTree.t() | nil) :: Zipper.t() | |
| def set_left(%__MODULE__{node: node} = zipper, left), | |
| do: %__MODULE__{zipper | node: %BinTree{node | left: left}} | |
| @doc """ | |
| Replace the right child tree of the focus node. | |
| """ | |
| @spec set_right(Zipper.t(), BinTree.t() | nil) :: Zipper.t() | |
| def set_right(%__MODULE__{node: node} = zipper, right), | |
| do: %__MODULE__{zipper | node: %BinTree{node | right: right}} | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment