035 — Layout a Binary Tree
Tutorial Video
Text description (accessibility)
This video demonstrates the "035 — Layout a Binary Tree" functional Rust example. Difficulty level: Intermediate. Key concepts covered: Functional Programming. Assigning (x, y) coordinates to tree nodes for visualization (OCaml 99 Problems #35) is a tree layout algorithm. Key difference from OCaml: 1. **Mutable state**: Both languages use mutable state for the inorder counter. Rust uses `&mut usize`, OCaml uses `ref int`. Both are equivalent; OCaml's `ref` is more explicit as a mutable cell.
Tutorial
The Problem
Assigning (x, y) coordinates to tree nodes for visualization (OCaml 99 Problems #35) is a tree layout algorithm. The simplest rule: y = depth (root at 1), x = position in inorder traversal (leftmost node at x=1, rightmost at x=n). This produces a planar embedding where no two nodes overlap and no edge crossings occur.
Tree layout algorithms are used in compiler visualization (AST display), file system browsers, organization charts, and graph drawing tools. The Reingold-Tilford algorithm (used in most modern tree visualizers) extends this idea with contour-based subtree fitting to minimize width.
🎯 Learning Outcomes
Tree<(T, (usize, usize))> that annotates each node with coordinates&mut usize counter through recursive calls to assign sequential in-order x-coordinatesCode Example
#![allow(clippy::all)]
// Placeholder — pending conversionKey Differences
&mut usize, OCaml uses ref int. Both are equivalent; OCaml's ref is more explicit as a mutable cell.Tree<(T, (usize, usize))> adds coordinate information to each node. OCaml's 'a tree becomes ('a * (int * int)) tree — the same pattern.(x, y) coordinates to each node. x is the in-order position (1-based, left-to-right), y is the depth (1-based, top-to-bottom). The result is a Tree<(T, usize, usize)> where each node carries its coordinates.&mut usize — mutable reference passed through recursive calls. OCaml's functional version threads the counter as an additional return value.&mut usize — both achieve the same shared mutable counter, expressed differently.OCaml Approach
OCaml's version uses a mutable reference: let layout_aux tree = let x = ref 0 in let rec lay depth = function | Leaf -> Leaf | Node (v, l, r) -> let left = lay (depth + 1) l in incr x; let pos = (!x, depth) in let right = lay (depth + 1) r in Node ((v, pos), left, right) in lay 1 tree. The x reference is incremented in inorder (left → self → right).
Full Source
#![allow(clippy::all)]
// Placeholder — pending conversionDeep Comparison
OCaml vs Rust: Layout Binary Tree
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
to_svg(tree: &Tree<(char, (usize, usize))>) -> String that produces an SVG string with circles for nodes and lines for edges.(x, y) positions and edges are drawn with - and | characters.