From 30c3926b25788311376cbde7f78b800c7cbb8047 Mon Sep 17 00:00:00 2001 From: Max Bucknell Date: Fri, 14 Mar 2025 15:55:17 -0700 Subject: [PATCH] Add tree creation and mutation functions --- lib/mb_binary_tree.ex | 92 ++++++++++++++++++++++++++++++++++-- test/mb_binary_tree_test.exs | 4 -- 2 files changed, 87 insertions(+), 9 deletions(-) diff --git a/lib/mb_binary_tree.ex b/lib/mb_binary_tree.ex index 53a8dfc..80c93ae 100644 --- a/lib/mb_binary_tree.ex +++ b/lib/mb_binary_tree.ex @@ -3,16 +3,98 @@ defmodule MbBinaryTree do Documentation for `MbBinaryTree`. """ + @type t :: nil | nonempty_maybe_improper_list() + + @spec new(any) :: t @doc """ - Hello world. + Create a new tree with a root node. ## Examples - iex> MbBinaryTree.hello() - :world + iex> MbBinaryTree.new(4) + [4, nil, nil] """ - def hello do - :world + def new(root) do + [root, nil, nil] end + + @spec is_tree?(any) :: boolean + @doc """ + Test whether argument is a valid binary tree. + + ## Examples + + iex> MbBinaryTree.new(19) |> MbBinaryTree.is_tree?() + true + iex> MbBinaryTree.is_tree?([12]) + false + iex> MbBinaryTree.is_tree?(12) + false + iex> MbBinaryTree.is_tree?([12, [4, MbBinaryTree.new(2), MbBinaryTree.new(5)], [26, MbBinaryTree.new(14), [28, MbBinaryTree.new(27), MbBinaryTree.new(30)]]]) + """ + def is_tree?(nil), do: true + def is_tree?([_, nil, nil]), do: true + def is_tree?([_, nil, right]), do: is_tree?(right) + def is_tree?([_, left, nil]), do: is_tree?(left) + def is_tree?([_, left, right]), do: is_tree?(left) && is_tree?(right) + def is_tree?(_), do: false + + @spec left(t) :: t + @doc """ + Get the left child of a tree. + + ## Examples + + iex> MbBinaryTree.left([1, MbBinaryTree.new(2), MbBinaryTree.new(3)]) + [2, nil, nil] + iex> MbBinaryTree.new(12) |> MbBinaryTree.left() + nil + iex> MbBinaryTree.left([12, [4, MbBinaryTree.new(2), MbBinaryTree.new(5)], [26, MbBinaryTree.new(14), [28, MbBinaryTree.new(27), MbBinaryTree.new(30)]]]) + [4, [2, nil, nil], [5, nil, nil]] + """ + def left([_, left | _]), do: left + def left(_), do: nil + + @spec right(t) :: t + @doc """ + Get the right child of a tree. + + ## Examples + + iex> MbBinaryTree.right([1, MbBinaryTree.new(2), MbBinaryTree.new(3)]) + [3, nil, nil] + iex> MbBinaryTree.new(12) |> MbBinaryTree.right() + nil + iex> MbBinaryTree.right([12, [4, MbBinaryTree.new(2), MbBinaryTree.new(5)], [26, MbBinaryTree.new(14), [28, MbBinaryTree.new(27), MbBinaryTree.new(30)]]]) + [26, [14, nil, nil], [28, [27, nil, nil], [30, nil, nil]]] + """ + def right([_, _, right]), do: right + def right(_), do: nil + + @spec update_left(t, t) :: t + @doc """ + Update the left child of a tree. + + ## Examples + + iex> MbBinaryTree.update_left([1, MbBinaryTree.new(2), MbBinaryTree.new(3)], MbBinaryTree.new(4)) + [1, [4, nil, nil], [3, nil, nil]] + iex> MbBinaryTree.new(12) |> MbBinaryTree.update_left(MbBinaryTree.new(4)) + [12, [4, nil, nil], nil] + """ + def update_left([node, _left, right], new_left), do: [node, new_left, right] + + @spec update_right(t, t) :: t + @doc """ + Update the right child of a tree. + + ## Examples + + iex> MbBinaryTree.update_right([1, MbBinaryTree.new(2), MbBinaryTree.new(3)], MbBinaryTree.new(4)) + [1, [2, nil, nil], [4, nil, nil]] + iex> MbBinaryTree.new(12) |> MbBinaryTree.update_right(MbBinaryTree.new(4)) + [12, nil, [4, nil, nil]] + """ + def update_right([node, left, _right], new_right), do: [node, left, new_right] end diff --git a/test/mb_binary_tree_test.exs b/test/mb_binary_tree_test.exs index 9a1b690..9a27e0f 100644 --- a/test/mb_binary_tree_test.exs +++ b/test/mb_binary_tree_test.exs @@ -1,8 +1,4 @@ defmodule MbBinaryTreeTest do use ExUnit.Case doctest MbBinaryTree - - test "greets the world" do - assert MbBinaryTree.hello() == :world - end end