Combinatorial algorithms: Theory and practice