Elements of the Theory of Computation