rose_tree v0.2.0 RoseTree

A rose tree is an n-ary tree in which each node has zero or more children, all of which are themselves rose trees.

Trees are unbalanced and children unordered.

Link to this section Summary

Functions

Add a new child to a tree

Retrieve a list of the values of a node’s immediate children

Fetch a node’s value by traversing a path of indicies through nodes and their children

Convert a map into a rose tree

Determines whether a node is a child of a tree

Map a function over a tree, preserving the tree’s structure (compare with Enum.map for rose trees, which maps over a list of node values)

Merge two nodes that have the same value

Create a new, empty rose tree

Initialize a new rose tree with a node value and empty children

Initialize a new rose tree with a node value and children

List all of the possible paths through a tree

Remove the first child from the children of a node

Remove the child at a given index from the children of a node

Extract the node values of a rose tree into a list

Replace the children of a node that matches a given value

Replace the value of every node that matches a given value

Link to this section Types

Link to this type t()
t() :: %RoseTree{children: [%RoseTree{children: term, node: term}], node: any}

Link to this section Functions

Link to this function add_child(tree, child)

Add a new child to a tree.

If the tree already has children, the new child is added to the front.

If the value of the new child’s node is already present in the tree’s children, then the new child’s children are merged with the existing child’s children.

Examples

iex> hello = RoseTree.new(:hello)
...> world = RoseTree.new(:world)
...> RoseTree.add_child(hello, world)
%RoseTree{node: :hello, children: [
  %RoseTree{node: :world, children: []}
]}

iex> hello = RoseTree.new(:hello)
...> world_wide = RoseTree.new(:world, :wide)
...> world_champ = RoseTree.new(:world, :champ)
...> dave = RoseTree.new(:dave)
...> hello
...> |> RoseTree.add_child(world_wide)
...> |> RoseTree.add_child(world_champ)
...> |> RoseTree.add_child(dave)
%RoseTree{children: [
  %RoseTree{children: [], node: :dave},
  %RoseTree{children: [
    %RoseTree{node: :wide, children: []},
    %RoseTree{node: :champ, children: []}],
    node: :world}],
  node: :hello}
Link to this function child_values(rose_tree)
child_values(RoseTree.t) :: [any]

Retrieve a list of the values of a node’s immediate children.

Examples

iex> c = RoseTree.new(:c, [:d, :z])
...> tree = RoseTree.new(:a, [:b, c])
...> RoseTree.child_values(tree)
[:b, :c]

iex> tree = RoseTree.new(:hello)
...> RoseTree.child_values(tree)
[]
Link to this function elem_at(tree, index_path)
elem_at(RoseTree.t, [integer]) :: {:ok, any} | {:error, tuple}

Fetch a node’s value by traversing a path of indicies through nodes and their children.

Examples

iex> tree = RoseTree.new(:a, [:b, RoseTree.new(:c, [:d, :z])])
...> RoseTree.elem_at(tree, [])
{:ok, :a}
...> RoseTree.elem_at(tree, [1, 0])
{:ok, :d}
...> RoseTree.elem_at(tree, [1, 2])
{:error, {:rose_tree, :bad_path}}
Link to this function from_map(map)
from_map(map) :: {:error, tuple} | {:ok, RoseTree.t}

Convert a map into a rose tree.

Examples

iex> RoseTree.from_map(%{a: [:b]})
{:ok, %RoseTree{node: :a, children: [%RoseTree{node: :b, children: []}]}}

iex> RoseTree.from_map(%{a: %{b: [:c]}})
{:ok, %RoseTree{node: :a, children: [
  %RoseTree{node: :b, children: [
    %RoseTree{node: :c, children: []}
  ]}
]}}
Link to this function is_child?(rose_tree1, rose_tree2)
is_child?(RoseTree.t, RoseTree.t) :: boolean

Determines whether a node is a child of a tree.

The determination is based on whether the value of the node of the potential child matches a node value in the tree of interest.

Examples

iex> b = RoseTree.new(:b)
...> c = RoseTree.new(:c, [:d, :z])
...> tree = RoseTree.new(:a, [b, c])
...> RoseTree.is_child?(tree, b)
true
...> x = RoseTree.new(:x)
...> RoseTree.is_child?(tree, x)
false
Link to this function map(rose_tree, func)
map(RoseTree.t, (any -> any)) :: RoseTree.t

Map a function over a tree, preserving the tree’s structure (compare with Enum.map for rose trees, which maps over a list of node values).

Examples

