Introduction To The Theory Of Computation by Michael Sipser