This is a book about computation, something which is ubiquitous in the modern world. More precisely, it examines computability theory and computational complexity theory. Computability theory is the part of mathematics and computer science which seeks to clarify what we mean by computation or algorithm. When is there a computational solution possible to some question? How can we show that none is possible? How computationally hard is the question we are concerned with? Arguably, this area lead to the development of digital computers. (Computational) complexity theory is an intellectual heir of computability theory. Complexity theory is concerned with understanding what resources are needed for computation, where typically we would measure the resources in terms of time and space. Can we perform some task in a feasible number of steps? Can we perform some algorithm with only a limited memory? Does randomness help? Are there standard approaches to overcoming computational difficulty?