At its core, Computer Science is the study of algorithmic problem solving. Although it is necessary to teach programming, data structures, computer organization, etc., students should ultimately learn to use these things to solve problems, understand what is good and bad about their solutions, and share their solutions with others. This paper describes a course that focuses on the four steps of the problem solving process: algorithmic thinking, implementation, analysis, and communication. This course, based on Knuth's popular seminar at Stanford, has been extremely successful at the authors' three institutions. In addition to discussing the course's objectives and methodology, we present sample problems, summarize the outcomes and feedback from students, and give advice to other educators looking to create a similar course.