// Binary Trees benchmark - recursive data structures
enum Tree {
    Leaf,
    Node(Box<Tree>, Box<Tree>),
}

fn make(depth: i32) -> Tree {
    if depth == 0 {
        Tree::Leaf
    } else {
        Tree::Node(Box::new(make(depth - 1)), Box::new(make(depth - 1)))
    }
}

fn check(tree: &Tree) -> i64 {
    match tree {
        Tree::Leaf => 1,
        Tree::Node(left, right) => 1 + check(left) + check(right),
    }
}

fn main() {
    let min_depth = 4;
    let max_depth = 14;

    // Stretch tree
    let stretch_depth = max_depth + 1;
    let stretch_tree = make(stretch_depth);
    println!("stretch tree check: {}", check(&stretch_tree));

    // Long lived tree
    let long_lived_tree = make(max_depth);

    // Iterate through depths
    let mut depth = min_depth;
    while depth <= max_depth {
        let iterations = 1 << (max_depth - depth + 4);
        let mut sum = 0i64;
        for _ in 0..iterations {
            sum += check(&make(depth));
        }
        println!("{} trees of depth {} check: {}", iterations, depth, sum);
        depth += 2;
    }

    println!("long lived tree check: {}", check(&long_lived_tree));
}
