Congratulations, you've made it to the end of the course and we've seen so much. Think about where you've come from. We started this course by talking about computational thinking. Computational thinking is this approach to problem solving that is based on concepts from Computer Science, and allows us to create and describe solutions in such a way that they can be carried out by a computer. In the first part of the course, we looked at the four pillars of computational thinking. Decomposition, where we break down a complex problem into smaller parts that are more manageable and easier to understand. Pattern recognition, where we find similarities or patterns between the decomposed problems that can help us solve more complex problems. Data Representation and abstraction, where we determine what characteristics of the problem are important and filter out those that are not, and algorithms, which are a set of finite step-by-step instructions for solving this and similar problems. In the second part of the course, we went into more detail about algorithms. Starting with some common ones like finding the maximum value of the collection or determining whether a collection contains a value. There are various ways of representing or communicating an algorithm. One of the most common is to use a flowchart, as we see here. A flowchart is a graphical representation of the sequence of steps needed to implement the solution. Though we can't use it to tell the computer how to carry out the steps, it helps us organize our thoughts and understand the process visually. There may be many different algorithms for solving the same problem, and one way of comparing algorithms is to consider their complexity. Complexity refers to how many operations need to be performed in the algorithm as a function of the size of the input. As the input size increases, the number of operations increase at different rates for different types of algorithms. So here, we see a graph where on the x-axis, we have the input size as before, and on the y-axis, we have the number of operations, whether it's comparisons or whatever else you're measuring. The simplest algorithms that we saw had linear complexity, which means that the number of operations increase linearly with respect to the size of the input. So, on this graph, that's the red line, linear. Where you can see that it's growing linearly with respect to the size of the input. But we also saw more complex algorithms like those using brute force, in which the number of possible solutions grows incredibly quickly as the input size grows. Which is something more like the blue and the green line shown on this graph. After we explored computational thinking and algorithms, we looked at computer architecture, so that we could understand what the computer is capable of, and then use that understanding to be able to tell the computer how to implement our algorithms. Modern computers are based on what is known as the von Neumann architecture. Conceptual model of a computer developed by the mathematician John von Neumann in the 1940's. Here we see a diagram of the Von Neumann architecture which consists of three main parts. Memory, which is used to store the instructions for our programs and also the data that is used by those programs during their execution. The central processing unit or CPU, which is responsible for carrying out the instructions, and which itself contains two parts, the control unit, which figures out which instruction to run and arithmetic and logic unit or ALU, which contains the hardware for doing that. Last, there's input and output, which allows the computer to interact with the outside world via various devices such as a keyboard or mouse for input, or a monitor or a printer for output. Understanding how the computer organizes data helps us understand the types of things we can do when we write programs. As we saw in the previous part of the course, we can use labels or variables as meaningful names to represent the addresses where data is stored. In the simplest case, a label can refer to a single piece of data like a number or a letter. But we also saw that it is possible to group data in other ways. For instance a list, where we can access individual elements by their index or position as we see on the left or into an object as we see on the right, where we group things together, so that the group as a whole has a name but so do the individual values. When we discussed the role of the CPU, we saw that it ordinarily executes instructions in sequential order. But sometimes, it can execute instructions conditionally or out of order. In some cases, as we see on the left, we can do one instruction under some condition and at different instruction under another, and so on, and others as we see on the right, we may want to loop and continue doing instructions until we need to stop. Last, once we understood the parts of the Von Neumann architecture, how data is organized, and how the CPU can execute different instructions, we started looking at this Python programming language. This examples show some code that determines whether a list of elements is in sorted order, and it shows just about all of the important Python features that we learned. Including variables, lists, if statements, loops, and functions. We've discussed these ideas in the context of some large, real-world applications like Google Earth, Facebook albums, and Amazon catalogs. However, even if you don't see yourself eventually working in the tech industry, the ideas of computational thinking are useful. For example, mulching your garden. Hire a landscaper. Scheduling meetings, planning shopping trips, or making a gourmet meal. You don't have to be a computer scientist to think like one. If you like coding and are interested in knowing more about it, I certainly encourage you to keep learning Python. Because we've really only scratched the surface here and there are plenty of Python libraries for solving all sorts of different problems. From there, you can keep progressing to more advanced languages like Java, which you can use for building apps or JavaScript for web development. If you like coding and math, in particular probability and statistics, and like working with data look into data science where you can learn to extract knowledge from big data sets using tools from AI and machine learning. Problems on big data require computational thinking in a manner similar to those on small data. Finally, if you're interested in pursuing a career in computing, we recommend the University of Pennsylvania's masters of Computer and Information Technology program. The MCIT program is a master's program in computer science for students who don't have prior computer science experience. In earning this degree, you'll go into more depth in the topics we've seen in this course, including data representation, algorithms, computer hardware, and developing high-quality software as part of a team. MCIT can help you launch or advance a career in computing and our graduates have gone on to companies such as Amazon, Microsoft, Facebook, and Google, even though they've had no prior Computer Science Experience. MCIT is available both on campus and online. It's an amazing program and can be a life changing experience. Well, that's the end of the course, we hope you've enjoyed it. Good luck. Goodbye.