#include #include #include // Option template struct Option { bool tag; T value; static Option some(T value) { return Option { .tag = true, .value = value, }; } static Option none() { return Option { .tag = false, }; } }; template T option_unwrap(Option self) { assert(self.tag); return self.value; } // Box template struct Box { T *value; }; template Box box_new(T value) { return Box { .value = new T(value), }; } template void box_drop(Box self) { delete self.value; } template struct Display { void (*fmt)(const Self *self, std::string *f); }; // iterate on previous program namespace iota { // SimpleIterator template struct Peekable; template Peekable peekable_default(Self self); template struct SimpleIterator { Option (*next)(Self *self); Peekable (*peekable)(Self self) = peekable_default; }; // Peekable template struct Peekable { T iter; Option peeked; static SimpleIterator, I> simple_iterator_impl; }; template Peekable peekable_default(Self self) { return Peekable { .iter = self, .peeked = Option::none(), }; } template Option peekable_peek(Peekable *self) { if (!self->peeked.tag) { self->peeked = T::simple_iterator_impl.next(&self->iter); } return self->peeked; } template Option peekable_next(Peekable *self) { if (self->peeked.tag) { const auto tmp = self->peeked; self->peeked = Option::none(); return tmp; } else return T::simple_iterator_impl.next(&self->iter); } template SimpleIterator, I> Peekable::simple_iterator_impl = { .next = peekable_next, }; // Iota struct Iota { size_t field0; static SimpleIterator simple_iterator_impl; }; Iota iota_new() { return Iota { .field0 = 0, }; } Option iota_next(Iota *self) { const auto prev = self->field0; self->field0 = prev + 1; return Option::some(prev); } SimpleIterator Iota::simple_iterator_impl = { .next = iota_next, }; } namespace peano { struct Nat; Nat nat_add(Nat self, Nat rhs); /// Peano Natural Number struct Nat { enum { Zero, Succ, } tag; Box field0; static Nat zero() { return Nat { .tag = Zero, }; } static Nat succ(Box field0) { return Nat { .tag = Succ, .field0 = field0, }; } Nat operator+(Nat rhs) { return nat_add(*this, rhs); } }; Nat nat_one() { return Nat::succ(box_new(Nat::zero())); } void nat_drop(Nat self) { if (self.tag == Nat::Succ) { nat_drop(*self.field0.value); box_drop(self.field0); } } Nat nat_add(Nat self, Nat rhs) { if (self.tag == Nat::Zero) { nat_drop(self); return rhs; } else { return Nat::succ(box_new(nat_add(*self.field0.value, rhs))); } } size_t from_nat(Nat value) { if (value.tag == Nat::Zero) { return 0; } else { return from_nat(*value.field0.value) + 1; } } Nat into_nat(size_t value) { if (value == 0) { return Nat::zero(); } else { return Nat::succ(box_new(into_nat(value - 1))); } } } namespace bin_tree { template struct Node; template void node_drop(Node self); /// Self-Balancing Binary Tree with 0, 1 or 2 children per nodes template struct BinTree { enum { Leaf, Left, LeftRight, } tag; Box> left; Box> right; static BinTree leaf() { return BinTree { .tag = Leaf, }; } static BinTree left_(Box> left) { return BinTree { .tag = Left, .left = left, }; } static BinTree left_right(Box> left, Box> right) { return BinTree { .tag = LeftRight, .left = left, .right = right, }; } }; template void bin_tree_drop(BinTree self) { if (self.tag != BinTree::Leaf) { node_drop(*self.left.value); box_drop(self.left); } if (self.tag == BinTree::LeftRight) { node_drop(*self.right.value); box_drop(self.right); } } template struct Node { D data; BinTree shape; static Display> display_impl; }; template void node_fmt(const Node *self, std::string *f) { *f += std::to_string(self->data); *f += ":"; if (self->shape.tag == BinTree::Leaf) *f += "()"; else if (self->shape.tag == BinTree::Left) { *f += "( "; node_fmt(self->shape.left.value, f); *f += " )"; } else if (self->shape.tag == BinTree::LeftRight) { *f += "( "; node_fmt(self->shape.left.value, f); *f += ", "; node_fmt(self->shape.right.value, f); *f += " )"; } } template Display> Node::display_impl = { .fmt = node_fmt, }; template Node node_root(D data) { return Node { .data = data, .shape = BinTree::leaf(), }; } template void node_drop(Node self) { bin_tree_drop(self.shape); } template N node_weight(const Node *self) { using namespace peano; auto subtree = Nat::zero(); if (self->shape.tag != BinTree::Leaf) subtree = into_nat(node_weight(self->shape.left.value)); if (self->shape.tag == BinTree::LeftRight) subtree = subtree + into_nat(node_weight(self->shape.right.value)); const auto nat = /*this node*/nat_one() + subtree; return from_nat(nat); } template Node node_add(Node self, Node rhs) { const auto data = self.data; const auto shape = self.shape; BinTree new_shape; if (shape.tag == BinTree::Leaf) new_shape = BinTree::left_(box_new(rhs)); else if (shape.tag == BinTree::Left) { new_shape = BinTree::left_right(shape.left, box_new(rhs)); } else if (shape.tag == BinTree::LeftRight && node_weight(shape.left.value) < node_weight(shape.right.value)) { new_shape = BinTree::left_right(box_new(node_add(*shape.left.value, rhs)), shape.right); } else if (shape.tag == BinTree::LeftRight) { new_shape = BinTree::left_right(shape.left, box_new(node_add(*shape.right.value, rhs))); } return Node { .data = data, .shape = new_shape, }; } } #include int main() { { auto iota = iota::iota_new(); assert(option_unwrap(iota::iota_next(&iota)) == 0); assert(option_unwrap(iota::iota_next(&iota)) == 1); assert(option_unwrap(iota::iota_next(&iota)) == 2); assert(option_unwrap(iota::iota_next(&iota)) == 3); auto peekable_iota = iota::Iota::simple_iterator_impl.peekable(iota); assert(option_unwrap(iota::peekable_peek(&peekable_iota)) == 4); assert(option_unwrap(iota::peekable_peek(&peekable_iota)) == 4); assert(option_unwrap(iota::peekable_peek(&peekable_iota)) == 4); assert(option_unwrap(iota::peekable_next(&peekable_iota)) == 4); assert(option_unwrap(iota::peekable_next(&peekable_iota)) == 5); assert(option_unwrap(iota::peekable_next(&peekable_iota)) == 6); } auto iota = iota::iota_new(); auto b = bin_tree::node_root(option_unwrap(iota::iota_next(&iota))); for (size_t i = 0; i < 100; i++) { const auto new_ = bin_tree::node_root(option_unwrap(iota::iota_next(&iota))); b = bin_tree::node_add(b, new_); } std::string f; bin_tree::Node::display_impl.fmt(&b, &f); // std::cout << f; assert(f == "0:( 1:( 4:( 10:( 22:( 46:( 94:() ), 62:( 78:() ) ), 30:( 38:( 86:() ), 54:( 70:() ) ) ), 14:( 18:( 42:( 90:() ), 58:( 74:() ) ), 26:( 34:( 82:() ), 50:( 66:(), 98:() ) ) ) ), 6:( 8:( 20:( 44:( 92:() ), 60:( 76:() ) ), 28:( 36:( 84:() ), 52:( 68:(), 100:() ) ) ), 12:( 16:( 40:( 88:() ), 56:( 72:() ) ), 24:( 32:( 80:() ), 48:( 64:(), 96:() ) ) ) ) ), 2:( 3:( 9:( 21:( 45:( 93:() ), 61:( 77:() ) ), 29:( 37:( 85:() ), 53:( 69:() ) ) ), 13:( 17:( 41:( 89:() ), 57:( 73:() ) ), 25:( 33:( 81:() ), 49:( 65:(), 97:() ) ) ) ), 5:( 7:( 19:( 43:( 91:() ), 59:( 75:() ) ), 27:( 35:( 83:() ), 51:( 67:(), 99:() ) ) ), 11:( 15:( 39:( 87:() ), 55:( 71:() ) ), 23:( 31:( 79:() ), 47:( 63:(), 95:() ) ) ) ) ) )"); bin_tree::node_drop(b); return 0; }