Being able to think is one of the hallmarks of being a human being - especially meta thinking which involves thinking about your own thoughts. We often overlook the complexity of thinking because it comes so naturally to us. It seems so easy because we do it everyday with little to no thought about how the process works. It only becomes apparent that it is complex when something or someone interrupts our thought process e.g. try explaining a specific idea you have to someone in one or two sentences; or try follow a lecture in a topic you don't know anything about. These tasks become difficult because in our daily life we strip away what we can safely assume to make communication easier and more effective. This stripping away of "unnecessary" information becomes a problem when we need it. This is most prominent when working with computer programming because a computer cannot assume any information, so you have to provide commands without exception. This means that you have to adjust your thinking slightly to work through problems in the same way a computer program would. This isn't as daunting as it sounds because it is quite straightforward and it can also help with the way in which you solve problems outside of programming too.
The main purpose of computational thinking is to identify problems and solve them. This seems simple, but problems themselves can be quite complex and made up of different parts, each of which forms its own separate problem. The complex nature of problems can make them seem to be overwhelming, but when you follow a few simple steps, you are able to break them down into manageable pieces. This is very effective because not only does it work for computational problems, but it also works for most problems you will face in life. There are four key steps in this process: 1) decomposition, 2) pattern recognition, 3) abstraction and 4) algorithmic thinking. Using these four components, you will be able to successfully solve problems by "dividing and conquering" them. There are also some additional factors that need to be considered that are not directly related to the core way of solving the problem - constraints. There could be several constraints that you are facing which were unforeseeable, imposed upon your project or factors that weren't considered when starting. In this course, you will learn to use these four components as well as how to deal with constraints and what you can do to mitigate the effects of them.
Another point that is important to understand involves the following three words: what, why and how. It is always important to understand what you are doing because if you don't understand that then you cannot reorientate yourself when you face problems in your project. In the same way, you need to understand why you are doing something. Keeping a goal in mind when you break down a problem into smaller pieces will keep you focused on the big picture even when you are working on the smaller issues. This is vital for lose losing sight of what your final goal is. Lastly, having a clear understanding of how you are going to do something will put an element of realism to a project and reveal any potential unrealistic expectations right in the beginning. These are three important components to keep in mind when you are working on any step of the computational thinking process. They are supplementary because even though they help keep you on track, you still need the plan and the action to achieve the goal.
This course will teach you how to effectively use these concepts to become a self-sufficient learner and problem-solver. Not only in the computational world, but also in the real world where you are faced with problems that are much less logical and solutions that are suboptimal at best. The principles behind both real world and computational problems are essentially the same, so these lessons are applicable in most - if not all - domains of study and life. The main point you need to keep in mind is that the purpose of the exercises isn't necessarily to achieve that specific goal, but it's rather to go through the process so that you learn the formula to achieve any goal.
In simple terms, decomposition is the process of breaking down a large problem into smaller problems. There are a few reasons why this is helpful in the bigger picture. It gives you insight into the practicalities associated with solving the problem. You can view the smaller tasks with more understanding of what needs to be done because the goal is clearer. This can help you develop actionable steps and get started on solving them. Image for a moment you moved to a new house and there is nothing in it yet, but you want to make a cup of coffee after a day of moving. This seems like a simple enough problem to solve - except that it isn't. You are actually dealing with a complex problem because it's made up of several problems disguised as one, so the problem actually seems to be impossible. You cannot make coffee because you don't have any of the ingredients in your house. So there are two main tasks to solve: buy ingredients and make the coffee.
There two tasks can be further broken down into even simpler tasks. When you buy ingredients, you need to do three things: 1) make of list of ingredients you need, 2) decide where you are going to buy them, and 3) decide how you are going to get there.
This can further be divided into separate tasks for each item that you need to buy. You will need milk, water, coffee powder, a kettle, a spoon and a mug.
You can buy all of those items at the supermarket, so you decide to go there.
The fastest why to the supermarket is by bus, so you decide to take the bus. You also need to make the same trip home after you are done at the supermarket.
When you have broken the problem down into smaller tasks, you can look for patterns. The first step (the list of ingredients) is made up of several smaller steps even though it looks like one step. The full step would actually be as follows:
- Take the bus to the supermarket
- Purchase the milk
- Take the bus back home
- Repeat the process for all the items
This isn't an efficient way of doing this, so we can look for patterns in the tasks. The glaringly obvious pattern is that if we buy all the items at the supermarket then we only have to make one trip to the supermarket and one trip back home. This is process of pattern recognition is very useful in using previous knowledge to apply to new problems. For example, perhaps you are going to a new supermarket because your regular supermarket is closed for the day. You don't need to go through the entire process of planning everything out because you can use the same pattern as usual, but adjusting a few key points. You would have to take a different bus and walk an extra few meters to get to the new supermarket, but buying the ticket, purchasing the items inside the supermarket and returning home is still the same process. You have recognized a pattern that you can use for other problems which have similar characteristics.
The process of abstraction is to discard unnecessary details that are not relevant to solving the problem. You shouldn't, in face you cannot, take everything into account when making a decision, so you filter out any unnecessary details and focus on what is relevant to the problem you are solving. In the above example, you take the bus to get to the supermarket. Is it important that you know every stop on the way to the bus stop? No. Is it important that you know the model of the bus you are taking? No. Is it important that you know the bus drivers name? No. These are all factors that could be relevant to someone else if they have task that involves those details. For example, if you are a bus driver and you need to change shifts with a bus driver named John then it's important to know the name of the bus driver. So, it's not necessarily the case that the details are not important, but rather that there are details that are not important to your own task.
When you have decomposed the problem, identified any patterns and filtered out the unnecessary details, you are ready to create a step-by-step guide on how to solve the actual problems. At this point you need to make detailed plans for each step. You have to specify actions in the right order and with sufficient detail, so you can't just say "take the bus to the supermarket and come back when you're done". You need to specify the smaller details such as the time you need to catch the bus, where you need to catch the bus and which number bus you need to catch. Then you need to specify where to get off, which direction to take towards the supermarket and how to long walk from the bus stop. Once you're in the supermarket, you need to find all the items, collect them in a basket and pay for them. Then you repeat the bus process in reverse order making sure to take the bus from the opposite side of the street.
The importance of the four components is to focus your thinking on the details of the problem, remove any inferences you might have and realistically show what kind of problem you are dealing with. This may seem a bit strange with the coffee example, but what is important isn't the example itself, but rather the way in which it was broken down and solved. This forms a blueprint for solving problems and you can use this blueprint to solve other problems. After doing a simple example, you can scale up the complexity of the problems until you are able to this for any problem you face. However, there are other factors to take into account because after all, the world we live in isn't a static place, so things often change.
There are often things that change along the way, so it's important to understand that most of the time you will have to work within some constraints because you hardly ever have the ideal conditions for carrying out your plan. For example if the supermarket doesn't have any coffee in stock then what is the solution for that? You could buy tea instead or buy some takeout coffee from the restaurant next door. These aren't optimal solutions, but they are alternatives to the constraints that you may face in the real world. What if you find out that the buses have changed their payment systems and now you need to pay with a transit card. The only problem is that you've never used a transit card before, so you need to figure out how it works. In this case, the decomposition of your plan is still valid, but you need to adjust the algorithmic thinking portion of the four components. You would need to prioritize getting a bus transit card and loading it with money before going to the bus stop. This would form a new tasks which takes a higher priority to the other tasks since you cannot complete any of the other tasks without first getting the bus transit card.
One of the biggest problems that most people face when they are trying to progress in towards a goal is finding problems to solve. Working through a textbook or a course where there are problems laid out for you. Having the problem presented in such a way removes a great deal of the thought required because in the real world, problems aren't generally so simple to find. For example, when you are getting your education everything is laid out for you in the form of a curriculum. You have a certain amount of courses that you have to pass and the grade which you need is also decided by the administration. There is not thinking involved in deciding for yourself what is an acceptable grade to get to pass the subject, but rather you just have to focus on learning the material in the class and pad the tests. This eliminates a lot of the thought processes that you need and makes questions such as "why" unnecessary. If you asked why do you need a certain grade to pass, then the answer will most likely be that it's set by the education ministry. A situation like this is similar to a "sandbox" in the development world. This is used to refer to an environment that isn't real, but functions like a real environment in which there are certain constraints on what can be done.
There are very logical reasons why education is structured like this, so this is in no means a disparagement on the educational system. However, what tends to happen is that when you need to make decisions where the problem isn't laid out clearly then it's difficult to know where to start. Which is exactly what is expected if you haven't been trained in it. For example, if we look at education versus the job market, there is a stark difference in how the two need to be approached. When you have finished your education - whether it's high school or university - you need to find a job. There is not formula to find a job that is comparable to the formula used to get people educated. You can pass a certain number of courses after which you get a degree at university for example, but you cannot go the a certain amount of job workshops then automatically get a job. The job market doesn't work like that. Instead what it does is show you how the market works in the real world. From that you have to do some investigative work to find out where you can get an opportunity. This is an important difference between the job market and educational system because you have to decide where you start and what "grade" is acceptable.
It is, therefore, important to learn to prioritize what is the most urgent problem and solve that first. In the job market example, your first priority is to get a job because you either get a job or you are jobless. The first option is good and the second option is bad. Contrast that to deciding between two jobs that you could get. In that case, both options are good, so while there is still a choice that needs to be made, it's different from choosing between being jobless and having a job. The same applies to other decisions in life and especially the decisions in programming.
Up until now, we haven't discussed anything directly related to writing designing a program. This has been intentional because the exercise in this section is going to address that. Programming is actually better described as problem solving and using the four components of computational thinking is a guide on how to do that. So, you actually have been learning to program - although you need to learn the practicalities of it now. Programming languages are simply ways in which you can communicate the plan you have designed to a computer. The computer then does the work and what appears on the screen are the results. This could be what you expected or it could be unexpected. Base on what appears on the screen, you can continue with your plan or adjust mistakes. You repeat this process until the main problem is solved. We are going to learning to program in Python, but the programming language is largely irrelevant because writing code is similar to writing a book. There are two components that are important to writing a book: the structure and the language. The structure is the way in which the book's narrative flows and the language is the what words that are written on the pages. In the same way, computational thinking is the structure of the program (the logical flow) and the programming language (the characters on the screen) are what brings that structure to life. They are both necessary and there can be errors in both, so it's important to understand how they work together.
The way in which programming languages work vary depending on the language, but all programming languages produce error messages when something has gone wrong. A lot of new programmers get intimidated with error messages because it may seem like they have failed in writing their code. The error messages usually seem intimidating with a bunch of text on a red background, but getting an error message isn't a failure. It simple means there is a mistake in your program and the error message is giving you a log of where it could be. Usually the last line of the error message is where the immediate problem is that's preventing the program from running. Learning to understand what these error messages mean takes some time, so don't worry if it seems overwhelming at first. In 90% of cases, you can enter the last line of the error message in a search engine such as Google or a website such as Stackoverflow and there should be an answer similar to the one you are looking for.
There are many different kinds of error messages, but for the sake of simplicity we can divide them into two categories: errors which stop the program from running and logical errors. When you have written some code that violates the syntax of the language then your program will not run until you fix the problem. To use an analogy to explain this, image you write a Tweet, but before the Tweet gets published it checks if your spelling and grammar is correct. If it's not correct then it shows an error message with the line where the spelling or grammar error is located. You have to correct the mistake and resend the Tweet. That is similar to how programming works in that error messages are just showing you where a mistake is and once you fix it then you can proceed.
On the other hand, a logical error is one in which your program runs, but it's not doing what you expect it to do. If we go back to the Tweet example, in the case of a logical error, the Tweet gets send without any errors, but the actual writing doesn't mean what you intended it to mean. This type of error is the most difficult to find because it doesn't stop the program from running, so you have to understand why the program is not doing what you intended. When you find the error it could be some big mistake, but usually it's the smaller mistake that are more difficult to find. For example, if you are trying to calculate the average of two numbers, but instead of the correct answer you get a much larger number. You later find out that you multiplied (*) the two numbers together instead of adding (+) them together. These kinds of errors are very common and just like any other problems in life their causes are usually quite straightforward: you were distracted and didn't notice the error, you were tired and didn't focus when you wrote the code;, you were nervous to make a mistake, so you made a mistake, etc.
The best way to deal with errors that you can't seem to fix is to take a break from the code and do something else. Come back to the code at a later time and look through it with fresh eyes. Often you will notice things that you didn't notice before and this could help you to solve the problem much easier. The main takeaway from error messages is that you mustn't be overwhelmed by them, they are there to help you find the error and they don't indicate you have failed.
The first exercise you are going to actually program without knowing how to program. Sounds impossible, right? Well, it's possible if you understood the previous lessons. Just like in the real world, the task is not going to be laid out perfectly, but rather you have to decide what is the best way to do it. In programming languages, it's customary for the first program to print the words "Hello world!", so to keep with custom, you task to print "Hello world!" to the screen using the Python programming language. You can do this however you want, but the following are a few tips
- Think about Occam's Razor (the simplest solution is usually the optimal one)
- Don't ask anyone for help - if you get frustrated then take a break and walk around. The point is for you to solve the problem, not someone else.
- If you have tried absolutely everything and you can't figure out the answer, then read exercise hint 1.
Exercise 1 hint 1
The most difficult step in solving a problem is knowing where to start. When you have no idea what to do, the problem may seem overwhelming, but if you don't know what to do then the best place to look for answers is from what other people have done. Since we have the internet and the world is becoming more and more connected, there are many different ways to find out how other people have solved the problem or similar problems. You can use those as starting points to solve your problem. A good rule of thumb to help with this is asking yourself what, why, how and where. - **What** am I doing? - Looking for a way to print "Hello world!" to the screen - **Why** am I doing this? - As a way to understand how to solve problems that I don't have concrete instructions for. - **How** am I going to do this? - I don't know yet, I need to use the Python programming language - which I don't know - but that provides some context. - These keywords phrases "printing in the Python programming language" or "how to print hello world in the Python programming language" are good starting points. - **Where** am I going to do this? - I need to find somewhere to write the code, so key phrases such as "where can I write Python programming code" could be useful.Using these clues, you can try find some more concrete answers. Of course, the phrases are just to get you to understand the basic through process and you can use whatever means to get the task done. The fundamental principles are always keep it as simple as possible. Especially for these exercises, the answers are should be very simple, so if you find something that looks extremely complicated then try look for something simpler. You can even search on YouTube for videos explaining these concepts because there are great resources published on YouTube for people learning to write code. One last point is that you don't have to feel overwhelmed by this. If you are getting nowhere and feeling frustrated then take a break and come back to the problem later. If you are still not finding a solution then move on the exercise hint 2.
Exercise 1 hint 2
Read the exercise hint 2 fully before trying anything. In order to write Python code, you need to install Python on your local machine, create a `.py` file which contains the code you want to run and execute the code via the command line (or terminal). For example, you can create a file called `hello_world.py` and run it from the command line using the following command `python hello_world.py`. There are a few steps in this process, but each step could have several problems. For example, it won't work if you don't have Python installed on your computer. If the `hello_world.py` file is not in the correct directory then it also won't work. If you haven't written the commands correctly in the file, then it won't run properly. If you haven't got the right version of Python then you might have to use `python3 hello_world.py`, so `python hello_world.py` won't work in this case. You might not even know what a command line is, so this simple task can seem overwhelming again even if you've done all the preparation as laid out in the previous lessons.Well then what can we do if even the most simple exercise is so complicated? We take a look at the original question which is:
Print "Hello world!" to the screen using the Python programming language.
In the the exercise there is no mention of installing anything on your local machine and there are no requirements for setting up any environment for writing Python code. So, since we have access to the internet, we could look for ways in which to write Python code without the need for setting anything up. In recent times, there have been a lot of websites that have been created to help people who are coding or learning to code. Since it's difficult to understand what a piece of code is doing without seeing the results, many developers have used the latest technologies to create coding environment within browsers. This means that they can write Python (or other programming languages too) on designated sections of their websites then press a button and the code executes (in other words, the program runs). This makes it easier for people to share code and show other developers the problems they are facing, since they can run the code themselves in their browsers without the need to set everything up.
Of course, the complexity of these environment differs from website to website, but usually the basic functionality works well. So, the easiest way to solve the current exercise is to look for online Python editors. This eliminates the need to install anything on your local machine and it also eliminates errors that could be caused from different operating systems (Window, Linux or MacOS). If you have made it to this point and you still cannot solve the problem then take a break, do something else and come back to it with some fresh eyes. If you are still have trouble after that, then go on the exercise hint 3 where I will provide a solution to this problem.
Exercise 1 hint 3 (solution)
The easiest way to do this exercise is to simply search "online Python editor" on Google and the first few results will show you such an editor. Here are the websites that I got when I searched this phrase [Programiz](https://www.programiz.com/python-programming/online-compiler/), [Online Python](https://www.online-python.com/) and [OnlineGDB](https://www.onlinegdb.com/online_python_compiler). All of these websites allow you to write Python code and execute the code by pressing the run button. There you have it, you've just written some Python code.Now that you have it running, you can play around with the code. It's always good to experiment with what's going on because I could explain to you every detail, but it might not make sense to everyone. When you are working with the code yourself, you can experiment with changing the code and observe how the results change. So a few things you could try is remove some elements of the code and see what happens. Replace the quotation marks (") with apostrophes ('), does the code still run? More importantly is it still giving the expected output? What happens when you remove the last close round bracket ())? Does the code still run or does it give an error? Can you replace the round brackets () with square brackets []? If you get an error doing this then can you draw the conclusion that for a print statement you can use round brackets and not square brackets? One final experiment you can try is deleting everything from the window and retyping it from memory. Can you get it running again or does it give an error? If it gives you can error, can you understand the error message?
You don't have to answer the questions above or you can try other experiments. The point is to get it working then break it then fix again. This is all to make you think about what's happening and what the results are if you change the code in a certain way. That being said, if the process can be so simple, then you might be wondering what's the point of setting up a Python environment on your own computer? For starters, if you don't have access to the internet then you can't run anything online. However, more important than that, the online Python editors are usually very basic and don't include more advanced packages and libraries that you might need. So, when you are working on developing programs for specific tasks, you will need to setup environments of your own, but remember to keep it simple. If all you need to do is print a simple sentence then the online editors are sufficient. A big component of programming (and problem solving in general) is to get the best results, with the least effort in the most efficient way possible. As was discussed previously, though, you won't always achieve this because of time, lack of knowledge or other constraints. So, don't worry about that for now, but rather focus on getting it working and keeping it simple.
It might still be a bit difficult to find out where to start when solving a problem, so there is a useful tool that you can use called an IPO (input, processing and output) table. It's a simple table where you have three columns with the previously mentioned names: input, processing and output. Using an IPO table, we can outline the print("Hello World!") example from earlier.
Input | Processing | Output |
---|---|---|
Words the need to be displayed on the screen, "Hello World!" in this case. | We will use the print() function. | "Hello world!" is displayed on the screen |
This is a very simple example, but it's a good way to breakdown what is required for the task at hand. In these kinds of simple examples it's a little tricky to understand why this would be useful, but in more complex examples it is very useful to understand exactly what is being passed as input into the program and what you expect as output. This is especially true when you have complex programs that rely on the output of one step to become the input of another one. For example, imagine you want to wash your clothes, so you create the following steps
Step 1 - Wash clothes
Input | Processing | Output |
---|---|---|
Clothes, washing liquid and washing machine | Place clothes in washing machine and start washing | Wet clothes |
Step 2 - Dry clothes
Input | Processing | Output |
---|---|---|
Wet clothes and dryer | Place wet clothes in dryer, select dryer program and start the process | Dry clothes |
Step 3 - Fold clothes
Input | Processing | Output |
---|---|---|
Laundry basket and dry clothes | For each item of clothing, remove it from the basket, fold it and packet away | Folded clothes in the cupboard |
From the above explanation you can see the the output of step 1 and 2 form the input of step 2 and 3 respectively. Step 3 also has laundry basket, but that's perfectly fine if you have planned to do that. You realize, though, when looking through your folded clothes that there is still a stain on one of your shirts. You go through your IPO table and you find out that you didn't actually use the washing liquid, so the program ran effectively, but it didn't work as planned. Luckily, because you have written down your IPO tables, you can easily find the mistake. IPO tables are a great way to visualize thought processes in a way that is easy to follow, thus easy to execute. Since you have everything written down, you can go through the plan to easily find where any mistakes could've been made that would affect the final results.
Using IPO tables you can easily breakdown a problem into its different logical steps. In the previous exercise, we've learned the simple solution of printing something to the screen. In this exercise we're going to get a bit more complicated, but if you follow the steps laid out in the beginning (decomposition, pattern recognition, abstraction and algorithmic thinking) together with IPO tables, you should have at least some idea of what to do for the next exercise. We discussed that it's important to understand why you are doing a task to help you keep focused on the ultimate goal. However, this is difficult when doing exercises because the exercise itself has no purpose other than doing it. So for the sake of of the exercise, I will provide a why to your task. Let's image you want to find the 10 most common words in a certain text (in Python text data is called a string). You need to do this because you are looking for the most common words in a text to make reading it easier for second language learners. Writing down the 10 most common words beside the text with their translation will give second language learners a kick start in understanding the main topic of the text. However, you want to do this for 100 texts, but you don't have time to do it manually. The following steps will help solve this problem.
Step 1
Input | Processing | Output |
---|---|---|
String | Assign string to a variable | variable |
Step 2
Input | Processing | Output |
---|---|---|
Variable | Make a list of all the words in the variable by using split() | List of words |
Step 3
Input | Processing | Output |
---|---|---|
List of words | Count all the words | List of words together with how many times they appear in the text (frequency) |
Step 4
Input | Processing | Output |
---|---|---|
List of words together with how many times they appear in the text (frequency) | Sort the words from highest to lowest frequency | Sorted list of words |
Step 5
Input | Processing | Output |
---|---|---|
Sorted list of words | Print first 10 to the screen | 10 most common words |
As you can see from the above steps, we have broken down the problem into 5 simple steps that need to be followed. The processing part of each IPO table is what you need to actually program. So you would need to figure out how to write code for the following:
- How to assign a string to a variable in Python?
- How to make a list by using split() in Python?
- How to count the frequency of words (in a list) in Python?
- How to sort a list of words in Python?
- How to display the first 10 items in a list in Python?
There is an easy breakdown of what actually needs to be done. As with the previous exercise, you probably don't know what a list is in Python, but that's okay because you have the guidelines available to figure it out. As with the previous exercise, try from number 1 to number 5 and if you get stuck then search around for answers. I will give three hints again together with the answer for those who cannot progress, but the purpose of the exercise is to move step by step through the tasks and search for those parts you don't understand.
Exercise 2 hint 1
If you are stuck on the first part of the exercise then there are a few steps that you can take to get started. First, you need to understand what everything means in the sentence (number 1). The three words that might prove to be a problem are "assign", "string" and "variable". In Python assign means placing the known value of something (in this case a body of text which is also called a string) into a variable. The variable is a word that you create which contains the value of whatever you assigned to it (in this case the string). Consider the following examples:"This is a test sentence"
(This is a text or in Python a string)
sentence
(This is a variable name - currently this variable has no value)
sentence = "This is a test sentence"
(This is assigning a string to the variable)
If we go back to the print("Hello world!") exercise from before, we can use the same structure (pattern recognition), but change it a little bit to prince out the variable. So, we can write print(sentence)
and this will display the string "This is a test sentence"
which is the value of the variable. If you remember from previous lessons, we mentioned that it's always important to understand why you are doing something. So, in this case why is it important to assign the value of the string to the variable? Why can't we just use the string itself? In these simple examples, it may not be clear, but if we have an entire paragraph of text then it's easier to work with a single word that refers to that text instead of working with the text every time. This reduces the chances for mistakes and it is also easier to understand what is happening in the code you are writing. One of the ultimate goals of writing code is to be able to be able to look at it a few years from now and still understand what the intention is of the code.
If you weren't able to figure out the first sentence on your own and the above explanation helped you to understand then there is a small exercise that you can do. Since the purpose of this course is to develop independent thinking, the real goal isn't to explain the concepts to you, but rather to point them out so you can find out what they mean. In the above case, there is a step-by-step explanation, but you can still develop independent thinking by looking for verification of this information. If you search these words do you find the same explanations? Are the explanations that I gave accurate to your understanding? Doing this when you get an explanation can still help you be better at independent thinking and finding answers for yourself - which is the basis of computational thinking.
Exercise 2 hint 2
Hopefully you have figured out how to assign text to a variable, but in case you haven't then it works as follows. Replace the three dots `...` with whatever text you are using making sure there are no double apostrophes in your text. Double apostrophes in Python indicate that whatever you have between them is text, so if you have double apostrophes then it will cut your text at that point and probably will raise an error.sentence = "..."
With your variable called sentence
you now have a reference to the text that you want to work with. We can take a look at the IPO table we wrote down for step 2 and see what we need to do with this variable. We need to get a list of words from the variable, so we need to think of what that means practically. A word is an element of a sentence which - in English at least - has the characteristic of a space before and after the word (this is also referred to as a white space). So, if we can isolate each individual word and add that to a list then we have a list of all of the words. Luckily in Python there is a function called split
which takes a string, splits it at whichever character you specify and returns a list. You need to assign it to a new variable because if you split the sentence variable without assigning it then it will just display the list, but not keep it in memory. Here is how you can do this:
sentence_words_list = sentence.split()
There default setting is to split it at each white space, but you can change that to whichever character you want in case you want to split it on a different character.
sentence_words_list = sentence.split(".")
(this splits it on each full stop)
sentence_words_list = sentence.split(". ")
(this splits it on each full stop followed by a white space)
Splitting on a full stop followed by a white space is a very quick way to split into sentences (although not very accurate, since it will miss question marks, exclamation marks, etc). Very aware that when you specify a character to split, it must be between apostrophes (double or single). For this exercise, we only need the default setting of splitting at the white space, since we need the individual words. After doing this, we now have a list of words, but it won't be perfect i.e. there is still punctuation and capital letters. For now, we don't have to worry about that because we want to get everything working before we evaluate the finer details. One part of writing code that is beneficial is to build something as quick as possible then make changes afterwards. The quick version of the code acts as a baseline, so you can see when you make changes how those changes affect the overall results of the program.
Exercise 2 hint 3
Now that you have a list of words (let's call it List A), you can count how many times they each appear. I'm going to walk through the thought process of doing this, but I'll provide an easy way at the end, so read the whole hint before trying any code. If you think of how this could be done manually by a person then one way to do it is to make a new list which we call List B. You would take the first word (let's call it Word 1) from List A and write it in List B. Then you would look through each word in List A and when you find Word 1, you add the number 1 next to Word 1 which is written in List B. Repeat this for all the words and you will have all the words written once in List B together with how many times they appear in List A i.e. their frequency. Another way that you could do this is to create the same two lists, but when you go through List A, you can update List B with each word. This would mean writing Word 1 in List B then move on to Word 2. Check if Word 2 is in List B. If it is in List B then you add one to it's count. If it's not in List B then you write it in List B with a count of 1. Repeat this until you get to the end of List A. Both of these methods would work for counting the words and there are probably other methods that you could figure out.However, we are not trying to get the quickest method for counting the words or comparing different methods for counting words. We simply need a way to count the words, so we can move on to the next step of our main task. Like we discussed earlier, don't get caught up in the finer details and forget what the main goal is. The ideal situation would be a single line of code that could count the words in a list and return that as a list. After all, if someone has already done the work then it saves us time and it prevents us from reinventing something that already exists. Luckily for us, there is a module called collections
that has a function called Counter
which does just what we are looking for. Using the list we created in the previous exercise, we can count the words in 1 line of code (after importing the module of course).
from collection import Counter
sentence_words_list_counted = Counter(sentence_words_list)
Now there is a slight challenge here that you can try solve before moving on to the next hint. sentence_words_list_counted
is not actually a list, but it's a Counter object. How can you work with Counter objects?
Exercise 2 hint 4 (solution)
At this point, if you've managed to do the exercise using the Counter object then it's quite simple to finish the rest of the steps and output the top 10 words. All you need to do is is the following:print(sentence_words_list_counted.most_common())
This will display the most common words together with their frequencies, however, if we want to get only the 10 most frequent words then we can simply specify that as an argument as follow. If you don't know what an argument is then search "what is an argument in Python?" and see if you can figure out which part of the following code is the argument.
print(sentence_words_list_counted.most_common(10))
In case you couldn't figure out what the argument was, it's the 10 in the above example. The argument in a Python function is whatever is between the parentheses. For example, in the above case there are actually two functions:
print()
sentence_words_list_counted.most_common()
In the case print (function 1), the argument is sentence_words_list_counted.most_common()
(function 2) and the argument of function 2 is 10. You can pass any whole number in function 2 as an argument as long as it's smaller then the number of words in the list. If we had to write what it's doing into plain English is would be as follows: most_common()
displays all the words in sentence_words_list_counted
, but as a list and not a Counter object. If you add an argument (in this case 10) then it displays only the top 10.
Using the Counter module is a quick and easy way to solve the problem, but if we wanted to sort the list ourselves, how could we do that? We know that sentence_words_list_counted.most_common()
without any arguments gives us the list of words with their frequencies. Let's create a new variable and assign that list to the new variable.
top_10_words = sentence_words_list_counted.most_common()
top_10_words
is a normal Python list that contains where each element is a tuple (if you don't know what a tuple is then search "what is a tuple in Python?" to find out). The first part of the tuple is the word and the second part of the tuple is the frequency of the word. If we take a step back and think about sorting again, there are a few ways we could sort a list like this: by the frequencies, alphabetically by the words, and we can do that from biggest to smallest (descending) or some smallest to biggest (ascending) order. The following code will display the list sorted in alphabetical order.
print(sorted(top_10_words, lambda x: x[0]))
The next code will sort and display the code in reverse alphabetical order
print(sorted(top_10_words, lambda x: x[0], reverse=True))
So, we have the following results:
- Sorted from biggest to smallest by frequency:
print(sorted(top_10_words, lambda x: x[0]))
- Sorted from smallest to biggest by frequency: ?
- Sorted alphabetically:
print(sorted(top_10_words, lambda x: x[0]))
- Sorted reverse alphabetically:
print(sorted(top_10_words, lambda x: x[0], reverse=True))
Can you figure out number 2 (sorted from smallest to biggest by frequency)?
This exercise was quite a lot of work to solve a simple tasks of displaying the top 10 words, but there are many benefits and most of the work done for this tasks can be reused literally or conceptually. You can literally reuse the text in case you need to find the top 10 words of another text or maybe expand that to find the top 100 words in multiple texts. In those cases, you just need to replace the current text in this piece of code with the new text you are working with. In terms of conceptually reusing the code, this links back to the four components of computational thinking we discussed in the beginning. Steps 1-5 that we have laid out above is an example of algorithmic thinking because it lays out the solution in a step-by-step way that is easy to follow. You can reuse this concept to solve other problems that are similar to it which refers to recognizing the patterns by which the problem was solved - this is pattern recognition.
Looking back on how we managed to solve to problem is a good way to understand the process as a whole, remember the key points and also find ways in which we could have done it better. Code can always be more efficient and effective, and problems can always be solved in different ways. So, it's important to review what solutions you have produced so that later on you can apply them to other problems. This might make more work in the beginning, but it will be worth the work later on. The more you create solutions and adapt them to solve other problems, the easier it becomes. The easier it becomes to do this, the quicker, more efficient and more accurate you will be able to do it.
One last point to consider from this exercise is that not everything was explained. Sometimes, you came across words and concepts that you didn't understand. This was intentionally done because when you are faced with a real-world problem which you have to solve, you usually won't have a starting point explained to you, since you are the one who has to solve the problem. So, it's imperative to learn how to find the answers to things you don't understand without the need for someone to explain it to you. A lot of the time you will have someone to help you or explain it to you, but in the cases where you don't have that person, you need to be at least come up with an idea to find the answer.
You are probably still confused as to what's going on and that's okay. Problem solving and programming are all about organizing unclear information into something that is clear and understandable. This is why it's so difficult for most people to understand, but with enough practice, we can start to become better and smarter in the way we solve problems. There are some key points to understanding how to solve a problem other than the four components of computational thinking and they involve breaking some assumptions that you might have when you start solving the problem. Much like anything in life, when you start, you probably won't have great results - that's okay. When you start, you probably won't know where to start - that's okay. When you do start and you get a program running, it's probably not going to be the most efficient it can be - that's okay. Even when you get your code running, there will probably be a lot of lines that can be improved - that's okay. You may be wondering, why I listed all the bad things that can happen when coding, but it's important to understand that it happens to everyone and at every level of coding. These problems are not rare, but are extremely common. Something rare when writing code or solving a problem is if everything works perfectly from the start - this would be a cause for concern.
With all the problems that could happen, you may wonder how you can improve them. The way to do this is quite simple, but not necessarily easy: small improvements, consistent practice and learning from others' mistakes. For example, if you wrote a program last week that runs, but is quite slow then you can review the code you wrote and search ways to make it faster. This will improve your understanding and you will be able to implement that faster method next time you write a line of code. The easiest way to improve your problem solving abilities is to solve problems - start with small problems the move on to bigger problems. Lastly, you can learn from other peoples' mistakes. Often on websites such as Stackoverflow, you will find answers to questions people have asked. This is a great way to save time by learning how other people have solved a problem, but without you having to spend as much time as they did. This helps you to improve much faster by using the lessons of other people. The rest of this section will look at breaking down real world problems into steps which can provide some structure on how to solve them. The purpose is to show you how problems can be broken down, what challenges some solutions could cause and inspire your own thinking on how to solve the problems. Keep one thing in mind: there is usually never a perfect solution, so if you have a solution that is better than the one provided here, let us know. Providing better solutions helps us all be better.
In the following sections, I will present a scenario in a sentence or two that is written in plain English - no programming jargon. I will then break down the problems into steps to show the thought process of solving real problems and what challenges you might face doing it yourself. The purpose of this is as examples, but also real solutions that you can use if you need to do something similar to what is described in the examples.
I want to open a file that I have on my computer so that I can use the content for a program I am writing.
We will start with the IPO tables to break the problem down into smaller steps that we can solve easier.
Step 1
Input | Processing | Output |
---|---|---|
File | Find the path to where the file is stored on your computer | Filepath (string) |
Step 2
Input | Processing | Output |
---|---|---|
Filepath (string) | Load the file by using the filepath | Contents of the file |
Step 3
Input | Processing | Output |
---|---|---|
Contents of the file | Assign the contents of the file to a Python variable | Variable that contains the contents of the file (string) |
In only 3 steps we can describe how to load the contents of a file into a variable in Python. By assigning the contents to a variable we now have them in the correct format to use for the rest of whatever program we are writing. You will notice that there is no code involved in the above steps and this is known as pseudocode. Pseudocode is like a blueprint for how the program will function, so in effect it is not programming language specific - you can apply this blueprint to any programming language. The language written down won't be the same, but the steps will be the same.
Why is this a good way to start when solving a problem? It provides structure to your solution without being too strict. As you can see in the processing section of step 2 "load the file by using the filepath" gives a good guide to what needs to be done, but keeps it vague enough that you can implement it anyway you feel works best. Just like people speak and write differently, programmers write code in different ways. This doesn't always mean that one solution is better than the other, but rather that there are many solutions to each problem. It's easier to learn coding when you get a guideline and you have to figure out how to implement the solution.
When you are given a problem to solve then you can break it down and find the answers that best match your way of understanding. This will help you to personalize the information which is the best way to understand and remember it. For example, perhaps you are unclear about how to find the filepath, so I explain it to you. However, you don't quite understand my explanation, so you search for some articles online and someone else explains it in a better way than me, but they use a different method. Having a guideline of what the general purpose of the task gives you the freedom to implement the solution in any way you can. It might even be better than anything I can come up with, so it's all about finding what best works for you and understanding that.