iex> RoseTree.new(0, [1, RoseTree.new(10, [11, 12])])
...> |> RoseTree.map(fn (value) -> value * value end)
%RoseTree{node: 0, children: [
  %RoseTree{node: 1, children: []},
  %RoseTree{node: 100, children: [
    %RoseTree{node: 121, children: []},
    %RoseTree{node: 144, children: []}
  ]}
]}
Link to this function merge_nodes(tree_a, tree_b)
merge_nodes(RoseTree.t, RoseTree.t) :: RoseTree.t

Merge two nodes that have the same value.

If the sets of children in the two nodes do not share any members, the children of tree_a are prepended to tree_b’s children.

If there are children with the same node value present in both trees, the children are themselves merged with the child in tree_a’s children (updated with the merge of the children of tree_b’s child) that matched prepended to the unique children from tree_b.

Examples

iex> world_wide = RoseTree.new(:world, :wide)
...> world_champ = RoseTree.new(:world, :champ)
...> RoseTree.merge_nodes(world_champ, world_wide)
%RoseTree{
  children: [
    %RoseTree{children: [], node: :champ},
    %RoseTree{children: [], node: :wide}
  ], node: :world
}

Create a new, empty rose tree.

Example

iex> RoseTree.new()
%RoseTree{node: :empty, children: []}
Link to this function new(value)
new(any) :: RoseTree.t

Initialize a new rose tree with a node value and empty children.

Examples

iex> RoseTree.new(:a)
%RoseTree{node: :a, children: []}
Link to this function new(value, children)
new(any, any) :: RoseTree.t

Initialize a new rose tree with a node value and children.

Examples

iex> b = RoseTree.new(:b)
...> RoseTree.new(:a, [b, :c])
%RoseTree{node: :a, children: [
  %RoseTree{node: :b, children: []},
  %RoseTree{node: :c, children: []}
]}
Link to this function paths(tree)
paths(RoseTree.t) :: [any]

List all of the possible paths through a tree.

Examples

iex> RoseTree.new(:a, [:b, RoseTree.new(:c, [:d, :z])])
...> |> RoseTree.paths()
[[:a, :b], [[:a, :c, :d], [:a, :c, :z]]]
Link to this function pop_child(tree)
pop_child(RoseTree.t) ::
  {RoseTree.t, RoseTree.t} |
  {nil, RoseTree.t}

Remove the first child from the children of a node.

Returns a tuple containing the child that was removed and the modified tree.

Examples

iex> RoseTree.new(:a, [:b, RoseTree.new(:c, [:d, :z])])
...> |> RoseTree.pop_child()
{%RoseTree{node: :b, children: []}, %RoseTree{
  node: :a, children: [
    %RoseTree{node: :c, children: [
      %RoseTree{node: :d, children: []},
      %RoseTree{node: :z, children: []}
    ]}
  ]
}}

iex> RoseTree.new(:hello)
...> |> RoseTree.pop_child()
{nil, %RoseTree{node: :hello, children: []}}
Link to this function pop_child_at(tree, idx)
pop_child_at(RoseTree.t, integer) ::
  {RoseTree.t, RoseTree.t} |
  {nil, RoseTree.t}

Remove the child at a given index from the children of a node.

Returns a tuple containing the child that was removed and the modified tree.

Examples

iex> RoseTree.new(:a, [:b, RoseTree.new(:c, [:d, :z])])
...> |> RoseTree.pop_child_at(1)
{%RoseTree{node: :c, children: [
  %RoseTree{node: :d, children: []},
  %RoseTree{node: :z, children: []}
]}, %RoseTree{node: :a, children: [
  %RoseTree{node: :b, children: []}
  ]}
}
Link to this function to_list(tree)
to_list(RoseTree.t) :: [any]

Extract the node values of a rose tree into a list.

Examples

iex> RoseTree.new(:a, [:b, RoseTree.new(:c, [:d, :z])])
...> |> RoseTree.to_list()
[:a, :b, :c, :d, :z]
Link to this function update_children(tree, value, new_children)
update_children(RoseTree.t, any, any) :: RoseTree.t

Replace the children of a node that matches a given value.

Note: this will update the value of every match. If there are multiple nodes throughout the tree that match, they will all be updated.

Examples

iex> RoseTree.new(:a, [:b])
...> |> RoseTree.update_children(:a, [RoseTree.new(:c)])
%RoseTree{node: :a, children: [%RoseTree{node: :c, children: []}]}
Link to this function update_node(tree, value, new_value)
update_node(RoseTree.t, any, any) :: RoseTree.t

Replace the value of every node that matches a given value.

Note: this will update the value of every match. If there are multiple nodes throughout the tree that match, they will all be updated.

Examples

iex> RoseTree.new(:a, [:b])
...> |> RoseTree.update_node(:a, :hello)
%RoseTree{node: :hello, children: [%RoseTree{node: :b, children: []}]}