# The Tree class was interesting, but it did not allow you to
# specify a new tree with a clean user interface. Let the initailizer
# accept a nested structure with hashes and arrays. You should be
# able to specific a tree like this: .....


# The Tree Class

class Tree

	attr_accessor :childNodes;
	attr_accessor :name;


	# I return an initialized Tree instance.

	def initialize( treeData )

		# Initialize the node variables. By default, we are going
		# to treat this node as the root node (unless the incoming
		# tree data only has one top-level key, in which case that
		# will be the root node).

		@name = "root";
		@childNodes = [];

		# Check to see how many top-level keys the tree data has.
		# If it only has one, we can use it to define this tree
		# node; if it has more than one, will have to treat it as
		# the child data of a the "root" node.

		if (treeData.size() == 1)

			# We only have one top-level key. We can use that to
			# define this tree node.

			@name = treeData.keys()[ 0 ];

			# Convert the sub-level tree data into the chile nodes
			# of this tree node.

			treeData[ @name ].each{ |key, value|

				@childNodes.push(
					Tree.new( { key => value } )
				);

			};

		else

			# We have more than one top-level key. We need to
			# create a root node to house multiple nodes.

			treeData.each{ |key, value|

				@childNodes.push(
					Tree.new( { key => value } )
				);

			};

		end

	end


	# I visit all decendant nodes in a depth-first traversal.

	def visitAll( &block )

		# Visit this node.

		visit( &block );

		# Visit all of this node's children.

		childNodes.each{ |c|

			c.visitAll( &block );

		}

	end


	# I visit just this node.

	def visit( &block )

		block.call( self );

	end

end



# ------------------------------------------------------------ #
# ------------------------------------------------------------ #
# ------------------------------------------------------------ #
# ------------------------------------------------------------ #


# Create our new Tree.

tree = Tree.new(
	{
		"grandpa" => {
			"dad" => {
				"child1" => {},
				"child2" => {}
			},
			"uncle" => {
				"child3" => {},
				"child4" => {}
			}
		}
	}
);


# Visit all nodes in the tree, starting with the root.

tree.visitAll{ |node|

	puts( "Visiting #{node.name}" );

};