Git Product home page Git Product logo

futurecoder's Introduction

MIT license Tests status logo Testing Powered By SauceLabs

futurecoder

This is a 100% free and interactive course for people to teach themselves programming in Python, especially complete beginners at programming. It is carefully designed to reduce frustration and guide the user while still ensuring that they learn how to solve problems. The goal is for as many people as possible to learn programming.

You can try it out here: https://futurecoder.io/

Please consider contributing or donating!

Alternatively, come have a chat on slack.

Features

For a fuller demonstration and explanation, watch this video.

The course is a fully interactive 'book' which requires the user to run code in the provided editor or shell to advance:

full

This requires a mixture of solving problems or simply typing and running provided code. In the latter case, the user is often kept engaged by being asked to predict the output in a simple multiple choice question: The code at each step is checked automatically. If needed, the student can get small hints to gradually guide them to the solution:

predict_output

hints

If they're still really stuck, they can reveal the solution bit by bit:

Or in some cases solve a Parsons problem instead, where they have to put a shuffled solution in the correct order:

solution

parsons

Tracebacks are more helpful than usual, with several enhancements:
  • Highlighting the exact operation that failed, not just the line, using executing
  • Tables of local variables and simple expressions evaluated by pure_eval
  • Suggestions for fixes provided by DidYouMean
  • Beginner friendly explanations provided by friendly-traceback (shown when hovering over the little i icon)
  • Showing multiline statements in full thanks to stack_data without showing unnecessary extra lines
Common mistakes can be caught and pointed out to the student. This includes specific checks in some steps as well as linting tailored for beginners.

traceback

executing

Several debuggers are provided, including snoop...

...birdseye...

snoop

birdseye

...and Python Tutor

pythontutor

Running locally

  1. Fork this repo, git clone it, and enter the top-level futurecoder folder.
  2. Install Python 3.11.2 and poetry.
  3. Run poetry install to install Python dependencies.
  4. Run ./scripts/generate.sh. This will generate various static files from Python used by the frontend and run some tests. Repeat this step whenever you change Python files.
  5. In the frontend folder:
    1. Install node. We recommend using version 16.17.1 (lts/gallium) but there are no known issues with other versions.

    2. Run npm ci to download dependencies.

    3. Run npm run build and then copy service-worker.js from the course folder to the public folder. The service worker is used by sync-message to handle time.sleep and reading from stdin (e.g. input()) in Python. If you want to enable caching (not a good idea when developing), set the environment variable REACT_APP_PRECACHE=1 when building.

    4. Run npm start to start the frontend development server.

  6. Go to http://localhost:3000/course/

To learn more about the system, see the contributing guide.

Controls

To explore the course more freely:

  1. Click the hamburger menu icon in the top left.
  2. Click Settings.
  3. Turn Developer mode on.
  4. This should give you two red buttons floating at the bottom of the screen. They change the currently active step, so you can move forward without having to complete exercises or backwards to test a step again.

futurecoder's People

Contributors

alexmojaki avatar andrewpluzhnikov avatar bobankh avatar cclauss avatar chrisjanwust avatar daviddavid avatar dependabot[bot] avatar floer32 avatar harimm avatar josephmarcus9 avatar matan-h avatar oskarissimus avatar pwwang avatar spamegg1 avatar tamilneram avatar tony avatar vokounigor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

futurecoder's Issues

UI feedback in feedback form

Users can provide feedback from the menu, which gets sent to Sentry. Currently nothing visible happens after clicking Submit. At the very least, we need some indication of success. Apart from that it would be good to show a spinner while submission is in progress.

Notes from spamegg1

Hi @spamegg1

I think we chatted a bit too much on #23, it's a central issue that lots of people are going to look at and some of it went off topic. We may want to edit some of it out at some point. For now let's just keep talking here. I should probably also be setting up a Slack workspace or some other chat medium.

  • The blinking cursor is not on the same line as '>>>', the way it would be in IDLE installed on a user's PC. (This could become crucial much later on with doctest)

This is what I see:

Screen Shot 2020-07-30 at 19 50 47

What do you see?

  • I'm not sure about the row stuff... it might be a good idea to save that for later, for the tic-tac-toe project, or dive right into that project at this point. Too difficult for now?
  • There should be a very clear indicator to the user "you are starting a project!" and its material should be self-contained, to make the user focus, and give them a strong sense of accomplishment. At least this is how I approached it in mine.

The tic tac toe project (#3) requires at least while loops and functions, which are not covered yet. We can't go there yet from boolean operators.

I think the and/or stuff is reasonably good up until the exercise to find a diagonal winner. From there my ideas got fuzzier - there should be a better example for not and we could leave the stuff below that for another time or for the project.

  • I think it might be a GOOD idea to start introducing a few Python specific tricks.

I want to avoid information overload. There's a lot to learn. So I think tricks in general should be mentioned briefly and without any exercises or other requirements for you to know them.

  • In word + name is word left undefined on purpose? Good pedagogical technique, undefined names are a common issue for beginners.

What exactly happened for you here? The intention is that you've already defined word on the previous page and it should still be in your shell. However if you go inactive for a long time your session might die and so by the time you reach word + name it's no longer defined. In that case when you get the error there should be a message "Oops, you need to set word = 'Hello' before we can continue." But that's not what we want to happen, word should usually be already defined at that point.

  • Will there be mention of single, double and triple-double quotes?

There should be at some point, but it's mostly a boring technical detail so I'm thinking I'll leave it for later. I want the course to start out as interesting as possible to keep the user's attention. That's why for loops are introduced quite early - it makes for interesting programs. However I have already accidentally used double quotes in text and exercises in some places, will need to do something about that.

Aaaahh... OK! Wow I was being dumb...

No worries, we all have our moments. It's very useful to see the things that can trip users up.

Also I forgot to use the Hint feature, so I guess there is no way to get "stuck" is there?

Sometimes, as you did, new users will forget to ask for hints. Maybe the first exercise should be a fake exercise that they solve by clicking the hint button all the way to revealing a solution.

Besides that, not every step has hints, although usually it's an obvious step like 'run this exact code'.

So everything up to and including nested for-loops has already been written then?

Yes, but it's not set in stone. The list chapter especially could use some refining.

One question: will there be "branching out" in the material later on?

As a starting point let's implement bonus challenges in #21

Oh I noticed the "hamburger" button on the top right JUST now. Feel very dumb once again.

Stop feeling bad. Let's point it out to the user near the beginning of the course. It's important they know it's there so they can give feedback if they want.

Cursor in wrong place in shell

The cursor should appear directly after >>> in the shell, like this:

Screen Shot 2020-07-30 at 19 50 47

On my machine this works correctly in Chrome, but not in Firefox or Safari, where it does this:

>>>
123 (what I type goes here, not the line above)

After I hit Enter it becomes:

>>> 123 (what I typed earlier)
(result appears here)

Thanks @spamegg1 for reporting this in #27, I didn't know about it because I only use Chrome.

The place to start looking for the problem is in frontend/src/shell/Terminal.jsx. The code is copied and modified from the project react-console-emulator, it might be helpful to look at what happens there and if what has changed since the code was copied.

Unable to run commands in shell - update

User Issue
Email: [email protected]
User Agent: PC / Windows 10 / Edge 84.0.522

I'm able to run commands on Chrome on an Android phone, but not on Safari on an iPad. The issue is the same as the previous one, where the shell responds to commands by saying the process timed out as the code is taking too long to run.

Redux state

{
  "rpc": {
    "loading": [],
    "error": null
  },
  "book": {
    "server": {
      "hints": [],
      "step_index": 0,
      "pages_progress": [
        2,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "page_index": 2,
      "showEditor": false,
      "showSnoop": false,
      "showPythonTutor": false,
      "showBirdseye": true
    },
    "pages": [
      {
        "slug": "IntroducingTheShell",
        "title": "Introducing The Shell",
        "index": 0,
        "step_texts": [
          "<p>At the bottom right of the screen is the <em>shell</em>. This is a place for running small bits of Python code. Just type in some code, press enter, and it'll run! Try it now:</p>\n<ol>\n<li>Click anywhere on the shell (the black area).</li>\n<li>Type <code>1+2</code></li>\n<li>Press the Enter key on your keyboard.</li>\n</ol>",
          "<p>Great! Python evaluated <code>1+2</code> and got the result <code>3</code>, so the shell displays that.</p>\n<p>The shell is probably your most important tool for learning Python, and you should spend lots of time experimenting and exploring in it. Be curious! Constantly ask yourself \"What would happen if I ran X?\" and then immediately answer that question by running it! Never be scared to try something out - if you get something wrong, nothing bad will happen.</p>\n<p>Try doing some more calculations now. You can multiply numbers with <code>*</code>, divide with <code>/</code>, and subtract with <code>-</code>. You can also use parentheses, i.e. <code>(</code> and <code>)</code>.</p>",
          "<p>Excellent! Keep experimenting. When you're ready, click 'Next' to continue.</p>"
        ]
      },
      {
        "slug": "NavigatingShellHistory",
        "title": "Navigating Shell History",
        "index": 1,
        "step_texts": [
          "<p>Here's a tip: often you will want to re-run a previously entered bit of code, or a slightly modified version of it. You can copy and paste, but that's tedious and gets in the way of experimenting. A better method is to press the Up Arrow key on your keyboard. This will insert the previous line of code into the shell. Keep pressing it to go further back in your history, and if you go too far, press the Down Arrow key to go the other way. Try using it now.</p>"
        ]
      },
      {
        "slug": "IntroducingStrings",
        "title": "Introducing Strings",
        "index": 2,
        "step_texts": [
          "<p>Python lets you do much more than calculate. In fact, we're not going to touch numbers or maths for a while. Instead, we're going to look at <em>strings</em>. Strings are essentially snippets of text. For example, enter the following into the shell, quotes (<code>'</code>) included:</p>\n<pre><code>'hello'\n</code></pre>",
          "<p>The shell simply gives the same thing back because there's nothing to further to calculate. <code>'hello'</code> is simply equal to <code>'hello'</code>.</p>\n<p>A string is a sequence of characters. A character is a single symbol such as a letter, number, punctuation, space, etc. In this case the string contains the 5 characters <code>hello</code>. The quotes are not part of the string - they are there to tell both humans and computers that this is a string consisting of whatever characters are between the quotes.</p>"
        ]
      },
      {
        "slug": "AddingStrings",
        "title": "Adding Strings",
        "index": 3,
        "step_texts": [
          "<p>Strings can be added together using <code>+</code>, although this means something very different from adding numbers. For example, try:</p>\n<pre><code>'hello' + 'world'\n</code></pre>",
          "<p>You can see that <code>+</code> combines or joins two strings together end to end. Technically, this is called concatenation.</p>\n<p>Here's an exercise: change the previous code slightly so that the result is the string <code>'hello world'</code>, i.e. with a space between the words.</p>\n<p>By the way, if you get stuck, you can click the lightbulb icon in the bottom right for a hint.</p>",
          "<p>Well done! Any of the following are valid solutions:</p>\n<pre><code>'hello ' + 'world'\n'hello' + ' world'\n'hello' + ' ' + 'world'\n</code></pre>"
        ]
      },
      {
        "slug": "IntroducingVariables",
        "title": "Introducing Variables",
        "index": 4,
        "step_texts": [
          "<p>To make interesting programs, we can't always manipulate the same values. We need a way to refer to values that are unknown ahead of time and can change - values that can vary. These are called <em>variables</em>.</p>\n<p>Run this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>",
          "<p>This creates a variable with the name <code>word</code> that refers to the string value <code>'Hello'</code>.</p>\n<p>Check now that this is true by simply running <code>word</code> in the shell by itself.</p>",
          "<p>Good. For comparison, run <code>'word'</code> in the shell by itself, with the quotes.</p>",
          "<p>As you can see, the quotes make all the difference. <code>'word'</code> is literally just <code>'word'</code>, hence it's technically called a <em>string literal</em>. On the other hand, <code>word</code> is a variable, whose value may be anything.</p>\n<p>Similarly, <code>'sunshine'</code> is <code>'sunshine'</code>, but what's <code>sunshine</code> without quotes?</p>",
          "<p>The answer is that <code>sunshine</code> looks like a variable, so Python tries to look up its value, but since we never defined a variable with that name we get an error.</p>"
        ]
      },
      {
        "slug": "UsingVariables",
        "title": "Using Variables",
        "index": 5,
        "step_texts": [
          "<p>Previously we made a variable called <code>word</code> with the value <code>'Hello'</code> with this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>\n<p>Now make a variable called <code>your_name</code> whose value is another string.</p>\n<p>(The character <code>_</code> in <code>your_name</code> is called an <em>underscore</em>. Use it to separate words when you want a variable name containing multiple words. You can type it on most keyboards by pressing Shift and hyphen/dash/minus (<code>-</code>).)</p>",
          "<p>You can use variables in calculations just like you would use literals. For example, try:</p>\n<pre><code>'Hello ' + your_name\n</code></pre>",
          "<p>Or you can just add variables together. Try:</p>\n<pre><code>word + your_name\n</code></pre>",
          "<p>Oops...that doesn't look nice. Can you modify the code above so that there's a space between the word and your name?</p>",
          "<p>Perfect!</p>\n<p>Variables can also change their values over time. Right now <code>word</code> has the value <code>'Hello'</code>. You can change its value in the same way that you set it for the first time. Run this:</p>\n<pre><code>word = 'Goodbye'\n</code></pre>",
          "<p>Now observe the effect of this change by running <code>word + ' ' + your_name</code> again.</p>",
          "<p>Those quotes around strings are getting annoying. Try running this:</p>\n<pre><code>print(word + ' ' + your_name)\n</code></pre>",
          "<p>Hooray! No more quotes! We'll break down what's happening in this code later. For now just know that <code>print(&lt;something&gt;)</code> displays <code>&lt;something&gt;</code> in the shell. In particular it displays the actual content of strings that we usually care about, instead of a representation of strings that's suitable for code which has things like quotes. The word <code>print</code> here has nothing to do with putting ink on paper.</p>"
        ]
      },
      {
        "slug": "WritingPrograms",
        "title": "Writing Programs",
        "index": 6,
        "step_texts": [
          "<p>It's time to stop doing everything in the shell. In the top right you can see the <em>editor</em>. This is a place where you can write and run longer programs. The shell is great and you should keep using it to explore, but the editor is where real programs live.</p>\n<p>Copy the program below into the editor, then click the 'Run' button:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nprint(word + ' ' + name)\nword = 'Goodbye'\nprint(word + ' ' + name)\n</code></pre>",
          "<p>Congratulations, you have run your first actual program!</p>\n<p>Take some time to understand this program. Python runs each line one at a time from top to bottom. You should try simulating this process in your head - think about what each line does. See how the value of <code>word</code> was changed and what effect this had. Note that when <code>print</code> is used multiple times, each thing (<code>Hello World</code> and <code>Goodbye World</code> in this case) is printed on its own line.</p>\n<p>Some things to note about programs in the editor:</p>\n<ol>\n<li>The program runs in the shell, meaning that the variables defined in the program now exist in the shell with the last values they had in the program. This lets you explore in the shell after the program completes. For example, <code>name</code> now has the value <code>'World'</code> in the shell.</li>\n<li>Programs run in isolation - they don't depend on any previously defined variables. The shell is reset and all previous variables are cleared. So even though <code>word</code> currently exists in the shell, if you delete the first line of the program and run it again, you'll get an error about <code>word</code> being undefined.</li>\n<li>If you enter code in the shell and it has a value, that value will automatically be displayed. That doesn't happen for programs in the editor - you have to print values. If you remove <code>print()</code> from the program, changing the two lines to just <code>word + ' ' + name</code>, nothing will be displayed.</li>\n</ol>\n<p>I recommend that you check all of these things for yourself.</p>"
        ]
      },
      {
        "slug": "StoringCalculationsInVariables",
        "title": "Storing Calculations In Variables",
        "index": 7,
        "step_texts": [
          "<p>Often you will use variables to store the results of calculations. This will help to build more complex programs. For example, try this program:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nsentence = word + ' ' + name\nprint(sentence)\n</code></pre>",
          "<p>Now <code>sentence</code> has the value <code>'Hello World'</code> which can be used multiple times. Note that it will continue to have this value until it is directly reassigned, e.g. with another statement like <code>sentence = &lt;something&gt;</code>. For example, add these two lines to the end of the program:</p>\n<pre><code>word = 'Goodbye'\nprint(sentence)\n</code></pre>",
          "<p>Unlike a spreadsheet where formulas update automatically, a variable like <code>sentence</code> doesn't remember how it was calculated and won't change if the underlying values <code>word</code> or <code>name</code> are changed.</p>"
        ]
      },
      {
        "slug": "IntroducingForLoops",
        "title": "Introducing For Loops",
        "index": 8,
        "step_texts": [
          "<p>Good news! You've made it past the boring basics. We can start to write some interesting programs and have a bit of fun. One of the most powerful concepts in programming is the <em>loop</em>, which lets you repeat the same code over and over. Python has two kinds of loop: <code>for</code> loops and <code>while</code> loops. Here is an example of a for loop, try running this program:</p>\n<pre><code>name = 'World'\nfor character in name: print(character)\n</code></pre>",
          "<p>You can read the code almost like normal English:</p>\n<blockquote>\n<p>For each character in the string <code>name</code>, print that character.</p>\n</blockquote>\n<p>Each character is just a normal string. <code>character</code> is a normal variable that is given a new value before the code after the <code>:</code> runs. So the code above is equivalent to:</p>\n<pre><code>name = 'World'\n\ncharacter = 'W'\nprint(character)\n\ncharacter = 'o'\nprint(character)\n\ncharacter = 'r'\nprint(character)\n\ncharacter = 'l'\nprint(character)\n\ncharacter = 'd'\nprint(character)\n</code></pre>\n<p>Note that we could use a different variable name, <code>character</code> just makes it clearer.</p>\n<p>A for loop generally follows this structure:</p>\n<pre><code>for &lt;variable&gt; in &lt;collection&gt;: &lt;code to repeat&gt;\n</code></pre>\n<p>The <code>for</code>, <code>in</code>, and <code>:</code> are all essential.</p>"
        ]
      },
      {
        "slug": "Indentation",
        "title": "Indentation",
        "index": 9,
        "step_texts": [
          "<p>This example loop:</p>\n<pre><code>for character in name: print(character)\n</code></pre>\n<p>works, but actually it would usually (and should) be written like this:</p>\n<pre><code>for character in name:\n    print(character)\n</code></pre>\n<p>Specifically, the code to be repeated (known as the <em>body</em>) starts on a new line after the colon (<code>:</code>), and it must be <em>indented</em>, i.e. have some spaces before it. The code below without indentation is invalid, run it to see for yourself:</p>\n<pre><code>for character in name:\nprint(character)\n</code></pre>",
          "<p>The spaces are required to tell Python which lines of code belong to the body of the for loop. This is critical when the loop contains several lines, which it often will. For example, run this code:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>",
          "<p>There are two indented lines, so they're both part of the body, so <code>---</code> gets printed after each character. Now try running the same code without the indentation in the last line:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\nprint('---')\n</code></pre>",
          "<p>Since <code>print('---')</code> is not indented, it's not part of the loop body. This means it only runs once, after the whole loop has finished running. Both programs are valid, they just do different things.</p>\n<p>The program below is invalid. Both lines in the loop body are indented, but by different amounts. The first line starts with 4 spaces, the second line starts with 2. Try running it.</p>\n<pre><code>for character in name:\n    print(character)\n  print('---')\n</code></pre>",
          "<p>When you indent, you should always indent by 4 spaces. Any consistent indentation is actually acceptable, but 4 spaces is the convention that almost everyone follows. Note that the editor generally makes this easy for you. For example, if you press the 'Tab' key on your keyboard in the editor, it will insert 4 spaces for you.</p>"
        ]
      },
      {
        "slug": "BasicForLoopExercises",
        "title": "Basic For Loop Exercises",
        "index": 10,
        "step_texts": [
          "<p>Time for some exercises! Modify this program:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>\n<p>to instead output:</p>\n<pre><code>---W\n---o\n---r\n---l\n---d\n</code></pre>",
          "<p>Splendid! Now write a program which prints <code>name</code> once for each character in <code>name</code>. For example, for <code>name = 'Amy'</code>, it should output:</p>\n<pre><code>Amy\nAmy\nAmy\n</code></pre>\n<p>For <code>name = 'World'</code>, it should output:</p>\n<pre><code>World\nWorld\nWorld\nWorld\nWorld\n</code></pre>\n<p>By the way, you can set <code>name</code> to anything in the first line. Only the rest of the program after that will be checked.</p>",
          "<p>We're making really good progress! You're solving problems and writing new code!\nLet's keep making things more interesting.</p>"
        ]
      },
      {
        "slug": "BuildingUpStrings",
        "title": "Building Up Strings",
        "index": 11,
        "step_texts": [
          "<p>Before we look at some more loops, we need to quickly learn another concept. Look at this program:</p>\n<pre><code>hello = 'Hello'\nprint(hello)\nhello = hello + '!'\nprint(hello)\n</code></pre>\n<p>What do you think the line <code>hello = hello + '!'</code> does? What do you think the program will output? Make a prediction, then run it to find out.</p>",
          "<p>Python doesn't care that <code>hello</code> is on both the left and the right of the <code>=</code>, it just does what it would always do if the variables were different: it calculates <code>hello + '!'</code> which at the time is <code>'Hello' + '!'</code> which is <code>'Hello!'</code>, and that becomes the new value of <code>hello</code>. If it helps, you can think of that line as split into two steps:</p>\n<pre><code>temp = hello + '!'\nhello = temp\n</code></pre>\n<p>or:</p>\n<pre><code>temp = hello\nhello = temp + '!'\n</code></pre>\n<p>This is very useful in a loop. Think about what this program will do, then run it:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>By the way, <code>''</code> is called the <em>empty string</em> - a string containing no characters.</p>",
          "<p>The details in the above program are important. What goes wrong if you swap the last two lines and run this program instead?</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    print(line)\n    line = line + char\n</code></pre>",
          "<p>The last character in <code>name</code> only gets added to <code>line</code> at the end of the loop, after <code>print(line)</code> has already run for the last time. So that character and the full <code>name</code> never get printed at the bottom of the triangle.</p>"
        ]
      },
      {
        "slug": "BuildingUpStringsExercises",
        "title": "Building Up Strings Exercises",
        "index": 12,
        "step_texts": [
          "<p>Modify this program:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>to add a space after every character in the triangle, so the output looks like this:</p>\n<pre><code>W\nW o\nW o r\nW o r l\nW o r l d\n</code></pre>",
          "<p>Tremendous! Now modify the program so that each line is backwards, like this:</p>\n<pre><code>W\noW\nroW\nlroW\ndlroW\n</code></pre>",
          "<p>Brilliant!</p>\n<p>Code like:</p>\n<pre><code>line = line + char\n</code></pre>\n<p>is so common that Python lets you abbreviate it. This means the same thing:</p>\n<pre><code>line += char\n</code></pre>\n<p>Note that there is no abbreviation for <code>line = char + line</code>.</p>\n<p>Now use <code>+=</code> and a for loop to write your own program which prints <code>name</code> 'underlined', like this:</p>\n<pre><code>World\n-----\n</code></pre>\n<p>There should be one <code>-</code> for each character in <code>name</code>.</p>",
          "<p>Fantastic!</p>\n<p>By the way, when you don't need to use a variable, it's common convention to name that variable <code>_</code> (underscore), e.g. <code>for _ in name:</code>. This doesn't change how the program runs, but it's helpful to readers.</p>\n<p>Let's make this fancier. Extend your program to draw a box around the name, like this:</p>\n<pre><code>+-------+\n| World |\n+-------+\n</code></pre>\n<p>Note that there is a space between the name and the pipes (<code>|</code>).</p>",
          "<p>You're getting good at this! Looks like you need more of a challenge...maybe instead of putting a name in a box, the name should be the box? Write a program that outputs this:</p>\n<pre><code>+World+\nW     W\no     o\nr     r\nl     l\nd     d\n+World+\n</code></pre>",
          "<p>Sweet! You're really getting the hang of this! If you want, here's one more optional bonus challenge. Try writing a program that outputs:</p>\n<pre><code>W\n o\n  r\n   l\n    d\n</code></pre>\n<p>Or don't, it's up to you.</p>"
        ]
      },
      {
        "slug": "BasicTerminology",
        "title": "Basic Terminology",
        "index": 13,
        "step_texts": [
          "<p>Here's some words you need to know:</p>\n<p>An <strong><em>expression</em></strong> is a piece of code that has a value. For example, in this line of code:</p>\n<pre><code>sentence = 'Hello ' + name\n</code></pre>\n<p>there are three expressions:</p>\n<ol>\n<li><code>'Hello '</code></li>\n<li><code>name</code></li>\n<li><code>'Hello ' + name</code></li>\n</ol>\n<p>By contrast, the full line <code>sentence = ...</code> is a <strong><em>statement</em></strong>. It's a command that tells the computer to perform an action. It has no value of its own. This means, for example, that you can't add statements together. This code is invalid:</p>\n<pre><code>(word = 'Hello') + (name = 'Bob')\n</code></pre>\n<p>Specifically, a statement like <code>sentence = ...</code> where a variable is given a value is called <strong><em>assignment</em></strong> - the value is <em>assigned to</em> the the variable.</p>\n<p>A program is a list of statements which are executed in order. A <code>for</code> loop is a <em>compound statement</em>, meaning it has a body of its own which contains other statements. Most statements will also contain expressions, and expressions can contain other smaller expressions, but expressions cannot contain statements.</p>\n<p>The process of calculating the value of an expression is called <strong><em>evaluation</em></strong> - note how it almost contains the word 'value'. The computer <em>evaluates</em> <code>1 + 2</code> to get the value <code>3</code>.</p>\n<p>The process of executing a loop is called <strong><em>iteration</em></strong>. Code like <code>for char in 'Hello':</code> is <em>iterating over</em> the string <code>'Hello'</code>. The fact that it's possible means that strings are <em>iterable</em>. By contrast, numbers are not iterable, which is exactly what Python will tell you if you try <code>for char in 3:</code>. Each run through the loop is <em>one iteration</em>, so in this example there will be 5 iterations.</p>"
        ]
      },
      {
        "slug": "IntroducingIfStatements",
        "title": "Introducing If Statements",
        "index": 14,
        "step_texts": [
          "<p>Now we're going to learn how to tell the computer to make decisions and only run code\nunder certain conditions. For this we will need a new type of value. You've seen\nnumbers and strings, now meet <em>booleans</em>. There are only two boolean values:\n<code>True</code> and <code>False</code>. Try this program:</p>\n<pre><code>condition = True\nprint(condition)\ncondition = False\nprint(condition)\n</code></pre>",
          "<p>Booleans are meant to be used inside <em>if statements</em> (sometimes also called <em>conditionals</em>).</p>\n<p>Here is a simple example for you to run:</p>\n<pre><code>if True:\n    print('This gets printed')\n\nif False:\n    print('This does not')\n</code></pre>",
          "<p>Note how the code inside the first <code>if</code> statement ran, but not the second.</p>\n<p>In general, an <code>if</code> statement looks like this:</p>\n<pre><code>if &lt;condition&gt;:\n    &lt;body&gt;\n</code></pre>\n<p>where <code>&lt;condition&gt;</code> is any expression which evaluates to a boolean and <code>&lt;body&gt;</code> is an <strong>indented</strong> list\nof one or more statements. The structure is quite similar to a <code>for</code> loop. Note the colon (<code>:</code>) which\nis essential.</p>\n<p>When the computer sees <code>if &lt;condition&gt;:</code>, it checks if <code>&lt;condition&gt;</code> is <code>True</code>. If it is, it runs the body.\nIf not, it skips it and continues to the rest of the program.</p>\n<p>Here's a more interesting example for you to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence += '!'\nprint(sentence)\n</code></pre>",
          "<p>(Remember that <code>sentence += '!'</code> means <code>sentence = sentence + '!'</code>)</p>\n<p>Change <code>excited = True</code> to <code>excited = False</code> and run the program again to see what the difference is.</p>",
          "<p>Time for an exercise. Modify the program above to include an extra\nboolean parameter <code>confused</code>, so the program should start like this:</p>\n<pre><code>sentence = 'Hello World'\nexcited = False\nconfused = True\n</code></pre>\n<p>(<code>sentence</code> can be any string and the two booleans can be either <code>True</code> or <code>False</code>)</p>\n<p>When <code>confused</code> is true, the printed sentence should have a question mark added to the end.\nIf both <code>confused</code> and <code>excited</code> are true, the sentence should end with <code>!?</code>.</p>",
          "<p>Well done! This program can do 4 different things depending on how you combine <code>excited</code>\nand <code>confused</code>. Try them out if you want.</p>"
        ]
      },
      {
        "slug": "CombiningCompoundStatements",
        "title": "Combining Compound Statements",
        "index": 15,
        "step_texts": [
          "<p>Compound statements like <code>for</code> loops and <code>if</code> statements have bodies which are a list\nof inner statements. Those inner statements can be anything, including other compound statements.\nTry this example of a <code>for</code> loop inside an <code>if</code> statement for when you want to show\nthat you're <em>really</em> excited:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    new_sentence = ''\n    for char in sentence:\n        new_sentence += char\n        new_sentence += '!'\n    sentence = new_sentence\n\nprint(sentence)\n</code></pre>",
          "<p>Note how the body of the <code>if</code> statement (5 lines) is indented as usual, while the body\nof the <code>for</code> loop (2 lines) is indented by an additional 4 spaces in each line to show that\nthose lines are within the <code>for</code> loop. You can see the overall structure of the program\njust by looking at the indentation.</p>\n<p>Alternatively, you can put an <code>if</code> inside a <code>for</code>:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nnew_sentence = ''\nfor char in sentence:\n    new_sentence += char\n    if excited:\n        new_sentence += '!'\n\nsentence = new_sentence\nprint(sentence)\n</code></pre>\n<p>These two programs have the exact same result. However the first one is more efficient as it\nonly iterates over the string if it needs to, since when <code>excited = False</code> nothing changes.</p>"
        ]
      },
      {
        "slug": "UnderstandingProgramsWithSnoop",
        "title": "Understanding Programs With Snoop",
        "index": 16,
        "step_texts": [
          "<p>Run this program:</p>\n<pre><code>sentence = 'Hello World'\n\ninclude = False\nnew_sentence = ''\nfor char in sentence:\n    if include:\n        new_sentence += char\n    include = True\n\nprint(new_sentence)\n</code></pre>",
          "<p>As you can see, it prints everything but the first character. Take some time to understand how this works.</p>\n<p>In fact, it's time to introduce a new tool to help you understand programs. Click the 'Snoop' button to run the same program while also showing what's happening.</p>",
          "<p>Tada! Scroll to the top of the terminal and let's walk through what snoop is showing you.\nIt starts out very straightforward:</p>\n<pre><code>    1 | sentence = 'Hello World'\n    3 | include = False\n    4 | new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The first lines are simply showing you the lines of the program that the computer ran.\nOn the left is the line number as seen in the editor.</p>\n<p>Running <code>for char in sentence:</code> assigns a value to the variable <code>char</code>, so snoop shows you that value.\nLines starting with <code>......</code> indicate a new variable or a change in the value of an existing variable.\nSuch lines will not be shown when they're redundant, which is why the snoop output doesn't start like this:</p>\n<pre><code>    1 | sentence = 'Hello World'\n ...... sentence = 'Hello World'\n    3 | include = False\n ...... include = False\n    4 | new_sentence = ''\n ...... new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The next two lines are:</p>\n<pre><code>    6 |     if include:\n    8 |     include = True\n</code></pre>\n<p>What's important here is what's not showing: because <code>include</code> is <code>False</code>, line 7 (<code>new_sentence += char</code>) gets skipped. But then <code>include</code> is set to <code>True</code>, so the next iteration of the loop is different:</p>\n<pre><code>    5 | for char in sentence:\n ...... char = 'e'\n    6 |     if include:\n    7 |         new_sentence += char\n .............. new_sentence = 'e'\n</code></pre>\n<p><code>new_sentence += char</code> runs for the first time and the variable <code>new_sentence</code> gets a new value.</p>\n<p>Now modify the program to do the opposite: only print the first character, leave out the rest.</p>",
          "<p>Great job! You're working with increasingly complex programs.</p>"
        ]
      },
      {
        "slug": "IfAndElse",
        "title": "<code>if</code> and <code>else</code>",
        "index": 17,
        "step_texts": [
          "<p>An <code>if</code> statement can optionally have an <code>else</code> part. Run this example:</p>\n<pre><code>condition = True\nif condition:\n    print('Yes')\nelse:\n    print('No')\n</code></pre>",
          "<p>Now change the first line to <code>condition = False</code> and run it again.</p>",
          "<p>Think of <code>else</code> as saying 'or else' or 'otherwise'. It means that if the condition in the <code>if</code>\nis false, then the body of the <code>else</code> will run instead. Whether the condition is true or false,\nexactly one of the two bodies will run.</p>\n<p>Here's a more interesting example to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence = sentence.upper()\nelse:\n    sentence = sentence.lower()\nprint(sentence)\n</code></pre>",
          "<p><code>sentence.upper()</code> is a new kind of expression we haven't encountered yet. What's going on here is that <code>sentence</code> is a string and strings have various <em>methods</em> that let you conveniently calculate new values from them, including <code>upper</code> and <code>lower</code>. The names refer to uppercase (capital letters) and lowercase (small letters). <code>'Hello World'.upper()</code> evaluates to <code>'HELLO WORLD'</code>. It doesn't change the contents of <code>sentence</code> though, so you have to assign the new value again with <code>sentence = sentence.upper()</code>.</p>\n<p>Now change <code>excited</code> to <code>False</code> and run it again.</p>",
          "<p>Here's a broken program:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    char = '!'\nsentence += char\n\nprint(sentence)\n</code></pre>\n<p>Can you see the problem? If you run it, everything seems fine. What could go wrong?</p>\n<p>Spoilers below! Have you figured it out?</p>\n<p>What happens if you change <code>excited</code> to <code>False</code>?</p>",
          "<p>If <code>excited</code> is true then <code>char</code> is defined and everything runs fine. But otherwise\n<code>char</code> never gets assigned a value, so trying to use it in <code>sentence += char</code> fails.</p>\n<p>Fix this by adding an <code>else</code> clause to the <code>if</code> so that if <code>excited</code> is false, a full stop (<code>.</code>)\nis added to the end of the sentence instead of an exclamation mark (<code>!</code>).</p>",
          "<p>Time for a challenge!</p>\n<p>Write a program which, given a string <code>sentence</code>, prints a modified version with\nthe same letters, where the first letter is capitalised and the rest are lowercase.\nFor example, the output should be <code>Hello world</code> whether the input <code>sentence = 'hello world'</code>\nor <code>'HELLO WORLD'</code>.</p>",
          "<p>Excellent!!!</p>\n<p>One more exercise, and then you can relax. </p>\n<p>Write a program which prints <code>sentence</code> mockingly, e.g:</p>\n<pre><code>OnE MoRe eXeRcIsE, aNd tHeN YoU CaN ReLaX.\n</code></pre>\n<p>Every second character should be lowercased, the rest should be uppercase.</p>",
          "<p>Perfect! Take a moment to be proud of what you've achieved. Can you feel your brain growing?</p>"
        ]
      },
      {
        "slug": "TheEqualityOperator",
        "title": "The Equality Operator",
        "index": 18,
        "step_texts": [
          "<p>There are several ways to obtain booleans without assigning them directly,\nwhich allows you to construct very useful <code>if</code> statements. In particular there\nare many <em>comparison operators</em> which compare the values of two expressions.\nThe most common is the equality operator which checks if two values are equal.\nIt's denoted by two equals signs: <code>==</code>. Try running this:</p>\n<pre><code>print(1 + 2 == 3)\nprint(4 + 5 == 6)\nprint('ab' + 'c' == 'a' + 'bc')\n</code></pre>",
          "<p>As you can see, if the values are equal, the equality expression evaluates to <code>True</code>,\notherwise it's <code>False</code>.</p>\n<p>Note the difference between the equality operator <code>==</code> and a single <code>=</code> which has different meanings,\nparticularly in assignment statements as you've seen them so far. What happens if you try\nremoving a single <code>=</code> from the previous program?</p>",
          "<p>Let's use <code>==</code> in an <code>if</code> statement. In this program, the <code>if</code> body runs only when <code>c</code> is the character <code>'s'</code>. See for yourself.</p>\n<pre><code>name = 'kesha'\nnew_name = ''\nfor c in name:\n    if c == 's':\n        c = '$'\n    new_name += c\n\nprint(new_name)\n</code></pre>",
          "<p>Now extend the program to also replace <code>e</code> with <code>3</code> and <code>a</code> with <code>@</code>.</p>",
          "<p>Well done!</p>"
        ]
      },
      {
        "slug": "IntroducingElif",
        "title": "Introducing <code>elif</code>",
        "index": 19,
        "step_texts": [
          "<p>Quick biology lesson! Most of the cells in your body contain your full genetic code in DNA.\nThis consists of strands of molecular units called nucleobases which come in four varieties:\nAdenine, Cytosine, Guanine, and Thymine, or ACGT for short.\nSo part of a single strand might be something like:</p>\n<pre><code>AGTAGCGTCCTTAGTTACAGGATGGCTTAT...\n</code></pre>\n<p>This will be paired with another strand where A is replaced by T and vice versa,\nand C is replaced by G and vice versa, e.g:</p>\n<pre><code>TCATCGCAGGAATCAATGTCCTACCGAATA...\n</code></pre>\n<p>The two strands are 'zipped' together into the famous double helix structure,\njoined by the matching A-T and C-G pairs. These pairings are essential in copying DNA when\ncells divide and reproduce. The double helix is unzipped and the code is transcribed\ninto its opposite version to make the copy.</p>\n<p>We're going to repeat that process. Let's try the same kind of program we just wrote:</p>\n<pre><code>dna = 'AGTAGCGTC'\nopposite_dna = ''\nfor char in dna:\n    if char == 'A':\n        char = 'T'\n    if char == 'T':\n        char = 'A'\n    if char == 'G':\n        char = 'C'\n    if char == 'C':\n        char = 'G'\n    opposite_dna += char\n\nprint(opposite_dna)\n</code></pre>",
          "<p>Oh dear, that doesn't quite work. <code>T</code> is changed to <code>A</code> but <code>A</code> isn't changed to anything.\nCan you see why?</p>\n<p>When <code>char == 'A'</code>, then the body <code>char = 'T'</code> does indeed run. But that means that the following\ncondition <code>char == 'T'</code> also passes and so <code>char = 'A'</code> and we're back where we started.\nWe need to only change <code>char</code> from <code>T</code> to <code>A</code> if <code>char</code> wasn't already <code>A</code> to begin with,\nmeaning <code>char == 'A'</code> was <code>False</code>. We can do that with an <code>else</code>, like so:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelse:\n    if char == 'T':\n        char = 'A'\n</code></pre>\n<p>Now fix the program to replace all characters correctly.</p>",
          "<p>Brilliant! You have mimicked what your own cells are constantly doing.</p>\n<p>An <code>if</code> inside an <code>else</code> can be replaced by a single keyword <code>elif</code>. For example,\nthe previous code can be changed to this:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelif char == 'T':\n    char = 'A'\nelif char == 'G':\n    char = 'C'\nelif char == 'C':\n    char = 'G'\n</code></pre>",
          "<p>It's common to have a chain of <code>elif</code> clauses when you want exactly one of many\nbodies to run, like in this case. In general, code like this:</p>\n<pre><code>if X:\n    ...\nelse:\n    if Y:\n        ...\n    else:\n        if Z:\n            ...\n        else:\n            ...\n</code></pre>\n<p>can be rewritten as:</p>\n<pre><code>if X:\n    ...\nelif Y:\n    ...\nelif Z:\n    ...\nelse:\n    ...\n</code></pre>\n<p>which is both shorter and saves you from unpleasant nested indentation.\nThe difference is only cosmetic: once the computer runs this code, it can't\ntell the difference between the two versions.</p>\n<p>Note that <code>elif</code>(s) can optionally be followed by one final <code>else</code>. We didn't include one\nin our DNA example, but we could add one to alert us to any unexpected characters\nin the input, or change <code>elif char == 'C':</code> to <code>else:</code> if we were confident\nabout the input being valid.</p>"
        ]
      },
      {
        "slug": "OtherComparisonOperators",
        "title": "Other Comparison Operators",
        "index": 20,
        "step_texts": [
          "<p>The opposite of the equals operator <code>==</code> is the <em>not equals</em> operator <code>!=</code>. If you squint it sort of looks like \u2260. It evaluates to <code>True</code> when two values are...not equal. Try it for yourself in the shell.</p>",
          "<p>Here's a cute little program using <code>!=</code>:</p>\n<pre><code>sentence = \"The e key on my keyboard is broken\"\nnew_sentence = ''\nfor c in sentence:\n    if c != 'e':\n        new_sentence += c\nprint(new_sentence)\n</code></pre>",
          "<p>Other handy operators are <code>&lt;</code> (less than) and <code>&gt;</code> (greater than). For example, <code>a &lt; b</code> means \"<code>a</code> is less than <code>b</code>\". Try using one of these in the shell to compare two numbers.</p>",
          "<p>You can also use these operators to compare strings. If you arrange two strings in alphabetical order, the first one is 'less than' the second. See for yourself.</p>",
          "<p>Here's a practical example of <code>&lt;</code> in action for you to try:</p>\n<pre><code>percentage = 73\n\nif percentage &lt; 20:\n    grade = \"F\"\nelif percentage &lt; 40:\n    grade = \"D\"\nelif percentage &lt; 60:\n    grade = \"C\"\nelif percentage &lt; 80:\n    grade = \"B\"\nelse:\n    grade = \"A\"\n\nprint(grade)\n</code></pre>\n<p>Recall that <code>elif percentage &lt; 40</code> after <code>if percentage &lt; 20</code> means \"if the percentage wasn't less than 20 and also is less than 40\", so it will pass for all numbers from 20 to 39 inclusive. Similarly a 'C' is for percentages from 40 to 59, and an 'A' is for any number 80 and up.</p>",
          "<p>Now for an exercise: write a program that takes three variables <code>x1</code>, <code>x2</code>, and <code>x3</code>, and prints the value of the smallest one. So for:</p>\n<pre><code>x1 = 'Charlie'\nx2 = 'Alice'\nx3 = 'Bob'\n</code></pre>\n<p>it should print <code>Alice</code>.</p>",
          "<p>Marvelous!</p>\n<p>There are many ways this could be solved. Here's one solution:</p>\n<pre><code>if x1 &lt; x2:\n    if x1 &lt; x3:\n        first = x1\n    else:\n        first = x3\nelse:\n    if x2 &lt; x3:\n        first = x2\n    else:\n        first = x3\n\nprint(first)\n</code></pre>\n<p>Here's another:</p>\n<pre><code>first = x1\n\nif x2 &lt; first:\n    first = x2\n\nif x3 &lt; first:\n    first = x3\n\nprint(first)\n</code></pre>\n<p>These programs (and yours too) all work equally well with numbers and strings,\nbut not a mixture.</p>\n<p><code>&lt;</code> and <code>&gt;</code> evaluate to False if the compared values are equal. For example,\n3 is not less than 3, so <code>3 &lt; 3</code> and <code>3 &gt; 3</code> are both False.\nTo allow equal values, use <code>&lt;=</code> and <code>&gt;=</code>.\nAgain, if you squint, they look a bit like \u2264 and \u2265.\nNote that the <code>=</code> comes second - there are no such operators as <code>=&lt;</code> or <code>=&gt;</code>.\nTo remember this, read them out loud as \"less than or equal to\"\nand \"greater than or equal to\".</p>\n<p>In summary, the main comparison operators are <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, and <code>&gt;=</code>.\nIf you ever have doubts about what they do, play with them in the shell!</p>"
        ]
      },
      {
        "slug": "IntroducingLists",
        "title": "Introducing Lists",
        "index": 21,
        "step_texts": [
          "<p>It's time to learn about a powerful new type of value called lists. Here's an example:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor word in words:\n    print(word)\n</code></pre>",
          "<p>A list is a <em>sequence</em> (an ordered collection/container) of any number of values.\nThe values are often referred to as <em>elements</em>.\nThey can be anything: numbers, strings, booleans, even lists! They can also be a mixture of types.</p>\n<p>To create a list directly, like above:</p>\n<ol>\n<li>Write some square brackets: <code>[]</code></li>\n<li>If you don't want an empty list, write some expressions inside to be the elements.</li>\n<li>Put commas (<code>,</code>) between elements to separate them.</li>\n</ol>\n<p>Here's another example of making a list:</p>\n<pre><code>x = 1\nthings = ['Hello', x, x + 3]\nprint(things)\n</code></pre>",
          "<p>As you saw above, lists are <em>iterable</em>, meaning you can iterate over them with a <code>for loop</code>.\nHere's a program that adds up all the numbers in a list:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9]\n\ntotal = 0\nfor number in numbers:\n    total += number\n\nprint(total)\n</code></pre>",
          "<p>Now modify the program so that it can add up a list of strings instead of numbers.\nFor example, given:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n</code></pre>\n<p>it should print:</p>\n<pre><code>Thisisalist\n</code></pre>",
          "<p>Optional bonus challenge: extend the program to insert a separator string <em>between</em> each word.\nFor example, given</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\nseparator = ' - '\n</code></pre>\n<p>it would output:</p>\n<pre><code>This - is - a - list\n</code></pre>\n<p>Lists and strings have a lot in common.\nFor example, you can add two lists to combine them together into a new list.\nYou can also create an empty list that has no elements.\nCheck for yourself:</p>\n<pre><code>numbers = [1, 2] + [3, 4]\nprint(numbers)\nnew_numbers = []\nnew_numbers += numbers\nnew_numbers += [5]\nprint(new_numbers)\n</code></pre>\n<p>With that knowledge, write a program which takes a list of numbers\nand prints a list where each number has been doubled. For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[6, 2, 8, 2, 10, 18, 4, 12, 10]\n</code></pre>",
          "<p>Great!</p>\n<p>When you want to add a single element to the end of a list, instead of:</p>\n<pre><code>some_list += [element]\n</code></pre>\n<p>it's actually more common to write:</p>\n<pre><code>some_list.append(element)\n</code></pre>\n<p>There isn't really a big difference between these, but <code>.append</code>\nwill be more familiar and readable to most people.</p>\n<p>Now use <code>.append</code> to write a program which prints a list containing only the numbers bigger than 5.</p>\n<p>For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[9, 6]\n</code></pre>",
          "<p>Fantastic! We're making great progress.</p>"
        ]
      },
      {
        "slug": "UsingBreak",
        "title": "Using <code>break</code> to end a loop early",
        "index": 22,
        "step_texts": [
          "<p>Exercise: write a program which takes a list and a value and checks\nif the list contains the value. For example, given:</p>\n<pre><code>things = ['This', 'is', 'a', 'list']\nthing_to_find = 'is'\n</code></pre>\n<p>it should print <code>True</code>, but for</p>\n<pre><code>thing_to_find = 'other'\n</code></pre>\n<p>it should print <code>False</code>.</p>",
          "<p>Nice!</p>\n<p>A typical solution looks something like this:</p>\n<pre><code>found = False\nfor thing in things:\n    if thing == thing_to_find:\n        found = True\n\nprint(found)\n</code></pre>\n<p>Your solution is probably similar. It's fine, but it's a bit inefficient.\nThat's because it'll loop over the entire list even if it finds the element at the beginning.\nYou can stop any loop using a <code>break</code> statement, like so:</p>\n<pre><code>for thing in things:\n    if thing == thing_to_find:\n        found = True\n        break\n</code></pre>\n<p>This is just as correct but skips unnecessary iterations and checks once it finds the element.\nYou can use snoop to see the difference.</p>"
        ]
      },
      {
        "slug": "GettingElementsAtPosition",
        "title": "Getting Elements at a Position",
        "index": 23,
        "step_texts": [
          "<p>Looping is great, but often you just want to retrieve a single element from the list at a known position.\nHere's how:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nprint(words[0])\nprint(words[1])\nprint(words[2])\nprint(words[3])\n</code></pre>",
          "<p>In general, you can get the element at the position <code>i</code> with <code>words[i]</code>. The operation is called <em>subscripting</em> or <em>indexing</em>, and the position is called the <em>index</em>.</p>\n<p>You've probably noticed that the first index is 0, not 1. In programming, counting starts at 0. It seems weird, but that's how most programming languages do it, and it's generally agreed to be better.</p>\n<p>This also means that the last index in this list of 4 elements is 3. What happens if you try getting an index greater than that?</p>",
          "<p>There you go. <code>words[4]</code> and beyond don't exist, so trying that will give you an error.</p>\n<p>By the way, you can get the number of elements in a list (commonly called the <em>length</em>) using <code>len(words)</code>.\nThat means that the last valid index of the list is <code>len(words) - 1</code>, so the last element is <code>words[len(words) - 1]</code>. Try these for yourself.</p>\n<p>So in general, the valid indices are:</p>\n<pre><code>[0, 1, 2, ..., len(words) - 2, len(words) - 1]\n</code></pre>\n<p>There's a handy built in function to give you these values, called <code>range</code>:</p>\n<pre><code>for i in range(10):\n    print(i)\n</code></pre>",
          "<p><code>range(n)</code> is similar to the list <code>[0, 1, 2, ..., n - 2, n - 1]</code>.\nThis gives us an alternative way to loop over a list:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor index in range(len(words)):\n    print(index)\n    print(words[index])\n</code></pre>",
          "<p>Let's get some exercise! Given a list <code>things</code> and a value <code>to_find</code>,\nprint the first index of <code>to_find</code> in the list, i.e. the lowest number <code>i</code> such that\n<code>things[i]</code> is <code>to_find</code>. For example, for</p>\n<pre><code>things = ['on', 'the', 'way', 'to', 'the', 'store']\nto_find = 'the'\n</code></pre>\n<p>your program should print <code>1</code>.</p>\n<p>You can assume that <code>to_find</code> appears at least once.</p>",
          "<p>Nice!</p>\n<p>By the way, indexing and <code>len()</code> also work on strings. Try them out in the shell.</p>\n<p>Here's another exercise. Given two strings of equal length, e.g:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"World\"\n</code></pre>\n<p>print them vertically side by side, with a space between each character:</p>\n<pre><code>H W\ne o\nl r\nl l\no d\n</code></pre>",
          "<p>Incredible!</p>\n<p>Your solution probably looks something like this:</p>\n<pre><code>for i in range(len(string1)):\n    char1 = string1[i]\n    char2 = string2[i]\n    print(char1 + ' ' + char2)\n</code></pre>\n<p>This doesn't work so well if the strings have different lengths.\nIn fact, it goes wrong in different ways depending on whether <code>string1</code> or <code>string2</code> is longer.\nYour next challenge is to fix this problem by filling in 'missing' characters with spaces.</p>\n<p>For example, for:</p>\n<pre><code>string1 = \"Goodbye\"\nstring2 = \"World\"\n</code></pre>\n<p>output:</p>\n<pre><code>G W\no o\no r\nd l\nb d\ny  \ne\n</code></pre>\n<p>and for:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"Elizabeth\"\n</code></pre>\n<p>output:</p>\n<pre><code>H E\ne l\nl i\nl z\no a\n  b\n  e\n  t\n  h\n</code></pre>",
          "<p>Magnificent! Take a break, you've earned it!</p>"
        ]
      },
      {
        "slug": "CallingFunctionsTerminology",
        "title": "Terminology: Calling functions and methods",
        "index": 24,
        "step_texts": [
          "<p>It's time to expand your vocabulary some more.</p>\n<p><code>print</code> and <code>len</code> are <strong><em>functions</em></strong>. See for yourself:</p>\n<pre><code>print(len)\nprint(print)\n</code></pre>",
          "<p>An expression like <code>len(things)</code> or <code>print(things)</code> is a function <strong><em>call</em></strong> - when you write that, you are <strong><em>calling</em></strong> the function <code>len</code> or <code>print</code>. The fact that this is possible means that functions are <strong><em>callable</em></strong>:</p>\n<pre><code>print(callable(len))\n</code></pre>",
          "<p>Most things are not callable, so trying to call them will give you an error:</p>\n<pre><code>f = 'a string'\nprint(callable(f))\nf()\n</code></pre>",
          "<p>In the call <code>len(things)</code>, <code>things</code> is an <strong><em>argument</em></strong>. Sometimes you will also see the word <strong><em>parameter</em></strong>, which means basically the same thing as argument. It's a bit like you're giving the argument to the function - specifically we say that the argument <code>things</code> is <em>passed</em> to <code>len</code>, and <code>len</code> <em>accepts</em> or <em>receives</em> the argument.</p>\n<p><code>len(things)</code> will evaluate to a number such as 3, in which case we say that <code>len</code> <strong><em>returned</em></strong> 3.</p>\n<p>All calls have to return something...even if it's nothing. For example, <code>print</code>'s job is to display something on screen, not to return a useful value. So it returns something useless instead:</p>\n<pre><code>things = [1, 2, 3]\nlength = len(things)\nprinted = print(length)\nprint(printed)\n</code></pre>",
          "<p><code>None</code> is a special 'null' value which can't do anything interesting. It's a common placeholder that represents the lack of a real useful value. Functions that don't want to return anything return <code>None</code> by default. If you see an error message about <code>None</code> or <code>NoneType</code>, it often means you assigned the wrong thing to a variable:</p>\n<pre><code>things = print([1, 2, 3])\nlength = len(things)\n</code></pre>",
          "<p>A <strong><em>method</em></strong> is a function which belongs to a type, and can be called on all values of that type using <code>.</code>. For example, <code>upper</code> and <code>lower</code> are methods of strings, which are called with e.g. <code>word.upper()</code>:</p>\n<pre><code>word = 'Hello'\nprint(word.upper)\nprint(word.upper())\n</code></pre>",
          "<p>Another example is that <code>append</code> is a method of lists. But you can't use <code>.upper</code> on a list or <code>.append</code> on a string:</p>\n<pre><code>word = 'Hello'\nword.append('!')\n</code></pre>",
          "<p>The word 'attribute' in the error message refers to the use of <code>.</code> - the error actually comes just from <code>word.append</code>, without even a call.</p>"
        ]
      },
      {
        "slug": "FunctionsAndMethodsForLists",
        "title": "Functions And Methods For Lists",
        "index": 25,
        "step_texts": [
          "<p>Let's review how to work with lists. Suppose we have a list <code>nums = [1, 2, 3]</code>. You can use:</p>\n<ul>\n<li><strong><code>append</code></strong>: Add an element to the end of the list. <code>nums.append(4)</code> changes the list to <code>[1, 2, 3, 4]</code>.</li>\n<li><strong><code>len</code></strong>: Returns the number of elements. <code>len(nums)</code> is <code>3</code>.</li>\n<li><strong><code>range</code></strong>: <code>range(n)</code> is an object similar to the list of numbers from 0 to <code>n - 1</code>. In particular, <code>range(len(nums))</code> is like <code>[0, 1, 2]</code>.</li>\n<li><strong><code>subscripting</code></strong>: Get a value at an index. <code>nums[0]</code> is 1, <code>nums[1]</code> is 2, <code>nums[2]</code> is 3.</li>\n<li><strong><code>+</code></strong>: Concatenates lists. <code>nums + [4, 5]</code> is <code>[1, 2, 3, 4, 5]</code>.</li>\n</ul>\n<p>Here's some new things. Try them out in the shell.</p>\n<ul>\n<li><strong><code>subscript assignment</code></strong>: Set a value at an index. <code>nums[0] = 9</code> changes the list to <code>[9, 2, 3]</code>.</li>\n<li><strong><code>join</code></strong>: Add a list of strings with a separator in between. This is a method of strings (the separator) which takes an iterable of strings as an argument. <code>'--'.join(['apples', 'oranges', 'bananas'])</code> returns <code>'apples--oranges--bananas'</code>. You can also use an empty string if you don't want a separator, e.g. <code>''.join(['apples', 'oranges', 'bananas'])</code> returns <code>'applesorangesbananas'</code>. </li>\n<li><strong><code>sum</code></strong>: Add a list of numbers. <code>sum(nums)</code> is 6.</li>\n<li><strong><code>in</code></strong>: A comparison operator that checks if a value is in a list. <code>2 in nums</code> is <code>True</code>, but <code>4 in nums</code> is <code>False</code>.</li>\n<li><strong><code>index</code></strong>: Returns the first index of a value in a list. <code>[7, 8, 9, 8].index(8)</code> is 1. Raises an error if the value isn't there.</li>\n</ul>\n<p>You may recognise some of these from your exercises. I assure you that those exercises were not pointless, as you've now learned valuable fundamental skills. For example, you can use <code>in</code> to check if a list contains 5, but there's no similarly easy way to check for a number bigger than 5.</p>\n<p>It's useful to know these functions, but it's not easy to learn them all, and there's many more. A more important skill is being able to look things up. For example, here are some typical ways you might Google the above functions if you forgot their names:</p>\n<ul>\n<li><code>append</code><ul>\n<li>python add element to list</li>\n<li>python add item at end of list</li>\n</ul>\n</li>\n<li><code>len</code><ul>\n<li>python size of list</li>\n<li>python number of elements in list</li>\n<li>python how many characters in string</li>\n</ul>\n</li>\n<li><code>join</code><ul>\n<li>python combine list of strings with separator</li>\n<li>python add together list of strings with string in between</li>\n</ul>\n</li>\n<li><code>sum</code><ul>\n<li>python add list of numbers</li>\n<li>python total of numbers</li>\n</ul>\n</li>\n<li><code>in</code><ul>\n<li>python check if list contains value</li>\n<li>python test if list has element</li>\n</ul>\n</li>\n<li><code>index</code><ul>\n<li>python get position of element</li>\n<li>python get index of value</li>\n</ul>\n</li>\n</ul>\n<p>Let's practice this skill now. Find a function/method that returns the value in a list which is bigger than any other value. For example, given the list <code>[21, 55, 4, 91, 62, 49]</code>, it will return <code>91</code>. You should write the answer in the shell as a single small expression. For example, if you were looking for the function <code>sum</code>, you could write <code>sum([21, 55, 4, 91, 62, 49])</code>. Don't solve this manually with a loop.</p>",
          "<p>Good find! Let's do one more. Consider this program:</p>\n<pre><code>nums = [1, 2, 3, 4, 5]\nnums.append(9)\nprint(nums)\n</code></pre>\n<p>This changes <code>nums</code> so that it prints:</p>\n<pre><code>[1, 2, 3, 4, 5, 9]\n</code></pre>\n<p>But suppose you don't want the 9 to be at the end, you want it to go between the second and third elements, so the output is:</p>\n<pre><code>[1, 2, 9, 3, 4, 5]\n</code></pre>\n<p>Replace the middle line (i.e. the call to <code>append</code>) with the right function/method call to do that.</p>",
          "<p>Perfect!</p>\n<p>It can also be useful to Google things like \"python list tutorial\", e.g. if:</p>\n<ul>\n<li>Googling a specific method has failed so you want to find it manually.</li>\n<li>You're still confused about lists after this course.</li>\n<li>It's been a while since you learned about lists and you need a reminder.</li>\n<li>You're struggling to solve a problem with lists and you need to go back to basics and strengthen your foundations.</li>\n</ul>\n<p>There are also ways to find information without any googling. Try <code>dir([])</code> in the shell.</p>",
          "<p><code>dir()</code> returns a list of the argument's attributes, which are mostly methods. Many will start with <code>__</code> which you can ignore for now - scroll to the end of the list and you'll see some familiar methods.</p>\n<p>Here are a few more useful functions/methods. Suppose <code>nums = [28, 99, 10, 81, 59, 64]</code></p>\n<ul>\n<li><strong><code>sorted</code></strong>: Takes an iterable and returns a list of the elements in order. <code>sorted(nums)</code> returns <code>[10, 28, 59, 64, 81, 99]</code>.</li>\n<li><strong><code>pop</code></strong>: Removes and returns an element at a given index. <code>nums.pop(3)</code> removes <code>nums[3]</code> (<code>81</code>) from the list and returns it. Without an argument, i.e. just <code>nums.pop()</code>, it will remove and return the last element.</li>\n<li><strong><code>remove</code></strong>: Removes the first occurrence of the given element. <code>nums.remove(10)</code> will leave <code>nums</code> as <code>[28, 99, 81, 59, 64]</code>. Raises an error if the value doesn't exist. Equivalent to <code>nums.pop(nums.index(10))</code>.</li>\n<li><strong><code>count</code></strong>: Returns the number of times the argument appears in the list. <code>[1, 2, 3, 2, 7, 2, 5].count(2)</code> is 3.</li>\n</ul>\n<p>You've already seen that <code>len</code> and subscripting work with strings, a bit as if strings are lists of characters. Strings also support some of the new methods we've learned, not just for characters but for any substring. For example:</p>\n<ul>\n<li><code>'the' in 'feed the dog and the cat'</code> is <code>True</code></li>\n<li><code>'feed the dog and the cat'.count('the')</code> is 2</li>\n<li><code>'feed the dog and the cat'.index('the')</code> is 5</li>\n</ul>\n<p>Note that in most cases, methods which modify a list in place (<code>append</code>, <code>insert</code>, <code>remove</code>) merely return <code>None</code>, while the remaining functions/methods return a new useful value without changing the original argument. The only exception is the <code>pop</code> method.</p>\n<p>Modifying a value directly is called <em>mutation</em> - types of values which can be mutated are <em>mutable</em>, while those that can't are <em>immutable</em>. Strings are immutable - they don't have any methods like <code>append</code> or even subscript assignment. You simply can't change a string - you can only create new strings and use those instead. That means that this is a useless statement on its own:</p>\n<pre><code>word.upper()\n</code></pre>\n<p>The string referred to by <code>word</code> isn't modified, instead <code>word.upper()</code> returned a new string which was immediately discarded. If you want to change the value that <code>word</code> refers to, you have to assign a new value to the variable:</p>\n<pre><code>word = word.upper()\n</code></pre>\n<p>Or you can use <code>word.upper()</code> immediately in a larger expression, e.g.</p>\n<pre><code>if word.lower() == 'yes':\n</code></pre>"
        ]
      },
      {
        "slug": "UnderstandingProgramsWithPythonTutor",
        "title": "Understanding Programs With Python Tutor",
        "index": 26,
        "step_texts": [
          "<p>It's time to learn about another tool to explore programs.\nCopy the code below into the editor and then click the new \"Python Tutor\" button.\nThe button opens a new tab with a visualisation from <a href=\"http://pythontutor.com\">pythontutor.com</a>.\nThere you can navigate through the program step by step with the \"Prev\" or \"Next\" buttons, or drag\nthe slider left or right. You can also see the values of variables on the right.</p>\n<pre><code>all_numbers = [2, 4, 8, 1, 9, 7]\n\nsmall_numbers = []\nbig_numbers = []\n\nfor number in all_numbers:\n    if number &lt;= 5:\n        small_numbers.append(number)\n    else:\n        big_numbers.append(number)\n\nprint(small_numbers)\nprint(big_numbers)\n</code></pre>",
          "<p>Note that the code runs twice separately: once here, once on pythontutor.com.\nDepending on your program, the two runs may produce different results.</p>"
        ]
      },
      {
        "slug": "EqualsVsIs",
        "title": "<code>==</code> vs <code>is</code>",
        "index": 27,
        "step_texts": [
          "<p>It's time to learn some technical details that are often misunderstood and lead to errors.\nRun this program:</p>\n<pre><code>list1 = [1, 2, 3]\nlist2 = [1, 2, 3]\n\nprint(list1)\nprint(list2)\nprint(list1 == list2)\n\nprint(list1 is list2)\n\nlist1.append(4)\n\nprint(list1)\nprint(list2)\n</code></pre>",
          "<p>This program is quite straightforward and mostly consists of things you're familiar with.\nWe create two variables which refer to lists.\nThe lists have the same elements, so they are equal: <code>list1 == list2</code> is <code>True</code>.</p>\n<p>But then there's a new comparison operator: <code>is</code>. Here <code>list1 is list2</code> is <code>False</code>.\nThat means that regardless of the two lists being equal,\nthey are still two separate, distinct, individual lists.\nAs a result, when you append 4 to <code>list1</code>, only <code>list1</code> changes.</p>\n<p>Now change <code>list2 = [1, 2, 3]</code> to <code>list2 = list1</code> and see what difference it makes.</p>",
          "<p>Now <code>list1 is list2</code> is <code>True</code>, because <em>there is only one list</em>, and the two variables\n<code>list1</code> and <code>list2</code> both refer to that same list. <code>list1.append(4)</code> appends to the one list\nand the result can be seen in both <code>print(list1)</code> and <code>print(list2)</code> because both lines\nare now just different ways of printing the same list.</p>\n<p>I recommend running both versions with Python Tutor to see how it visualises the difference.\nIn the second case, the two variables both have arrows pointing to a single list object.</p>\n<p><code>list2 = list1</code> doesn't create an eternal link between the variables. If you assign a new value\nto <em>either</em> of the variables, e.g. <code>list1 = [7, 8, 9]</code>, the other variable will be unaffected\nand will still point to the original list.</p>\n<p>Basically, an assignment like:</p>\n<pre><code>list2 = &lt;expression&gt;\n</code></pre>\n<p>means 'make the variable <code>list2</code> refer to whatever <code>&lt;expression&gt;</code> evaluates to'.\nIt doesn't make a copy of that value, which is how both variables can end up pointing to the same list.\nBut as we've learned before, <code>list2</code> doesn't remember <code>&lt;expression&gt;</code>, only the value.\nIt doesn't know about other variables.</p>\n<p>You can copy a list with the <code>copy</code> method:</p>\n<pre><code>list2 = list1.copy()\n</code></pre>\n<p>This will make the program behave like the first version again.</p>\n<p>If you come across this kind of problem and you're still having trouble understanding this stuff, read the essay <a href=\"https://nedbatchelder.com/text/names.html\">Facts and myths about Python names and values</a>.</p>"
        ]
      },
      {
        "slug": "ModifyingWhileIterating",
        "title": "Modifying While Iterating",
        "index": 28,
        "step_texts": [
          "<p>Consider this program. It loops through a numbers and removes the ones smaller than 10. Or at least, it tries to. I recommend running it with Python Tutor.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor i in range(len(numbers)):\n    number = numbers[i]\n    if number &lt;= 10:\n        numbers.pop(i)\nprint(numbers)\n</code></pre>\n<p>(remember that <code>numbers.pop(i)</code> removes the element from <code>numbers</code> at index <code>i</code>)</p>\n<p>As it runs, it clearly skips even looking at 7 or 3 and doesn't remove them, and at the end it fails when it tries to access an index that's too high. Can you see why this happens?</p>\n<p>The index variable <code>i</code> runs through the usual values 0, 1, 2, ... as it's supposed to, but as the list changes those are no longer the positions we want. For example in the first iteration <code>i</code> is 0 and <code>number</code> is 10, which gets removed. This shifts the rest of the numbers left one position, so now 7 is in position 0. But then in the next iteration <code>i</code> is 1, and <code>numbers[i]</code> is 8. 7 got skipped. </p>\n<p>We could try writing the program to use <code>remove</code> instead of <code>pop</code> so we don't have to use indices. It even looks nicer this way.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor number in numbers:\n    if number &lt;= 10:\n        numbers.remove(number)\nprint(numbers)\n</code></pre>\n<p>But it turns out this does the same thing, for the same reason. Iterating over a list still goes through the indices under the hood.</p>\n<p>The lesson here is to <strong><em>never modify something while you iterate over it</em></strong>. Keep mutation and looping separate.</p>\n<p>The good news is that there are many ways to solve this. You can instead just loop over a copy, as in:</p>\n<pre><code>for number in numbers.copy():\n</code></pre>\n<p>Now the list being modified and the list being itererated over are separate objects, even if they start out with equal contents.</p>\n<p>Similarly, you could loop over the original and modify a copy:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = numbers.copy()\n\nfor number in numbers:\n    if number &lt;= 10:\n        big_numbers.remove(number)\nprint(big_numbers)\n</code></pre>\n<p>Or you could build up a new list from scratch. In this case, we've already done a similar thing in an exercise:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = []\n\nfor number in numbers:\n    if number &gt; 10:\n        big_numbers.append(number)\nprint(big_numbers)\n</code></pre>"
        ]
      },
      {
        "slug": "IntroducingNestedLoops",
        "title": "Introducing Nested Loops",
        "index": 29,
        "step_texts": [
          "<p>You've seen that the indented body of an <code>if</code> or a loop can contain any kind of statement, including more <code>if</code> statements and loops. In particular a loop can contain another loop. Here's an example:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(number)\n</code></pre>",
          "<p>This is called a <em>nested loop</em>. Nothing about it is really new, it's just worth understanding properly because it can be very useful for writing interesting programs.</p>\n<p>Let's add a line to separate sections of the output:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(number)\n    print('---')\n</code></pre>",
          "<p>Make sure you fully grasp what's going on. <code>print(letter)</code> and <code>print('---')</code> each run 3 times, because their indentation puts them in the <em>outer loop</em>. <code>print(number)</code> is called 3 \u00d7 4 = 12 times, because it's in the <em>inner loop</em> <code>for number in range(4):</code> which has 4 iterations but is itself in the outer loop so it runs 3 times.</p>\n<p>One more tweak:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(letter, number)\n    print('---')\n</code></pre>",
          "<p><code>print(letter, number)</code> gives <code>print</code> two arguments. <code>print</code> can take any number of arguments, and it will output them all on the same line, with spaces in between. If you try using <code>print(letter + ' ' + number)</code> instead you'll get an error, because you can't add strings and numbers. We'll come back to that later.</p>\n<p>Let's put this to use! Suppose you're a teacher and you need to print out all the multiplication tables from 1 to 12 for your students. You don't want to write them manually, but you can write a program to do it for you! Your program output should look like this including the lines of dashes:</p>\n<pre><code>1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n(you get the idea...)\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n</code></pre>",
          "<p>Perfect!</p>\n<p>Next exercise: you're organising a tournament for a game, such as chess or tennis. You have a list of player names:</p>\n<pre><code>players = [\"Alice\", \"Bob\", \"Charlie\"]\n</code></pre>\n<p>Every player is going to play against every other player twice: once where they get the advantage (e.g. by moving or serving first) and once not. Print out all the match combinations like this:</p>\n<pre><code>Alice vs Bob\nAlice vs Charlie\nBob vs Alice\nBob vs Charlie\nCharlie vs Alice\nCharlie vs Bob\n</code></pre>\n<p>Note that \"Alice vs Bob\" and \"Bob vs Alice\" are both in the list, but there's no \"Alice vs Alice\" - we don't want anyone playing with themselves.</p>",
          "<p>Well done! If you'd like a bonus challenge, remove the repetition and only output each pair of players once, e.g:</p>\n<pre><code>Alice vs Bob\nAlice vs Charlie\nBob vs Charlie\n</code></pre>\n<p>For your next exercise, you need to crack a password. You know that it's exactly four letters long and that only a few letters are possible, which you've written down:</p>\n<pre><code>letters = \"ABCD\"\n</code></pre>\n<p>You need to print out all possible passwords:</p>\n<pre><code>AAAA\nAAAB\nAAAC\nAAAD\nAABA\nAABB\n...skipping a few...\nDDDA\nDDDB\nDDDC\nDDDD\n</code></pre>",
          "<p>Wow, you're basically a hacker now!</p>\n<p>One more exercise. Given a size:</p>\n<pre><code>size = 5\n</code></pre>\n<p>Print out an 'upside down' triangle made of the letter <code>O</code> whose sides are as long as the given size, e.g:</p>\n<pre><code>OOOOO\nOOOO\nOOO\nOO\nO\n</code></pre>",
          "<p>Wow, you're an artist too!</p>"
        ]
      }
    ],
    "user": {
      "email": "[email protected]",
      "developerMode": true
    },
    "processing": false,
    "numHints": 0,
    "editorContent": "",
    "messages": [],
    "pastMessages": [],
    "requestingSolution": false,
    "solution": {
      "tokens": [],
      "maskedIndices": [],
      "mask": []
    }
  }
}

Handle Javascript errors

The interface currently can't handle errors in the Javascript side. We need a React error boundary instead of the screen going blank. It would also be nice to automatically open a feedback form the way we do if there's an error in the backend.

Fundraising

Eventually we will need to launch this project with some serious hosting to handle large numbers of users. We will need donations to sustain the project.

This isn't a pressing issue yet, as there's still lots of work to do before the project is ready for users, but it's something worth thinking about. I've never done this before so I'd love to hear ideas.

Functions chapter

Some things to add to the current functions chapter:

  • In the page on calling functions from functions, after showing what this looks like in various debuggers, I want to show what it looks like in a traceback. An exception should be raised in the innermost function (e.g. by intentionally misspelling a name) and then explain the resulting traceback.
  • Scope and local variables:
    • Explain that variables defined in one function are not accessible outside that function
    • If they want to access them, they should return them
    • However they can access global variables from within a function
    • Explain that global and local variables should have different names to avoid errors
  • Explain that return ends the function call. Sometimes beginners want to return a list of values like this:
def double_nums(nums):
    for n in nums:
        return n * 2

Explain that they must build up a list instead. Maybe hint at generators but don't actually show them.

Things that will only be covered in a later chapter:

  • Variadic, named, or optional arguments/parameters
  • Higher order functions, functions as objects, functional programming, etc.
  • How to set global variables with the global statement
  • Inner functions and closures

Make bonus challenges concrete

There are currently three bonus challenges in the text (search the chapters for 'bonus'). The first one is in chapter 4 and is a proper exercise with hints and a solution. The other two don't have this, they're just described in the text. They should be converted to real ExerciseSteps and moved to the end of the page with a link to the next page, just like the first one.

@spamegg1 this is a decent bite sized task, want to give it a go?

Unable to run commands in shell

User Issue
Email: [email protected]
User Agent: PC / Windows 10 / Edge 84.0.522

Using Windows 10 PC, have tried Edge and Chrome browsers

Any time I attempt to run any sort of command in shell, the system responds by saying that the process died because it is taking too long. Not sure if this is due to high traffic - will check later

Redux state

{
  "rpc": {
    "loading": [],
    "error": null
  },
  "book": {
    "server": {
      "hints": [],
      "step_index": 0,
      "pages_progress": [
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "page_index": 0,
      "showEditor": false,
      "showSnoop": false,
      "showPythonTutor": false,
      "showBirdseye": true
    },
    "pages": [
      {
        "slug": "IntroducingTheShell",
        "title": "Introducing The Shell",
        "index": 0,
        "step_texts": [
          "<p>At the bottom right of the screen is the <em>shell</em>. This is a place for running small bits of Python code. Just type in some code, press enter, and it'll run! Try it now:</p>\n<ol>\n<li>Click anywhere on the shell (the black area).</li>\n<li>Type <code>1+2</code></li>\n<li>Press the Enter key on your keyboard.</li>\n</ol>",
          "<p>Great! Python evaluated <code>1+2</code> and got the result <code>3</code>, so the shell displays that.</p>\n<p>The shell is probably your most important tool for learning Python, and you should spend lots of time experimenting and exploring in it. Be curious! Constantly ask yourself \"What would happen if I ran X?\" and then immediately answer that question by running it! Never be scared to try something out - if you get something wrong, nothing bad will happen.</p>\n<p>Try doing some more calculations now. You can multiply numbers with <code>*</code>, divide with <code>/</code>, and subtract with <code>-</code>. You can also use parentheses, i.e. <code>(</code> and <code>)</code>.</p>",
          "<p>Excellent! Keep experimenting. When you're ready, click 'Next' to continue.</p>"
        ]
      },
      {
        "slug": "NavigatingShellHistory",
        "title": "Navigating Shell History",
        "index": 1,
        "step_texts": [
          "<p>Here's a tip: often you will want to re-run a previously entered bit of code, or a slightly modified version of it. You can copy and paste, but that's tedious and gets in the way of experimenting. A better method is to press the Up Arrow key on your keyboard. This will insert the previous line of code into the shell. Keep pressing it to go further back in your history, and if you go too far, press the Down Arrow key to go the other way. Try using it now.</p>"
        ]
      },
      {
        "slug": "IntroducingStrings",
        "title": "Introducing Strings",
        "index": 2,
        "step_texts": [
          "<p>Python lets you do much more than calculate. In fact, we're not going to touch numbers or maths for a while. Instead, we're going to look at <em>strings</em>. Strings are essentially snippets of text. For example, enter the following into the shell, quotes (<code>'</code>) included:</p>\n<pre><code>'hello'\n</code></pre>",
          "<p>The shell simply gives the same thing back because there's nothing to further to calculate. <code>'hello'</code> is simply equal to <code>'hello'</code>.</p>\n<p>A string is a sequence of characters. A character is a single symbol such as a letter, number, punctuation, space, etc. In this case the string contains the 5 characters <code>hello</code>. The quotes are not part of the string - they are there to tell both humans and computers that this is a string consisting of whatever characters are between the quotes.</p>"
        ]
      },
      {
        "slug": "AddingStrings",
        "title": "Adding Strings",
        "index": 3,
        "step_texts": [
          "<p>Strings can be added together using <code>+</code>, although this means something very different from adding numbers. For example, try:</p>\n<pre><code>'hello' + 'world'\n</code></pre>",
          "<p>You can see that <code>+</code> combines or joins two strings together end to end. Technically, this is called concatenation.</p>\n<p>Here's an exercise: change the previous code slightly so that the result is the string <code>'hello world'</code>, i.e. with a space between the words.</p>\n<p>By the way, if you get stuck, you can click the lightbulb icon in the bottom right for a hint.</p>",
          "<p>Well done! Any of the following are valid solutions:</p>\n<pre><code>'hello ' + 'world'\n'hello' + ' world'\n'hello' + ' ' + 'world'\n</code></pre>"
        ]
      },
      {
        "slug": "IntroducingVariables",
        "title": "Introducing Variables",
        "index": 4,
        "step_texts": [
          "<p>To make interesting programs, we can't always manipulate the same values. We need a way to refer to values that are unknown ahead of time and can change - values that can vary. These are called <em>variables</em>.</p>\n<p>Run this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>",
          "<p>This creates a variable with the name <code>word</code> that refers to the string value <code>'Hello'</code>.</p>\n<p>Check now that this is true by simply running <code>word</code> in the shell by itself.</p>",
          "<p>Good. For comparison, run <code>'word'</code> in the shell by itself, with the quotes.</p>",
          "<p>As you can see, the quotes make all the difference. <code>'word'</code> is literally just <code>'word'</code>, hence it's technically called a <em>string literal</em>. On the other hand, <code>word</code> is a variable, whose value may be anything.</p>\n<p>Similarly, <code>'sunshine'</code> is <code>'sunshine'</code>, but what's <code>sunshine</code> without quotes?</p>",
          "<p>The answer is that <code>sunshine</code> looks like a variable, so Python tries to look up its value, but since we never defined a variable with that name we get an error.</p>"
        ]
      },
      {
        "slug": "UsingVariables",
        "title": "Using Variables",
        "index": 5,
        "step_texts": [
          "<p>Previously we made a variable called <code>word</code> with the value <code>'Hello'</code> with this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>\n<p>Now make a variable called <code>your_name</code> whose value is another string.</p>\n<p>(The character <code>_</code> in <code>your_name</code> is called an <em>underscore</em>. Use it to separate words when you want a variable name containing multiple words. You can type it on most keyboards by pressing Shift and hyphen/dash/minus (<code>-</code>).)</p>",
          "<p>You can use variables in calculations just like you would use literals. For example, try:</p>\n<pre><code>'Hello ' + your_name\n</code></pre>",
          "<p>Or you can just add variables together. Try:</p>\n<pre><code>word + your_name\n</code></pre>",
          "<p>Oops...that doesn't look nice. Can you modify the code above so that there's a space between the word and your name?</p>",
          "<p>Perfect!</p>\n<p>Variables can also change their values over time. Right now <code>word</code> has the value <code>'Hello'</code>. You can change its value in the same way that you set it for the first time. Run this:</p>\n<pre><code>word = 'Goodbye'\n</code></pre>",
          "<p>Now observe the effect of this change by running <code>word + ' ' + your_name</code> again.</p>",
          "<p>Those quotes around strings are getting annoying. Try running this:</p>\n<pre><code>print(word + ' ' + your_name)\n</code></pre>",
          "<p>Hooray! No more quotes! We'll break down what's happening in this code later. For now just know that <code>print(&lt;something&gt;)</code> displays <code>&lt;something&gt;</code> in the shell. In particular it displays the actual content of strings that we usually care about, instead of a representation of strings that's suitable for code which has things like quotes. The word <code>print</code> here has nothing to do with putting ink on paper.</p>"
        ]
      },
      {
        "slug": "WritingPrograms",
        "title": "Writing Programs",
        "index": 6,
        "step_texts": [
          "<p>It's time to stop doing everything in the shell. In the top right you can see the <em>editor</em>. This is a place where you can write and run longer programs. The shell is great and you should keep using it to explore, but the editor is where real programs live.</p>\n<p>Copy the program below into the editor, then click the 'Run' button:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nprint(word + ' ' + name)\nword = 'Goodbye'\nprint(word + ' ' + name)\n</code></pre>",
          "<p>Congratulations, you have run your first actual program!</p>\n<p>Take some time to understand this program. Python runs each line one at a time from top to bottom. You should try simulating this process in your head - think about what each line does. See how the value of <code>word</code> was changed and what effect this had. Note that when <code>print</code> is used multiple times, each thing (<code>Hello World</code> and <code>Goodbye World</code> in this case) is printed on its own line.</p>\n<p>Some things to note about programs in the editor:</p>\n<ol>\n<li>The program runs in the shell, meaning that the variables defined in the program now exist in the shell with the last values they had in the program. This lets you explore in the shell after the program completes. For example, <code>name</code> now has the value <code>'World'</code> in the shell.</li>\n<li>Programs run in isolation - they don't depend on any previously defined variables. The shell is reset and all previous variables are cleared. So even though <code>word</code> currently exists in the shell, if you delete the first line of the program and run it again, you'll get an error about <code>word</code> being undefined.</li>\n<li>If you enter code in the shell and it has a value, that value will automatically be displayed. That doesn't happen for programs in the editor - you have to print values. If you remove <code>print()</code> from the program, changing the two lines to just <code>word + ' ' + name</code>, nothing will be displayed.</li>\n</ol>\n<p>I recommend that you check all of these things for yourself.</p>"
        ]
      },
      {
        "slug": "StoringCalculationsInVariables",
        "title": "Storing Calculations In Variables",
        "index": 7,
        "step_texts": [
          "<p>Often you will use variables to store the results of calculations. This will help to build more complex programs. For example, try this program:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nsentence = word + ' ' + name\nprint(sentence)\n</code></pre>",
          "<p>Now <code>sentence</code> has the value <code>'Hello World'</code> which can be used multiple times. Note that it will continue to have this value until it is directly reassigned, e.g. with another statement like <code>sentence = &lt;something&gt;</code>. For example, add these two lines to the end of the program:</p>\n<pre><code>word = 'Goodbye'\nprint(sentence)\n</code></pre>",
          "<p>Unlike a spreadsheet where formulas update automatically, a variable like <code>sentence</code> doesn't remember how it was calculated and won't change if the underlying values <code>word</code> or <code>name</code> are changed.</p>"
        ]
      },
      {
        "slug": "IntroducingForLoops",
        "title": "Introducing For Loops",
        "index": 8,
        "step_texts": [
          "<p>Good news! You've made it past the boring basics. We can start to write some interesting programs and have a bit of fun. One of the most powerful concepts in programming is the <em>loop</em>, which lets you repeat the same code over and over. Python has two kinds of loop: <code>for</code> loops and <code>while</code> loops. Here is an example of a for loop, try running this program:</p>\n<pre><code>name = 'World'\nfor character in name: print(character)\n</code></pre>",
          "<p>You can read the code almost like normal English:</p>\n<blockquote>\n<p>For each character in the string <code>name</code>, print that character.</p>\n</blockquote>\n<p>Each character is just a normal string. <code>character</code> is a normal variable that is given a new value before the code after the <code>:</code> runs. So the code above is equivalent to:</p>\n<pre><code>name = 'World'\n\ncharacter = 'W'\nprint(character)\n\ncharacter = 'o'\nprint(character)\n\ncharacter = 'r'\nprint(character)\n\ncharacter = 'l'\nprint(character)\n\ncharacter = 'd'\nprint(character)\n</code></pre>\n<p>Note that we could use a different variable name, <code>character</code> just makes it clearer.</p>\n<p>A for loop generally follows this structure:</p>\n<pre><code>for &lt;variable&gt; in &lt;collection&gt;: &lt;code to repeat&gt;\n</code></pre>\n<p>The <code>for</code>, <code>in</code>, and <code>:</code> are all essential.</p>"
        ]
      },
      {
        "slug": "Indentation",
        "title": "Indentation",
        "index": 9,
        "step_texts": [
          "<p>This example loop:</p>\n<pre><code>for character in name: print(character)\n</code></pre>\n<p>works, but actually it would usually (and should) be written like this:</p>\n<pre><code>for character in name:\n    print(character)\n</code></pre>\n<p>Specifically, the code to be repeated (known as the <em>body</em>) starts on a new line after the colon (<code>:</code>), and it must be <em>indented</em>, i.e. have some spaces before it. The code below without indentation is invalid, run it to see for yourself:</p>\n<pre><code>for character in name:\nprint(character)\n</code></pre>",
          "<p>The spaces are required to tell Python which lines of code belong to the body of the for loop. This is critical when the loop contains several lines, which it often will. For example, run this code:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>",
          "<p>There are two indented lines, so they're both part of the body, so <code>---</code> gets printed after each character. Now try running the same code without the indentation in the last line:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\nprint('---')\n</code></pre>",
          "<p>Since <code>print('---')</code> is not indented, it's not part of the loop body. This means it only runs once, after the whole loop has finished running. Both programs are valid, they just do different things.</p>\n<p>The program below is invalid. Both lines in the loop body are indented, but by different amounts. The first line starts with 4 spaces, the second line starts with 2. Try running it.</p>\n<pre><code>for character in name:\n    print(character)\n  print('---')\n</code></pre>",
          "<p>When you indent, you should always indent by 4 spaces. Any consistent indentation is actually acceptable, but 4 spaces is the convention that almost everyone follows. Note that the editor generally makes this easy for you. For example, if you press the 'Tab' key on your keyboard in the editor, it will insert 4 spaces for you.</p>"
        ]
      },
      {
        "slug": "BasicForLoopExercises",
        "title": "Basic For Loop Exercises",
        "index": 10,
        "step_texts": [
          "<p>Time for some exercises! Modify this program:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>\n<p>to instead output:</p>\n<pre><code>---W\n---o\n---r\n---l\n---d\n</code></pre>",
          "<p>Splendid! Now write a program which prints <code>name</code> once for each character in <code>name</code>. For example, for <code>name = 'Amy'</code>, it should output:</p>\n<pre><code>Amy\nAmy\nAmy\n</code></pre>\n<p>For <code>name = 'World'</code>, it should output:</p>\n<pre><code>World\nWorld\nWorld\nWorld\nWorld\n</code></pre>\n<p>By the way, you can set <code>name</code> to anything in the first line. Only the rest of the program after that will be checked.</p>",
          "<p>We're making really good progress! You're solving problems and writing new code!\nLet's keep making things more interesting.</p>"
        ]
      },
      {
        "slug": "BuildingUpStrings",
        "title": "Building Up Strings",
        "index": 11,
        "step_texts": [
          "<p>Before we look at some more loops, we need to quickly learn another concept. Look at this program:</p>\n<pre><code>hello = 'Hello'\nprint(hello)\nhello = hello + '!'\nprint(hello)\n</code></pre>\n<p>What do you think the line <code>hello = hello + '!'</code> does? What do you think the program will output? Make a prediction, then run it to find out.</p>",
          "<p>Python doesn't care that <code>hello</code> is on both the left and the right of the <code>=</code>, it just does what it would always do if the variables were different: it calculates <code>hello + '!'</code> which at the time is <code>'Hello' + '!'</code> which is <code>'Hello!'</code>, and that becomes the new value of <code>hello</code>. If it helps, you can think of that line as split into two steps:</p>\n<pre><code>temp = hello + '!'\nhello = temp\n</code></pre>\n<p>or:</p>\n<pre><code>temp = hello\nhello = temp + '!'\n</code></pre>\n<p>This is very useful in a loop. Think about what this program will do, then run it:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>By the way, <code>''</code> is called the <em>empty string</em> - a string containing no characters.</p>",
          "<p>The details in the above program are important. What goes wrong if you swap the last two lines and run this program instead?</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    print(line)\n    line = line + char\n</code></pre>",
          "<p>The last character in <code>name</code> only gets added to <code>line</code> at the end of the loop, after <code>print(line)</code> has already run for the last time. So that character and the full <code>name</code> never get printed at the bottom of the triangle.</p>"
        ]
      },
      {
        "slug": "BuildingUpStringsExercises",
        "title": "Building Up Strings Exercises",
        "index": 12,
        "step_texts": [
          "<p>Modify this program:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>to add a space after every character in the triangle, so the output looks like this:</p>\n<pre><code>W\nW o\nW o r\nW o r l\nW o r l d\n</code></pre>",
          "<p>Tremendous! Now modify the program so that each line is backwards, like this:</p>\n<pre><code>W\noW\nroW\nlroW\ndlroW\n</code></pre>",
          "<p>Brilliant!</p>\n<p>Code like:</p>\n<pre><code>line = line + char\n</code></pre>\n<p>is so common that Python lets you abbreviate it. This means the same thing:</p>\n<pre><code>line += char\n</code></pre>\n<p>Note that there is no abbreviation for <code>line = char + line</code>.</p>\n<p>Now use <code>+=</code> and a for loop to write your own program which prints <code>name</code> 'underlined', like this:</p>\n<pre><code>World\n-----\n</code></pre>\n<p>There should be one <code>-</code> for each character in <code>name</code>.</p>",
          "<p>Fantastic!</p>\n<p>By the way, when you don't need to use a variable, it's common convention to name that variable <code>_</code> (underscore), e.g. <code>for _ in name:</code>. This doesn't change how the program runs, but it's helpful to readers.</p>\n<p>Let's make this fancier. Extend your program to draw a box around the name, like this:</p>\n<pre><code>+-------+\n| World |\n+-------+\n</code></pre>\n<p>Note that there is a space between the name and the pipes (<code>|</code>).</p>",
          "<p>You're getting good at this! Looks like you need more of a challenge...maybe instead of putting a name in a box, the name should be the box? Write a program that outputs this:</p>\n<pre><code>+World+\nW     W\no     o\nr     r\nl     l\nd     d\n+World+\n</code></pre>",
          "<p>Sweet! You're really getting the hang of this! If you want, here's one more optional bonus challenge. Try writing a program that outputs:</p>\n<pre><code>W\n o\n  r\n   l\n    d\n</code></pre>\n<p>Or don't, it's up to you.</p>"
        ]
      },
      {
        "slug": "BasicTerminology",
        "title": "Basic Terminology",
        "index": 13,
        "step_texts": [
          "<p>Here's some words you need to know:</p>\n<p>An <strong><em>expression</em></strong> is a piece of code that has a value. For example, in this line of code:</p>\n<pre><code>sentence = 'Hello ' + name\n</code></pre>\n<p>there are three expressions:</p>\n<ol>\n<li><code>'Hello '</code></li>\n<li><code>name</code></li>\n<li><code>'Hello ' + name</code></li>\n</ol>\n<p>By contrast, the full line <code>sentence = ...</code> is a <strong><em>statement</em></strong>. It's a command that tells the computer to perform an action. It has no value of its own. This means, for example, that you can't add statements together. This code is invalid:</p>\n<pre><code>(word = 'Hello') + (name = 'Bob')\n</code></pre>\n<p>Specifically, a statement like <code>sentence = ...</code> where a variable is given a value is called <strong><em>assignment</em></strong> - the value is <em>assigned to</em> the the variable.</p>\n<p>A program is a list of statements which are executed in order. A <code>for</code> loop is a <em>compound statement</em>, meaning it has a body of its own which contains other statements. Most statements will also contain expressions, and expressions can contain other smaller expressions, but expressions cannot contain statements.</p>\n<p>The process of calculating the value of an expression is called <strong><em>evaluation</em></strong> - note how it almost contains the word 'value'. The computer <em>evaluates</em> <code>1 + 2</code> to get the value <code>3</code>.</p>\n<p>The process of executing a loop is called <strong><em>iteration</em></strong>. Code like <code>for char in 'Hello':</code> is <em>iterating over</em> the string <code>'Hello'</code>. The fact that it's possible means that strings are <em>iterable</em>. By contrast, numbers are not iterable, which is exactly what Python will tell you if you try <code>for char in 3:</code>. Each run through the loop is <em>one iteration</em>, so in this example there will be 5 iterations.</p>"
        ]
      },
      {
        "slug": "IntroducingIfStatements",
        "title": "Introducing If Statements",
        "index": 14,
        "step_texts": [
          "<p>Now we're going to learn how to tell the computer to make decisions and only run code\nunder certain conditions. For this we will need a new type of value. You've seen\nnumbers and strings, now meet <em>booleans</em>. There are only two boolean values:\n<code>True</code> and <code>False</code>. Try this program:</p>\n<pre><code>condition = True\nprint(condition)\ncondition = False\nprint(condition)\n</code></pre>",
          "<p>Booleans are meant to be used inside <em>if statements</em> (sometimes also called <em>conditionals</em>).</p>\n<p>Here is a simple example for you to run:</p>\n<pre><code>if True:\n    print('This gets printed')\n\nif False:\n    print('This does not')\n</code></pre>",
          "<p>Note how the code inside the first <code>if</code> statement ran, but not the second.</p>\n<p>In general, an <code>if</code> statement looks like this:</p>\n<pre><code>if &lt;condition&gt;:\n    &lt;body&gt;\n</code></pre>\n<p>where <code>&lt;condition&gt;</code> is any expression which evaluates to a boolean and <code>&lt;body&gt;</code> is an <strong>indented</strong> list\nof one or more statements. The structure is quite similar to a <code>for</code> loop. Note the colon (<code>:</code>) which\nis essential.</p>\n<p>When the computer sees <code>if &lt;condition&gt;:</code>, it checks if <code>&lt;condition&gt;</code> is <code>True</code>. If it is, it runs the body.\nIf not, it skips it and continues to the rest of the program.</p>\n<p>Here's a more interesting example for you to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence += '!'\nprint(sentence)\n</code></pre>",
          "<p>(Remember that <code>sentence += '!'</code> means <code>sentence = sentence + '!'</code>)</p>\n<p>Change <code>excited = True</code> to <code>excited = False</code> and run the program again to see what the difference is.</p>",
          "<p>Time for an exercise. Modify the program above to include an extra\nboolean parameter <code>confused</code>, so the program should start like this:</p>\n<pre><code>sentence = 'Hello World'\nexcited = False\nconfused = True\n</code></pre>\n<p>(<code>sentence</code> can be any string and the two booleans can be either <code>True</code> or <code>False</code>)</p>\n<p>When <code>confused</code> is true, the printed sentence should have a question mark added to the end.\nIf both <code>confused</code> and <code>excited</code> are true, the sentence should end with <code>!?</code>.</p>",
          "<p>Well done! This program can do 4 different things depending on how you combine <code>excited</code>\nand <code>confused</code>. Try them out if you want.</p>"
        ]
      },
      {
        "slug": "CombiningCompoundStatements",
        "title": "Combining Compound Statements",
        "index": 15,
        "step_texts": [
          "<p>Compound statements like <code>for</code> loops and <code>if</code> statements have bodies which are a list\nof inner statements. Those inner statements can be anything, including other compound statements.\nTry this example of a <code>for</code> loop inside an <code>if</code> statement for when you want to show\nthat you're <em>really</em> excited:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    new_sentence = ''\n    for char in sentence:\n        new_sentence += char\n        new_sentence += '!'\n    sentence = new_sentence\n\nprint(sentence)\n</code></pre>",
          "<p>Note how the body of the <code>if</code> statement (5 lines) is indented as usual, while the body\nof the <code>for</code> loop (2 lines) is indented by an additional 4 spaces in each line to show that\nthose lines are within the <code>for</code> loop. You can see the overall structure of the program\njust by looking at the indentation.</p>\n<p>Alternatively, you can put an <code>if</code> inside a <code>for</code>:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nnew_sentence = ''\nfor char in sentence:\n    new_sentence += char\n    if excited:\n        new_sentence += '!'\n\nsentence = new_sentence\nprint(sentence)\n</code></pre>\n<p>These two programs have the exact same result. However the first one is more efficient as it\nonly iterates over the string if it needs to, since when <code>excited = False</code> nothing changes.</p>"
        ]
      },
      {
        "slug": "UnderstandingProgramsWithSnoop",
        "title": "Understanding Programs With Snoop",
        "index": 16,
        "step_texts": [
          "<p>Run this program:</p>\n<pre><code>sentence = 'Hello World'\n\ninclude = False\nnew_sentence = ''\nfor char in sentence:\n    if include:\n        new_sentence += char\n    include = True\n\nprint(new_sentence)\n</code></pre>",
          "<p>As you can see, it prints everything but the first character. Take some time to understand how this works.</p>\n<p>In fact, it's time to introduce a new tool to help you understand programs. Click the 'Snoop' button to run the same program while also showing what's happening.</p>",
          "<p>Tada! Scroll to the top of the terminal and let's walk through what snoop is showing you.\nIt starts out very straightforward:</p>\n<pre><code>    1 | sentence = 'Hello World'\n    3 | include = False\n    4 | new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The first lines are simply showing you the lines of the program that the computer ran.\nOn the left is the line number as seen in the editor.</p>\n<p>Running <code>for char in sentence:</code> assigns a value to the variable <code>char</code>, so snoop shows you that value.\nLines starting with <code>......</code> indicate a new variable or a change in the value of an existing variable.\nSuch lines will not be shown when they're redundant, which is why the snoop output doesn't start like this:</p>\n<pre><code>    1 | sentence = 'Hello World'\n ...... sentence = 'Hello World'\n    3 | include = False\n ...... include = False\n    4 | new_sentence = ''\n ...... new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The next two lines are:</p>\n<pre><code>    6 |     if include:\n    8 |     include = True\n</code></pre>\n<p>What's important here is what's not showing: because <code>include</code> is <code>False</code>, line 7 (<code>new_sentence += char</code>) gets skipped. But then <code>include</code> is set to <code>True</code>, so the next iteration of the loop is different:</p>\n<pre><code>    5 | for char in sentence:\n ...... char = 'e'\n    6 |     if include:\n    7 |         new_sentence += char\n .............. new_sentence = 'e'\n</code></pre>\n<p><code>new_sentence += char</code> runs for the first time and the variable <code>new_sentence</code> gets a new value.</p>\n<p>Now modify the program to do the opposite: only print the first character, leave out the rest.</p>",
          "<p>Great job! You're working with increasingly complex programs.</p>"
        ]
      },
      {
        "slug": "IfAndElse",
        "title": "<code>if</code> and <code>else</code>",
        "index": 17,
        "step_texts": [
          "<p>An <code>if</code> statement can optionally have an <code>else</code> part. Run this example:</p>\n<pre><code>condition = True\nif condition:\n    print('Yes')\nelse:\n    print('No')\n</code></pre>",
          "<p>Now change the first line to <code>condition = False</code> and run it again.</p>",
          "<p>Think of <code>else</code> as saying 'or else' or 'otherwise'. It means that if the condition in the <code>if</code>\nis false, then the body of the <code>else</code> will run instead. Whether the condition is true or false,\nexactly one of the two bodies will run.</p>\n<p>Here's a more interesting example to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence = sentence.upper()\nelse:\n    sentence = sentence.lower()\nprint(sentence)\n</code></pre>",
          "<p><code>sentence.upper()</code> is a new kind of expression we haven't encountered yet. What's going on here is that <code>sentence</code> is a string and strings have various <em>methods</em> that let you conveniently calculate new values from them, including <code>upper</code> and <code>lower</code>. The names refer to uppercase (capital letters) and lowercase (small letters). <code>'Hello World'.upper()</code> evaluates to <code>'HELLO WORLD'</code>. It doesn't change the contents of <code>sentence</code> though, so you have to assign the new value again with <code>sentence = sentence.upper()</code>.</p>\n<p>Now change <code>excited</code> to <code>False</code> and run it again.</p>",
          "<p>Here's a broken program:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    char = '!'\nsentence += char\n\nprint(sentence)\n</code></pre>\n<p>Can you see the problem? If you run it, everything seems fine. What could go wrong?</p>\n<p>Spoilers below! Have you figured it out?</p>\n<p>What happens if you change <code>excited</code> to <code>False</code>?</p>",
          "<p>If <code>excited</code> is true then <code>char</code> is defined and everything runs fine. But otherwise\n<code>char</code> never gets assigned a value, so trying to use it in <code>sentence += char</code> fails.</p>\n<p>Fix this by adding an <code>else</code> clause to the <code>if</code> so that if <code>excited</code> is false, a full stop (<code>.</code>)\nis added to the end of the sentence instead of an exclamation mark (<code>!</code>).</p>",
          "<p>Time for a challenge!</p>\n<p>Write a program which, given a string <code>sentence</code>, prints a modified version with\nthe same letters, where the first letter is capitalised and the rest are lowercase.\nFor example, the output should be <code>Hello world</code> whether the input <code>sentence = 'hello world'</code>\nor <code>'HELLO WORLD'</code>.</p>",
          "<p>Excellent!!!</p>\n<p>One more exercise, and then you can relax. </p>\n<p>Write a program which prints <code>sentence</code> mockingly, e.g:</p>\n<pre><code>OnE MoRe eXeRcIsE, aNd tHeN YoU CaN ReLaX.\n</code></pre>\n<p>Every second character should be lowercased, the rest should be uppercase.</p>",
          "<p>Perfect! Take a moment to be proud of what you've achieved. Can you feel your brain growing?</p>"
        ]
      },
      {
        "slug": "TheEqualityOperator",
        "title": "The Equality Operator",
        "index": 18,
        "step_texts": [
          "<p>There are several ways to obtain booleans without assigning them directly,\nwhich allows you to construct very useful <code>if</code> statements. In particular there\nare many <em>comparison operators</em> which compare the values of two expressions.\nThe most common is the equality operator which checks if two values are equal.\nIt's denoted by two equals signs: <code>==</code>. Try running this:</p>\n<pre><code>print(1 + 2 == 3)\nprint(4 + 5 == 6)\nprint('ab' + 'c' == 'a' + 'bc')\n</code></pre>",
          "<p>As you can see, if the values are equal, the equality expression evaluates to <code>True</code>,\notherwise it's <code>False</code>.</p>\n<p>Note the difference between the equality operator <code>==</code> and a single <code>=</code> which has different meanings,\nparticularly in assignment statements as you've seen them so far. What happens if you try\nremoving a single <code>=</code> from the previous program?</p>",
          "<p>Let's use <code>==</code> in an <code>if</code> statement. In this program, the <code>if</code> body runs only when <code>c</code> is the character <code>'s'</code>. See for yourself.</p>\n<pre><code>name = 'kesha'\nnew_name = ''\nfor c in name:\n    if c == 's':\n        c = '$'\n    new_name += c\n\nprint(new_name)\n</code></pre>",
          "<p>Now extend the program to also replace <code>e</code> with <code>3</code> and <code>a</code> with <code>@</code>.</p>",
          "<p>Well done!</p>"
        ]
      },
      {
        "slug": "IntroducingElif",
        "title": "Introducing <code>elif</code>",
        "index": 19,
        "step_texts": [
          "<p>Quick biology lesson! Most of the cells in your body contain your full genetic code in DNA.\nThis consists of strands of molecular units called nucleobases which come in four varieties:\nAdenine, Cytosine, Guanine, and Thymine, or ACGT for short.\nSo part of a single strand might be something like:</p>\n<pre><code>AGTAGCGTCCTTAGTTACAGGATGGCTTAT...\n</code></pre>\n<p>This will be paired with another strand where A is replaced by T and vice versa,\nand C is replaced by G and vice versa, e.g:</p>\n<pre><code>TCATCGCAGGAATCAATGTCCTACCGAATA...\n</code></pre>\n<p>The two strands are 'zipped' together into the famous double helix structure,\njoined by the matching A-T and C-G pairs. These pairings are essential in copying DNA when\ncells divide and reproduce. The double helix is unzipped and the code is transcribed\ninto its opposite version to make the copy.</p>\n<p>We're going to repeat that process. Let's try the same kind of program we just wrote:</p>\n<pre><code>dna = 'AGTAGCGTC'\nopposite_dna = ''\nfor char in dna:\n    if char == 'A':\n        char = 'T'\n    if char == 'T':\n        char = 'A'\n    if char == 'G':\n        char = 'C'\n    if char == 'C':\n        char = 'G'\n    opposite_dna += char\n\nprint(opposite_dna)\n</code></pre>",
          "<p>Oh dear, that doesn't quite work. <code>T</code> is changed to <code>A</code> but <code>A</code> isn't changed to anything.\nCan you see why?</p>\n<p>When <code>char == 'A'</code>, then the body <code>char = 'T'</code> does indeed run. But that means that the following\ncondition <code>char == 'T'</code> also passes and so <code>char = 'A'</code> and we're back where we started.\nWe need to only change <code>char</code> from <code>T</code> to <code>A</code> if <code>char</code> wasn't already <code>A</code> to begin with,\nmeaning <code>char == 'A'</code> was <code>False</code>. We can do that with an <code>else</code>, like so:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelse:\n    if char == 'T':\n        char = 'A'\n</code></pre>\n<p>Now fix the program to replace all characters correctly.</p>",
          "<p>Brilliant! You have mimicked what your own cells are constantly doing.</p>\n<p>An <code>if</code> inside an <code>else</code> can be replaced by a single keyword <code>elif</code>. For example,\nthe previous code can be changed to this:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelif char == 'T':\n    char = 'A'\nelif char == 'G':\n    char = 'C'\nelif char == 'C':\n    char = 'G'\n</code></pre>",
          "<p>It's common to have a chain of <code>elif</code> clauses when you want exactly one of many\nbodies to run, like in this case. In general, code like this:</p>\n<pre><code>if X:\n    ...\nelse:\n    if Y:\n        ...\n    else:\n        if Z:\n            ...\n        else:\n            ...\n</code></pre>\n<p>can be rewritten as:</p>\n<pre><code>if X:\n    ...\nelif Y:\n    ...\nelif Z:\n    ...\nelse:\n    ...\n</code></pre>\n<p>which is both shorter and saves you from unpleasant nested indentation.\nThe difference is only cosmetic: once the computer runs this code, it can't\ntell the difference between the two versions.</p>\n<p>Note that <code>elif</code>(s) can optionally be followed by one final <code>else</code>. We didn't include one\nin our DNA example, but we could add one to alert us to any unexpected characters\nin the input, or change <code>elif char == 'C':</code> to <code>else:</code> if we were confident\nabout the input being valid.</p>"
        ]
      },
      {
        "slug": "OtherComparisonOperators",
        "title": "Other Comparison Operators",
        "index": 20,
        "step_texts": [
          "<p>The opposite of the equals operator <code>==</code> is the <em>not equals</em> operator <code>!=</code>. If you squint it sort of looks like \u2260. It evaluates to <code>True</code> when two values are...not equal. Try it for yourself in the shell.</p>",
          "<p>Here's a cute little program using <code>!=</code>:</p>\n<pre><code>sentence = \"The e key on my keyboard is broken\"\nnew_sentence = ''\nfor c in sentence:\n    if c != 'e':\n        new_sentence += c\nprint(new_sentence)\n</code></pre>",
          "<p>Other handy operators are <code>&lt;</code> (less than) and <code>&gt;</code> (greater than). For example, <code>a &lt; b</code> means \"<code>a</code> is less than <code>b</code>\". Try using one of these in the shell to compare two numbers.</p>",
          "<p>You can also use these operators to compare strings. If you arrange two strings in alphabetical order, the first one is 'less than' the second. See for yourself.</p>",
          "<p>Here's a practical example of <code>&lt;</code> in action for you to try:</p>\n<pre><code>percentage = 73\n\nif percentage &lt; 20:\n    grade = \"F\"\nelif percentage &lt; 40:\n    grade = \"D\"\nelif percentage &lt; 60:\n    grade = \"C\"\nelif percentage &lt; 80:\n    grade = \"B\"\nelse:\n    grade = \"A\"\n\nprint(grade)\n</code></pre>\n<p>Recall that <code>elif percentage &lt; 40</code> after <code>if percentage &lt; 20</code> means \"if the percentage wasn't less than 20 and also is less than 40\", so it will pass for all numbers from 20 to 39 inclusive. Similarly a 'C' is for percentages from 40 to 59, and an 'A' is for any number 80 and up.</p>",
          "<p>Now for an exercise: write a program that takes three variables <code>x1</code>, <code>x2</code>, and <code>x3</code>, and prints the value of the smallest one. So for:</p>\n<pre><code>x1 = 'Charlie'\nx2 = 'Alice'\nx3 = 'Bob'\n</code></pre>\n<p>it should print <code>Alice</code>.</p>",
          "<p>Marvelous!</p>\n<p>There are many ways this could be solved. Here's one solution:</p>\n<pre><code>if x1 &lt; x2:\n    if x1 &lt; x3:\n        first = x1\n    else:\n        first = x3\nelse:\n    if x2 &lt; x3:\n        first = x2\n    else:\n        first = x3\n\nprint(first)\n</code></pre>\n<p>Here's another:</p>\n<pre><code>first = x1\n\nif x2 &lt; first:\n    first = x2\n\nif x3 &lt; first:\n    first = x3\n\nprint(first)\n</code></pre>\n<p>These programs (and yours too) all work equally well with numbers and strings,\nbut not a mixture.</p>\n<p><code>&lt;</code> and <code>&gt;</code> evaluate to False if the compared values are equal. For example,\n3 is not less than 3, so <code>3 &lt; 3</code> and <code>3 &gt; 3</code> are both False.\nTo allow equal values, use <code>&lt;=</code> and <code>&gt;=</code>.\nAgain, if you squint, they look a bit like \u2264 and \u2265.\nNote that the <code>=</code> comes second - there are no such operators as <code>=&lt;</code> or <code>=&gt;</code>.\nTo remember this, read them out loud as \"less than or equal to\"\nand \"greater than or equal to\".</p>\n<p>In summary, the main comparison operators are <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, and <code>&gt;=</code>.\nIf you ever have doubts about what they do, play with them in the shell!</p>"
        ]
      },
      {
        "slug": "IntroducingLists",
        "title": "Introducing Lists",
        "index": 21,
        "step_texts": [
          "<p>It's time to learn about a powerful new type of value called lists. Here's an example:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor word in words:\n    print(word)\n</code></pre>",
          "<p>A list is a <em>sequence</em> (an ordered collection/container) of any number of values.\nThe values are often referred to as <em>elements</em>.\nThey can be anything: numbers, strings, booleans, even lists! They can also be a mixture of types.</p>\n<p>To create a list directly, like above:</p>\n<ol>\n<li>Write some square brackets: <code>[]</code></li>\n<li>If you don't want an empty list, write some expressions inside to be the elements.</li>\n<li>Put commas (<code>,</code>) between elements to separate them.</li>\n</ol>\n<p>Here's another example of making a list:</p>\n<pre><code>x = 1\nthings = ['Hello', x, x + 3]\nprint(things)\n</code></pre>",
          "<p>As you saw above, lists are <em>iterable</em>, meaning you can iterate over them with a <code>for loop</code>.\nHere's a program that adds up all the numbers in a list:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9]\n\ntotal = 0\nfor number in numbers:\n    total += number\n\nprint(total)\n</code></pre>",
          "<p>Now modify the program so that it can add up a list of strings instead of numbers.\nFor example, given:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n</code></pre>\n<p>it should print:</p>\n<pre><code>Thisisalist\n</code></pre>",
          "<p>Optional bonus challenge: extend the program to insert a separator string <em>between</em> each word.\nFor example, given</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\nseparator = ' - '\n</code></pre>\n<p>it would output:</p>\n<pre><code>This - is - a - list\n</code></pre>\n<p>Lists and strings have a lot in common.\nFor example, you can add two lists to combine them together into a new list.\nYou can also create an empty list that has no elements.\nCheck for yourself:</p>\n<pre><code>numbers = [1, 2] + [3, 4]\nprint(numbers)\nnew_numbers = []\nnew_numbers += numbers\nnew_numbers += [5]\nprint(new_numbers)\n</code></pre>\n<p>With that knowledge, write a program which takes a list of numbers\nand prints a list where each number has been doubled. For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[6, 2, 8, 2, 10, 18, 4, 12, 10]\n</code></pre>",
          "<p>Great!</p>\n<p>When you want to add a single element to the end of a list, instead of:</p>\n<pre><code>some_list += [element]\n</code></pre>\n<p>it's actually more common to write:</p>\n<pre><code>some_list.append(element)\n</code></pre>\n<p>There isn't really a big difference between these, but <code>.append</code>\nwill be more familiar and readable to most people.</p>\n<p>Now use <code>.append</code> to write a program which prints a list containing only the numbers bigger than 5.</p>\n<p>For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[9, 6]\n</code></pre>",
          "<p>Fantastic! We're making great progress.</p>"
        ]
      },
      {
        "slug": "UsingBreak",
        "title": "Using <code>break</code> to end a loop early",
        "index": 22,
        "step_texts": [
          "<p>Exercise: write a program which takes a list and a value and checks\nif the list contains the value. For example, given:</p>\n<pre><code>things = ['This', 'is', 'a', 'list']\nthing_to_find = 'is'\n</code></pre>\n<p>it should print <code>True</code>, but for</p>\n<pre><code>thing_to_find = 'other'\n</code></pre>\n<p>it should print <code>False</code>.</p>",
          "<p>Nice!</p>\n<p>A typical solution looks something like this:</p>\n<pre><code>found = False\nfor thing in things:\n    if thing == thing_to_find:\n        found = True\n\nprint(found)\n</code></pre>\n<p>Your solution is probably similar. It's fine, but it's a bit inefficient.\nThat's because it'll loop over the entire list even if it finds the element at the beginning.\nYou can stop any loop using a <code>break</code> statement, like so:</p>\n<pre><code>for thing in things:\n    if thing == thing_to_find:\n        found = True\n        break\n</code></pre>\n<p>This is just as correct but skips unnecessary iterations and checks once it finds the element.\nYou can use snoop to see the difference.</p>"
        ]
      },
      {
        "slug": "GettingElementsAtPosition",
        "title": "Getting Elements at a Position",
        "index": 23,
        "step_texts": [
          "<p>Looping is great, but often you just want to retrieve a single element from the list at a known position.\nHere's how:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nprint(words[0])\nprint(words[1])\nprint(words[2])\nprint(words[3])\n</code></pre>",
          "<p>In general, you can get the element at the position <code>i</code> with <code>words[i]</code>. The operation is called <em>subscripting</em> or <em>indexing</em>, and the position is called the <em>index</em>.</p>\n<p>You've probably noticed that the first index is 0, not 1. In programming, counting starts at 0. It seems weird, but that's how most programming languages do it, and it's generally agreed to be better.</p>\n<p>This also means that the last index in this list of 4 elements is 3. What happens if you try getting an index greater than that?</p>",
          "<p>There you go. <code>words[4]</code> and beyond don't exist, so trying that will give you an error.</p>\n<p>By the way, you can get the number of elements in a list (commonly called the <em>length</em>) using <code>len(words)</code>.\nThat means that the last valid index of the list is <code>len(words) - 1</code>, so the last element is <code>words[len(words) - 1]</code>. Try these for yourself.</p>\n<p>So in general, the valid indices are:</p>\n<pre><code>[0, 1, 2, ..., len(words) - 2, len(words) - 1]\n</code></pre>\n<p>There's a handy built in function to give you these values, called <code>range</code>:</p>\n<pre><code>for i in range(10):\n    print(i)\n</code></pre>",
          "<p><code>range(n)</code> is similar to the list <code>[0, 1, 2, ..., n - 2, n - 1]</code>.\nThis gives us an alternative way to loop over a list:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor index in range(len(words)):\n    print(index)\n    print(words[index])\n</code></pre>",
          "<p>Let's get some exercise! Given a list <code>things</code> and a value <code>to_find</code>,\nprint the first index of <code>to_find</code> in the list, i.e. the lowest number <code>i</code> such that\n<code>things[i]</code> is <code>to_find</code>. For example, for</p>\n<pre><code>things = ['on', 'the', 'way', 'to', 'the', 'store']\nto_find = 'the'\n</code></pre>\n<p>your program should print <code>1</code>.</p>\n<p>You can assume that <code>to_find</code> appears at least once.</p>",
          "<p>Nice!</p>\n<p>By the way, indexing and <code>len()</code> also work on strings. Try them out in the shell.</p>\n<p>Here's another exercise. Given two strings of equal length, e.g:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"World\"\n</code></pre>\n<p>print them vertically side by side, with a space between each character:</p>\n<pre><code>H W\ne o\nl r\nl l\no d\n</code></pre>",
          "<p>Incredible!</p>\n<p>Your solution probably looks something like this:</p>\n<pre><code>for i in range(len(string1)):\n    char1 = string1[i]\n    char2 = string2[i]\n    print(char1 + ' ' + char2)\n</code></pre>\n<p>This doesn't work so well if the strings have different lengths.\nIn fact, it goes wrong in different ways depending on whether <code>string1</code> or <code>string2</code> is longer.\nYour next challenge is to fix this problem by filling in 'missing' characters with spaces.</p>\n<p>For example, for:</p>\n<pre><code>string1 = \"Goodbye\"\nstring2 = \"World\"\n</code></pre>\n<p>output:</p>\n<pre><code>G W\no o\no r\nd l\nb d\ny  \ne\n</code></pre>\n<p>and for:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"Elizabeth\"\n</code></pre>\n<p>output:</p>\n<pre><code>H E\ne l\nl i\nl z\no a\n  b\n  e\n  t\n  h\n</code></pre>",
          "<p>Magnificent! Take a break, you've earned it!</p>"
        ]
      },
      {
        "slug": "CallingFunctionsTerminology",
        "title": "Terminology: Calling functions and methods",
        "index": 24,
        "step_texts": [
          "<p>It's time to expand your vocabulary some more.</p>\n<p><code>print</code> and <code>len</code> are <strong><em>functions</em></strong>. See for yourself:</p>\n<pre><code>print(len)\nprint(print)\n</code></pre>",
          "<p>An expression like <code>len(things)</code> or <code>print(things)</code> is a function <strong><em>call</em></strong> - when you write that, you are <strong><em>calling</em></strong> the function <code>len</code> or <code>print</code>. The fact that this is possible means that functions are <strong><em>callable</em></strong>:</p>\n<pre><code>print(callable(len))\n</code></pre>",
          "<p>Most things are not callable, so trying to call them will give you an error:</p>\n<pre><code>f = 'a string'\nprint(callable(f))\nf()\n</code></pre>",
          "<p>In the call <code>len(things)</code>, <code>things</code> is an <strong><em>argument</em></strong>. Sometimes you will also see the word <strong><em>parameter</em></strong>, which means basically the same thing as argument. It's a bit like you're giving the argument to the function - specifically we say that the argument <code>things</code> is <em>passed</em> to <code>len</code>, and <code>len</code> <em>accepts</em> or <em>receives</em> the argument.</p>\n<p><code>len(things)</code> will evaluate to a number such as 3, in which case we say that <code>len</code> <strong><em>returned</em></strong> 3.</p>\n<p>All calls have to return something...even if it's nothing. For example, <code>print</code>'s job is to display something on screen, not to return a useful value. So it returns something useless instead:</p>\n<pre><code>things = [1, 2, 3]\nlength = len(things)\nprinted = print(length)\nprint(printed)\n</code></pre>",
          "<p><code>None</code> is a special 'null' value which can't do anything interesting. It's a common placeholder that represents the lack of a real useful value. Functions that don't want to return anything return <code>None</code> by default. If you see an error message about <code>None</code> or <code>NoneType</code>, it often means you assigned the wrong thing to a variable:</p>\n<pre><code>things = print([1, 2, 3])\nlength = len(things)\n</code></pre>",
          "<p>A <strong><em>method</em></strong> is a function which belongs to a type, and can be called on all values of that type using <code>.</code>. For example, <code>upper</code> and <code>lower</code> are methods of strings, which are called with e.g. <code>word.upper()</code>:</p>\n<pre><code>word = 'Hello'\nprint(word.upper)\nprint(word.upper())\n</code></pre>",
          "<p>Another example is that <code>append</code> is a method of lists. But you can't use <code>.upper</code> on a list or <code>.append</code> on a string:</p>\n<pre><code>word = 'Hello'\nword.append('!')\n</code></pre>",
          "<p>The word 'attribute' in the error message refers to the use of <code>.</code> - the error actually comes just from <code>word.append</code>, without even a call.</p>"
        ]
      },
      {
        "slug": "FunctionsAndMethodsForLists",
        "title": "Functions And Methods For Lists",
        "index": 25,
        "step_texts": [
          "<p>Let's review how to work with lists. Suppose we have a list <code>nums = [1, 2, 3]</code>. You can use:</p>\n<ul>\n<li><strong><code>append</code></strong>: Add an element to the end of the list. <code>nums.append(4)</code> changes the list to <code>[1, 2, 3, 4]</code>.</li>\n<li><strong><code>len</code></strong>: Returns the number of elements. <code>len(nums)</code> is <code>3</code>.</li>\n<li><strong><code>range</code></strong>: <code>range(n)</code> is an object similar to the list of numbers from 0 to <code>n - 1</code>. In particular, <code>range(len(nums))</code> is like <code>[0, 1, 2]</code>.</li>\n<li><strong><code>subscripting</code></strong>: Get a value at an index. <code>nums[0]</code> is 1, <code>nums[1]</code> is 2, <code>nums[2]</code> is 3.</li>\n<li><strong><code>+</code></strong>: Concatenates lists. <code>nums + [4, 5]</code> is <code>[1, 2, 3, 4, 5]</code>.</li>\n</ul>\n<p>Here's some new things. Try them out in the shell.</p>\n<ul>\n<li><strong><code>subscript assignment</code></strong>: Set a value at an index. <code>nums[0] = 9</code> changes the list to <code>[9, 2, 3]</code>.</li>\n<li><strong><code>join</code></strong>: Add a list of strings with a separator in between. This is a method of strings (the separator) which takes an iterable of strings as an argument. <code>'--'.join(['apples', 'oranges', 'bananas'])</code> returns <code>'apples--oranges--bananas'</code>. You can also use an empty string if you don't want a separator, e.g. <code>''.join(['apples', 'oranges', 'bananas'])</code> returns <code>'applesorangesbananas'</code>. </li>\n<li><strong><code>sum</code></strong>: Add a list of numbers. <code>sum(nums)</code> is 6.</li>\n<li><strong><code>in</code></strong>: A comparison operator that checks if a value is in a list. <code>2 in nums</code> is <code>True</code>, but <code>4 in nums</code> is <code>False</code>.</li>\n<li><strong><code>index</code></strong>: Returns the first index of a value in a list. <code>[7, 8, 9, 8].index(8)</code> is 1. Raises an error if the value isn't there.</li>\n</ul>\n<p>You may recognise some of these from your exercises. I assure you that those exercises were not pointless, as you've now learned valuable fundamental skills. For example, you can use <code>in</code> to check if a list contains 5, but there's no similarly easy way to check for a number bigger than 5.</p>\n<p>It's useful to know these functions, but it's not easy to learn them all, and there's many more. A more important skill is being able to look things up. For example, here are some typical ways you might Google the above functions if you forgot their names:</p>\n<ul>\n<li><code>append</code><ul>\n<li>python add element to list</li>\n<li>python add item at end of list</li>\n</ul>\n</li>\n<li><code>len</code><ul>\n<li>python size of list</li>\n<li>python number of elements in list</li>\n<li>python how many characters in string</li>\n</ul>\n</li>\n<li><code>join</code><ul>\n<li>python combine list of strings with separator</li>\n<li>python add together list of strings with string in between</li>\n</ul>\n</li>\n<li><code>sum</code><ul>\n<li>python add list of numbers</li>\n<li>python total of numbers</li>\n</ul>\n</li>\n<li><code>in</code><ul>\n<li>python check if list contains value</li>\n<li>python test if list has element</li>\n</ul>\n</li>\n<li><code>index</code><ul>\n<li>python get position of element</li>\n<li>python get index of value</li>\n</ul>\n</li>\n</ul>\n<p>Let's practice this skill now. Find a function/method that returns the value in a list which is bigger than any other value. For example, given the list <code>[21, 55, 4, 91, 62, 49]</code>, it will return <code>91</code>. You should write the answer in the shell as a single small expression. For example, if you were looking for the function <code>sum</code>, you could write <code>sum([21, 55, 4, 91, 62, 49])</code>. Don't solve this manually with a loop.</p>",
          "<p>Good find! Let's do one more. Consider this program:</p>\n<pre><code>nums = [1, 2, 3, 4, 5]\nnums.append(9)\nprint(nums)\n</code></pre>\n<p>This changes <code>nums</code> so that it prints:</p>\n<pre><code>[1, 2, 3, 4, 5, 9]\n</code></pre>\n<p>But suppose you don't want the 9 to be at the end, you want it to go between the second and third elements, so the output is:</p>\n<pre><code>[1, 2, 9, 3, 4, 5]\n</code></pre>\n<p>Replace the middle line (i.e. the call to <code>append</code>) with the right function/method call to do that.</p>",
          "<p>Perfect!</p>\n<p>It can also be useful to Google things like \"python list tutorial\", e.g. if:</p>\n<ul>\n<li>Googling a specific method has failed so you want to find it manually.</li>\n<li>You're still confused about lists after this course.</li>\n<li>It's been a while since you learned about lists and you need a reminder.</li>\n<li>You're struggling to solve a problem with lists and you need to go back to basics and strengthen your foundations.</li>\n</ul>\n<p>There are also ways to find information without any googling. Try <code>dir([])</code> in the shell.</p>",
          "<p><code>dir()</code> returns a list of the argument's attributes, which are mostly methods. Many will start with <code>__</code> which you can ignore for now - scroll to the end of the list and you'll see some familiar methods.</p>\n<p>Here are a few more useful functions/methods. Suppose <code>nums = [28, 99, 10, 81, 59, 64]</code></p>\n<ul>\n<li><strong><code>sorted</code></strong>: Takes an iterable and returns a list of the elements in order. <code>sorted(nums)</code> returns <code>[10, 28, 59, 64, 81, 99]</code>.</li>\n<li><strong><code>pop</code></strong>: Removes and returns an element at a given index. <code>nums.pop(3)</code> removes <code>nums[3]</code> (<code>81</code>) from the list and returns it. Without an argument, i.e. just <code>nums.pop()</code>, it will remove and return the last element.</li>\n<li><strong><code>remove</code></strong>: Removes the first occurrence of the given element. <code>nums.remove(10)</code> will leave <code>nums</code> as <code>[28, 99, 81, 59, 64]</code>. Raises an error if the value doesn't exist. Equivalent to <code>nums.pop(nums.index(10))</code>.</li>\n<li><strong><code>count</code></strong>: Returns the number of times the argument appears in the list. <code>[1, 2, 3, 2, 7, 2, 5].count(2)</code> is 3.</li>\n</ul>\n<p>You've already seen that <code>len</code> and subscripting work with strings, a bit as if strings are lists of characters. Strings also support some of the new methods we've learned, not just for characters but for any substring. For example:</p>\n<ul>\n<li><code>'the' in 'feed the dog and the cat'</code> is <code>True</code></li>\n<li><code>'feed the dog and the cat'.count('the')</code> is 2</li>\n<li><code>'feed the dog and the cat'.index('the')</code> is 5</li>\n</ul>\n<p>Note that in most cases, methods which modify a list in place (<code>append</code>, <code>insert</code>, <code>remove</code>) merely return <code>None</code>, while the remaining functions/methods return a new useful value without changing the original argument. The only exception is the <code>pop</code> method.</p>\n<p>Modifying a value directly is called <em>mutation</em> - types of values which can be mutated are <em>mutable</em>, while those that can't are <em>immutable</em>. Strings are immutable - they don't have any methods like <code>append</code> or even subscript assignment. You simply can't change a string - you can only create new strings and use those instead. That means that this is a useless statement on its own:</p>\n<pre><code>word.upper()\n</code></pre>\n<p>The string referred to by <code>word</code> isn't modified, instead <code>word.upper()</code> returned a new string which was immediately discarded. If you want to change the value that <code>word</code> refers to, you have to assign a new value to the variable:</p>\n<pre><code>word = word.upper()\n</code></pre>\n<p>Or you can use <code>word.upper()</code> immediately in a larger expression, e.g.</p>\n<pre><code>if word.lower() == 'yes':\n</code></pre>"
        ]
      },
      {
        "slug": "UnderstandingProgramsWithPythonTutor",
        "title": "Understanding Programs With Python Tutor",
        "index": 26,
        "step_texts": [
          "<p>It's time to learn about another tool to explore programs.\nCopy the code below into the editor and then click the new \"Python Tutor\" button.\nThe button opens a new tab with a visualisation from <a href=\"http://pythontutor.com\">pythontutor.com</a>.\nThere you can navigate through the program step by step with the \"Prev\" or \"Next\" buttons, or drag\nthe slider left or right. You can also see the values of variables on the right.</p>\n<pre><code>all_numbers = [2, 4, 8, 1, 9, 7]\n\nsmall_numbers = []\nbig_numbers = []\n\nfor number in all_numbers:\n    if number &lt;= 5:\n        small_numbers.append(number)\n    else:\n        big_numbers.append(number)\n\nprint(small_numbers)\nprint(big_numbers)\n</code></pre>",
          "<p>Note that the code runs twice separately: once here, once on pythontutor.com.\nDepending on your program, the two runs may produce different results.</p>"
        ]
      },
      {
        "slug": "EqualsVsIs",
        "title": "<code>==</code> vs <code>is</code>",
        "index": 27,
        "step_texts": [
          "<p>It's time to learn some technical details that are often misunderstood and lead to errors.\nRun this program:</p>\n<pre><code>list1 = [1, 2, 3]\nlist2 = [1, 2, 3]\n\nprint(list1)\nprint(list2)\nprint(list1 == list2)\n\nprint(list1 is list2)\n\nlist1.append(4)\n\nprint(list1)\nprint(list2)\n</code></pre>",
          "<p>This program is quite straightforward and mostly consists of things you're familiar with.\nWe create two variables which refer to lists.\nThe lists have the same elements, so they are equal: <code>list1 == list2</code> is <code>True</code>.</p>\n<p>But then there's a new comparison operator: <code>is</code>. Here <code>list1 is list2</code> is <code>False</code>.\nThat means that regardless of the two lists being equal,\nthey are still two separate, distinct, individual lists.\nAs a result, when you append 4 to <code>list1</code>, only <code>list1</code> changes.</p>\n<p>Now change <code>list2 = [1, 2, 3]</code> to <code>list2 = list1</code> and see what difference it makes.</p>",
          "<p>Now <code>list1 is list2</code> is <code>True</code>, because <em>there is only one list</em>, and the two variables\n<code>list1</code> and <code>list2</code> both refer to that same list. <code>list1.append(4)</code> appends to the one list\nand the result can be seen in both <code>print(list1)</code> and <code>print(list2)</code> because both lines\nare now just different ways of printing the same list.</p>\n<p>I recommend running both versions with Python Tutor to see how it visualises the difference.\nIn the second case, the two variables both have arrows pointing to a single list object.</p>\n<p><code>list2 = list1</code> doesn't create an eternal link between the variables. If you assign a new value\nto <em>either</em> of the variables, e.g. <code>list1 = [7, 8, 9]</code>, the other variable will be unaffected\nand will still point to the original list.</p>\n<p>Basically, an assignment like:</p>\n<pre><code>list2 = &lt;expression&gt;\n</code></pre>\n<p>means 'make the variable <code>list2</code> refer to whatever <code>&lt;expression&gt;</code> evaluates to'.\nIt doesn't make a copy of that value, which is how both variables can end up pointing to the same list.\nBut as we've learned before, <code>list2</code> doesn't remember <code>&lt;expression&gt;</code>, only the value.\nIt doesn't know about other variables.</p>\n<p>You can copy a list with the <code>copy</code> method:</p>\n<pre><code>list2 = list1.copy()\n</code></pre>\n<p>This will make the program behave like the first version again.</p>\n<p>If you come across this kind of problem and you're still having trouble understanding this stuff, read the essay <a href=\"https://nedbatchelder.com/text/names.html\">Facts and myths about Python names and values</a>.</p>"
        ]
      },
      {
        "slug": "ModifyingWhileIterating",
        "title": "Modifying While Iterating",
        "index": 28,
        "step_texts": [
          "<p>Consider this program. It loops through a numbers and removes the ones smaller than 10. Or at least, it tries to. I recommend running it with Python Tutor.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor i in range(len(numbers)):\n    number = numbers[i]\n    if number &lt;= 10:\n        numbers.pop(i)\nprint(numbers)\n</code></pre>\n<p>(remember that <code>numbers.pop(i)</code> removes the element from <code>numbers</code> at index <code>i</code>)</p>\n<p>As it runs, it clearly skips even looking at 7 or 3 and doesn't remove them, and at the end it fails when it tries to access an index that's too high. Can you see why this happens?</p>\n<p>The index variable <code>i</code> runs through the usual values 0, 1, 2, ... as it's supposed to, but as the list changes those are no longer the positions we want. For example in the first iteration <code>i</code> is 0 and <code>number</code> is 10, which gets removed. This shifts the rest of the numbers left one position, so now 7 is in position 0. But then in the next iteration <code>i</code> is 1, and <code>numbers[i]</code> is 8. 7 got skipped. </p>\n<p>We could try writing the program to use <code>remove</code> instead of <code>pop</code> so we don't have to use indices. It even looks nicer this way.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor number in numbers:\n    if number &lt;= 10:\n        numbers.remove(number)\nprint(numbers)\n</code></pre>\n<p>But it turns out this does the same thing, for the same reason. Iterating over a list still goes through the indices under the hood.</p>\n<p>The lesson here is to <strong><em>never modify something while you iterate over it</em></strong>. Keep mutation and looping separate.</p>\n<p>The good news is that there are many ways to solve this. You can instead just loop over a copy, as in:</p>\n<pre><code>for number in numbers.copy():\n</code></pre>\n<p>Now the list being modified and the list being itererated over are separate objects, even if they start out with equal contents.</p>\n<p>Similarly, you could loop over the original and modify a copy:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = numbers.copy()\n\nfor number in numbers:\n    if number &lt;= 10:\n        big_numbers.remove(number)\nprint(big_numbers)\n</code></pre>\n<p>Or you could build up a new list from scratch. In this case, we've already done a similar thing in an exercise:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = []\n\nfor number in numbers:\n    if number &gt; 10:\n        big_numbers.append(number)\nprint(big_numbers)\n</code></pre>"
        ]
      },
      {
        "slug": "IntroducingNestedLoops",
        "title": "Introducing Nested Loops",
        "index": 29,
        "step_texts": [
          "<p>You've seen that the indented body of an <code>if</code> or a loop can contain any kind of statement, including more <code>if</code> statements and loops. In particular a loop can contain another loop. Here's an example:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(number)\n</code></pre>",
          "<p>This is called a <em>nested loop</em>. Nothing about it is really new, it's just worth understanding properly because it can be very useful for writing interesting programs.</p>\n<p>Let's add a line to separate sections of the output:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(number)\n    print('---')\n</code></pre>",
          "<p>Make sure you fully grasp what's going on. <code>print(letter)</code> and <code>print('---')</code> each run 3 times, because their indentation puts them in the <em>outer loop</em>. <code>print(number)</code> is called 3 \u00d7 4 = 12 times, because it's in the <em>inner loop</em> <code>for number in range(4):</code> which has 4 iterations but is itself in the outer loop so it runs 3 times.</p>\n<p>One more tweak:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(letter, number)\n    print('---')\n</code></pre>",
          "<p><code>print(letter, number)</code> gives <code>print</code> two arguments. <code>print</code> can take any number of arguments, and it will output them all on the same line, with spaces in between. If you try using <code>print(letter + ' ' + number)</code> instead you'll get an error, because you can't add strings and numbers. We'll come back to that later.</p>\n<p>Let's put this to use! Suppose you're a teacher and you need to print out all the multiplication tables from 1 to 12 for your students. You don't want to write them manually, but you can write a program to do it for you! Your program output should look like this including the lines of dashes:</p>\n<pre><code>1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n(you get the idea...)\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n</code></pre>",
          "<p>Perfect!</p>\n<p>Next exercise: you're organising a tournament for a game, such as chess or tennis. You have a list of player names:</p>\n<pre><code>players = [\"Alice\", \"Bob\", \"Charlie\"]\n</code></pre>\n<p>Every player is going to play against every other player twice: once where they get the advantage (e.g. by moving or serving first) and once not. Print out all the match combinations like this:</p>\n<pre><code>Alice vs Bob\nAlice vs Charlie\nBob vs Alice\nBob vs Charlie\nCharlie vs Alice\nCharlie vs Bob\n</code></pre>\n<p>Note that \"Alice vs Bob\" and \"Bob vs Alice\" are both in the list, but there's no \"Alice vs Alice\" - we don't want anyone playing with themselves.</p>",
          "<p>Well done! If you'd like a bonus challenge, remove the repetition and only output each pair of players once, e.g:</p>\n<pre><code>Alice vs Bob\nAlice vs Charlie\nBob vs Charlie\n</code></pre>\n<p>For your next exercise, you need to crack a password. You know that it's exactly four letters long and that only a few letters are possible, which you've written down:</p>\n<pre><code>letters = \"ABCD\"\n</code></pre>\n<p>You need to print out all possible passwords:</p>\n<pre><code>AAAA\nAAAB\nAAAC\nAAAD\nAABA\nAABB\n...skipping a few...\nDDDA\nDDDB\nDDDC\nDDDD\n</code></pre>",
          "<p>Wow, you're basically a hacker now!</p>\n<p>One more exercise. Given a size:</p>\n<pre><code>size = 5\n</code></pre>\n<p>Print out an 'upside down' triangle made of the letter <code>O</code> whose sides are as long as the given size, e.g:</p>\n<pre><code>OOOOO\nOOOO\nOOO\nOO\nO\n</code></pre>",
          "<p>Wow, you're an artist too!</p>"
        ]
      }
    ],
    "user": {
      "email": "[email protected]",
      "developerMode": false
    },
    "processing": false,
    "numHints": 0,
    "editorContent": "",
    "messages": [],
    "pastMessages": [],
    "requestingSolution": false,
    "solution": {
      "tokens": [],
      "maskedIndices": [],
      "mask": []
    }
  }
}

Better visual design and CSS in the course

The main part of the site, the course, doesn't look great. It's plain and generic and uses bootstrap. This stuff is really not my strong point so I need someone more skilled to assist. Doing this will hopefully get people more excited about futurecoder and help attract students, contributors, or even donors.

This is specifically about the course. Redesigning the home page is happening in #72

Sandboxing

We will need to figure out how to run user submitted code in the cloud without letting people exploit it to e.g. mine bitcoin. Need to limit:

  • Network access
  • Code size
  • Runtime
  • Memory usage
  • CPU usage
  • Filesystem access

Ideally existing tools should be used as much as possible. For now I just want to note down things that look potentially useful.

https://github.com/containers/bubblewrap
https://repl.it/site/api (currently not available, will need to check periodically)
https://stackoverflow.com/questions/36191589/sandboxing-for-online-judges
https://stackoverflow.com/a/16759352/2482744
https://security.stackexchange.com/questions/150486/what-security-measure-one-should-implement-before-executing-user-uploaded-files

Demonstration that you can't just restrict access to certain python functions in python: https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html

https://doc.pypy.org/en/latest/sandbox.html
https://github.com/dsagal/pynbox

https://docs.python.org/3/library/resource.html We can use this to prevent opening files, starting processes, or using too much memory or CPU. Not sure if it can be circumvented.

https://github.com/pgbovine/PythonSandboxSandbox
https://github.com/cemc/safeexec

Next course chapters

EDIT: replaced by #165

This issue is replacing #23 which contains quite a bit of discussion that newcomers don't need.

Here is an overview of what needs to be written next:

  • Nested lists, under the nested loops chapter
  • Basics of types:
    • Different values have different types
    • These can be revealed with the type() function
    • Types include str, int, float, bool, and list.
    • Different types behave differently, e.g. + and < means different things for each, and each have different methods.
    • Different types are often 'incompatible', e.g. numbers and strings
  • input(). Explain that it always returns a string, and must convert to int when needed.
  • The tic-tac-toe project described in #3, but without using while loops. This means the code should assume valid user input and the user can only play once per program run.
  • while. Start with a simple counter (contrast with for i in range), then another example with a proper condition (any ideas for a compelling example?), then while True. Show how while can be used to improve the tic-tac-toe program.

Styling for account pages

The login and signup pages look like crap, I just got something working as quickly as possible. Apply some bootstrap classes and basic CSS to make them look decent. The files are backend/main/templates/account/login.html and signup.html.

Error in RPC method move_step

User Issue
Email: [email protected]
User Agent: PC / Linux / Chrome 80.0.3987

I was scrolling through the course and noticed that by enabling developer mode, I could scroll from the first section to the very last one (seems like it's looping). When I tried to go forward (back to the first one), I received this error. I'm on Chrome, in a machine running Ubuntu 18.04.

Method: move_step
Request data: {
    "delta": 1
}

Traceback (most recent call last):
  File "/usr/src/app/backend/main/views.py", line 52, in api_view
    result = method(**args)
  File "/usr/src/app/backend/main/views.py", line 178, in move_step
    self.next_page()
  File "/usr/src/app/backend/main/views.py", line 188, in next_page
    self.user.page_slug = page_slugs_list[self.page.index + 1]
IndexError: list index out of range

Redux state

{
  "rpc": {
    "loading": [],
    "error": {
      "traceback": "Traceback (most recent call last):\n  File \"/usr/src/app/backend/main/views.py\", line 52, in api_view\n    result = method(**args)\n  File \"/usr/src/app/backend/main/views.py\", line 178, in move_step\n    self.next_page()\n  File \"/usr/src/app/backend/main/views.py\", line 188, in next_page\n    self.user.page_slug = page_slugs_list[self.page.index + 1]\nIndexError: list index out of range\n",
      "method": "move_step",
      "data": {
        "delta": 1
      }
    }
  },
  "book": {
    "server": {
      "hints": [],
      "step_index": 7,
      "page_index": 29,
      "showEditor": true,
      "showSnoop": true,
      "showPythonTutor": true,
      "showBirdseye": true
    },
    "pages": [
      {
        "title": "Introducing The Shell",
        "step_texts": [
          "<p>At the bottom right of the screen is the <em>shell</em>. This is a place for running small bits of Python code. Just type in some code, press enter, and it'll run! Try it now:</p>\n<ol>\n<li>Click anywhere on the shell (the black area).</li>\n<li>Type <code>1+2</code></li>\n<li>Press the Enter key on your keyboard.</li>\n</ol>",
          "<p>Great! Python evaluated <code>1+2</code> and got the result <code>3</code>, so the shell displays that.</p>\n<p>The shell is probably your most important tool for learning Python, and you should spend lots of time experimenting and exploring in it. Be curious! Constantly ask yourself \"What would happen if I ran X?\" and then immediately answer that question by running it! Never be scared to try something out - if you get something wrong, nothing bad will happen.</p>\n<p>Try doing some more calculations now. You can multiply numbers with <code>*</code>, divide with <code>/</code>, and subtract with <code>-</code>. You can also use parentheses, i.e. <code>(</code> and <code>)</code>.</p>",
          "<p>Excellent! Keep experimenting. When you're ready, click 'Next' to continue.</p>"
        ]
      },
      {
        "title": "Navigating Shell History",
        "step_texts": [
          "<p>Here's a tip: often you will want to re-run a previously entered bit of code, or a slightly modified version of it. You can copy and paste, but that's tedious and gets in the way of experimenting. A better method is to press the Up Arrow key on your keyboard. This will insert the previous line of code into the shell. Keep pressing it to go further back in your history, and if you go too far, press the Down Arrow key to go the other way. Try using it now.</p>"
        ]
      },
      {
        "title": "Introducing Strings",
        "step_texts": [
          "<p>Python lets you do much more than calculate. In fact, we're not going to touch numbers or maths for a while. Instead, we're going to look at <em>strings</em>. Strings are essentially snippets of text. For example, enter the following into the shell, quotes (<code>'</code>) included:</p>\n<pre><code>'hello'\n</code></pre>",
          "<p>The shell simply gives the same thing back because there's nothing to further to calculate. <code>'hello'</code> is simply equal to <code>'hello'</code>.</p>\n<p>A string is a sequence of characters. A character is a single symbol such as a letter, number, punctuation, space, etc. In this case the string contains the 5 characters <code>hello</code>. The quotes are not part of the string - they are there to tell both humans and computers that this is a string consisting of whatever characters are between the quotes.</p>"
        ]
      },
      {
        "title": "Adding Strings",
        "step_texts": [
          "<p>Strings can be added together using <code>+</code>, although this means something very different from adding numbers. For example, try:</p>\n<pre><code>'hello' + 'world'\n</code></pre>",
          "<p>You can see that <code>+</code> combines or joins two strings together end to end. Technically, this is called concatenation.</p>\n<p>Here's an exercise: change the previous code slightly so that the result is the string <code>'hello world'</code>, i.e. with a space between the words.</p>\n<p>By the way, if you get stuck, you can click the lightbulb icon in the bottom right for a hint.</p>",
          "<p>Well done! Any of the following are valid solutions:</p>\n<pre><code>'hello ' + 'world'\n'hello' + ' world'\n'hello' + ' ' + 'world'\n</code></pre>"
        ]
      },
      {
        "title": "Introducing Variables",
        "step_texts": [
          "<p>To make interesting programs, we can't always manipulate the same values. We need a way to refer to values that are unknown ahead of time and can change - values that can vary. These are called <em>variables</em>.</p>\n<p>Run this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>",
          "<p>This creates a variable with the name <code>word</code> that refers to the string value <code>'Hello'</code>.</p>\n<p>Check now that this is true by simply running <code>word</code> in the shell by itself.</p>",
          "<p>Good. For comparison, run <code>'word'</code> in the shell by itself, with the quotes.</p>",
          "<p>As you can see, the quotes make all the difference. <code>'word'</code> is literally just <code>'word'</code>, hence it's technically called a <em>string literal</em>. On the other hand, <code>word</code> is a variable, whose value may be anything.</p>\n<p>Similarly, <code>'sunshine'</code> is <code>'sunshine'</code>, but what's <code>sunshine</code> without quotes?</p>",
          "<p>The answer is that <code>sunshine</code> looks like a variable, so Python tries to look up its value, but since we never defined a variable with that name we get an error.</p>"
        ]
      },
      {
        "title": "Using Variables",
        "step_texts": [
          "<p>Previously we made a variable called <code>word</code> with the value <code>'Hello'</code> with this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>\n<p>Now make a variable called <code>name</code> whose value is another string. The string can be anything...how about your name?</p>",
          "<p>You can use variables in calculations just like you would use literals. For example, try:</p>\n<pre><code>'Hello ' + name\n</code></pre>",
          "<p>Or you can just add variables together. Try:</p>\n<pre><code>word + name\n</code></pre>",
          "<p>Oops...that doesn't look nice. Can you modify the code above so that there's a space between the word and the name?</p>",
          "<p>Perfect!</p>\n<p>Variables can also change their values over time. Right now <code>word</code> has the value <code>'Hello'</code>. You can change its value in the same way that you set it for the first time. Run this:</p>\n<pre><code>word = 'Goodbye'\n</code></pre>",
          "<p>Now observe the effect of this change by running <code>word + ' ' + name</code> again.</p>",
          "<p>Those quotes around strings are getting annoying. Try running this:</p>\n<pre><code>print(word + ' ' + name)\n</code></pre>",
          "<p>Hooray! No more quotes! We'll break down what's happening in this code later. For now just know that <code>print(&lt;something&gt;)</code> displays <code>&lt;something&gt;</code> in the shell. In particular it displays the actual content of strings that we usually care about, instead of a representation of strings that's suitable for code which has things like quotes. The word <code>print</code> here has nothing to do with putting ink on paper.</p>"
        ]
      },
      {
        "title": "Writing Programs",
        "step_texts": [
          "<p>It's time to stop doing everything in the shell. In the top right you can see the <em>editor</em>. This is a place where you can write and run longer programs. The shell is great and you should keep using it to explore, but the editor is where real programs live.</p>\n<p>Copy the program below into the editor, then click the 'Run' button:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nprint(word + ' ' + name)\nword = 'Goodbye'\nprint(word + ' ' + name)\n</code></pre>",
          "<p>Congratulations, you have run your first actual program!</p>\n<p>Take some time to understand this program. Python runs each line one at a time from top to bottom. You should try simulating this process in your head - think about what each line does. See how the value of <code>word</code> was changed and what effect this had. Note that when <code>print</code> is used multiple times, each thing (<code>Hello World</code> and <code>Goodbye World</code> in this case) is printed on its own line.</p>\n<p>Some things to note about programs in the editor:</p>\n<ol>\n<li>The program runs in the shell, meaning that the variables defined in the program now exist in the shell with the last values they had in the program. This lets you explore in the shell after the program completes. For example, <code>name</code> now has the value <code>'World'</code> in the shell.</li>\n<li>Programs run in isolation - they don't depend on any previously defined variables. The shell is reset and all previous variables are cleared. So even though <code>word</code> currently exists in the shell, if you delete the first line of the program and run it again, you'll get an error about <code>word</code> being undefined.</li>\n<li>If you enter code in the shell and it has a value, that value will automatically be displayed. That doesn't happen for programs in the editor - you have to print values. If you remove <code>print()</code> from the program, changing the two lines to just <code>word + ' ' + name</code>, nothing will be displayed.</li>\n</ol>\n<p>I recommend that you check all of these things for yourself.</p>"
        ]
      },
      {
        "title": "Storing Calculations In Variables",
        "step_texts": [
          "<p>Often you will use variables to store the results of calculations. This will help to build more complex programs. For example, try this program:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nsentence = word + ' ' + name\nprint(sentence)\n</code></pre>",
          "<p>Now <code>sentence</code> has the value <code>'Hello World'</code> which can be used multiple times. Note that it will continue to have this value until it is directly reassigned, e.g. with another statement like <code>sentence = &lt;something&gt;</code>. For example, add these two lines to the end of the program:</p>\n<pre><code>word = 'Goodbye'\nprint(sentence)\n</code></pre>",
          "<p>Unlike a spreadsheet where formulas update automatically, a variable like <code>sentence</code> doesn't remember how it was calculated and won't change if the underlying values <code>word</code> or <code>name</code> are changed.</p>"
        ]
      },
      {
        "title": "Introducing For Loops",
        "step_texts": [
          "<p>Good news! You've made it past the boring basics. We can start to write some interesting programs and have a bit of fun. One of the most powerful concepts in programming is the <em>loop</em>, which lets you repeat the same code over and over. Python has two kinds of loop: <code>for</code> loops and <code>while</code> loops. Here is an example of a for loop, try running this program:</p>\n<pre><code>name = 'World'\nfor character in name: print(character)\n</code></pre>",
          "<p>You can read the code almost like normal English:</p>\n<blockquote>\n<p>For each character in the string <code>name</code>, print that character.</p>\n</blockquote>\n<p>Each character is just a normal string. <code>character</code> is a normal variable that is given a new value before the code after the <code>:</code> runs. So the code above is equivalent to:</p>\n<pre><code>name = 'World'\n\ncharacter = 'W'\nprint(character)\n\ncharacter = 'o'\nprint(character)\n\ncharacter = 'r'\nprint(character)\n\ncharacter = 'l'\nprint(character)\n\ncharacter = 'd'\nprint(character)\n</code></pre>\n<p>Note that we could use a different variable name, <code>character</code> just makes it clearer.</p>\n<p>A for loop generally follows this structure:</p>\n<pre><code>for &lt;variable&gt; in &lt;collection&gt;: &lt;code to repeat&gt;\n</code></pre>\n<p>The <code>for</code>, <code>in</code>, and <code>:</code> are all essential.</p>"
        ]
      },
      {
        "title": "Indentation",
        "step_texts": [
          "<p>This example loop:</p>\n<pre><code>for character in name: print(character)\n</code></pre>\n<p>works, but actually it would usually (and should) be written like this:</p>\n<pre><code>for character in name:\n    print(character)\n</code></pre>\n<p>Specifically, the code to be repeated (known as the <em>body</em>) starts on a new line after the colon (<code>:</code>), and it must be <em>indented</em>, i.e. have some spaces before it. The code below without indentation is invalid, run it to see for yourself:</p>\n<pre><code>for character in name:\nprint(character)\n</code></pre>",
          "<p>The spaces are required to tell Python which lines of code belong to the body of the for loop. This is critical when the loop contains several lines, which it often will. For example, run this code:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>",
          "<p>There are two indented lines, so they're both part of the body, so <code>---</code> gets printed after each character. Now try running the same code without the indentation in the last line:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\nprint('---')\n</code></pre>",
          "<p>Since <code>print('---')</code> is not indented, it's not part of the loop body. This means it only runs once, after the whole loop has finished running. Both programs are valid, they just do different things.</p>\n<p>The program below is invalid. Both lines in the loop body are indented, but by different amounts. The first line starts with 4 spaces, the second line starts with 2. Try running it.</p>\n<pre><code>for character in name:\n    print(character)\n  print('---')\n</code></pre>",
          "<p>When you indent, you should always indent by 4 spaces. Any consistent indentation is actually acceptable, but 4 spaces is the convention that almost everyone follows. Note that the editor generally makes this easy for you. For example, if you press the 'Tab' key on your keyboard in the editor, it will insert 4 spaces for you.</p>"
        ]
      },
      {
        "title": "Basic For Loop Exercises",
        "step_texts": [
          "<p>Time for some exercises! Modify this program:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>\n<p>to instead output:</p>\n<pre><code>---W\n---o\n---r\n---l\n---d\n</code></pre>",
          "<p>Splendid! Now write a program which prints <code>name</code> once for each character in <code>name</code>. For example, for <code>name = 'Amy'</code>, it should output:</p>\n<pre><code>Amy\nAmy\nAmy\n</code></pre>\n<p>For <code>name = 'World'</code>, it should output:</p>\n<pre><code>World\nWorld\nWorld\nWorld\nWorld\n</code></pre>\n<p>By the way, you can set <code>name</code> to anything in the first line. Only the rest of the program after that will be checked.</p>",
          "<p>We're making really good progress! You're solving problems and writing new code!\nLet's keep making things more interesting.</p>"
        ]
      },
      {
        "title": "Building Up Strings",
        "step_texts": [
          "<p>Before we look at some more loops, we need to quickly learn another concept. Look at this program:</p>\n<pre><code>hello = 'Hello'\nprint(hello)\nhello = hello + '!'\nprint(hello)\n</code></pre>\n<p>What do you think the line <code>hello = hello + '!'</code> does? What do you think the program will output? Make a prediction, then run it to find out.</p>",
          "<p>Python doesn't care that <code>hello</code> is on both the left and the right of the <code>=</code>, it just does what it would always do if the variables were different: it calculates <code>hello + '!'</code> which at the time is <code>'Hello' + '!'</code> which is <code>'Hello!'</code>, and that becomes the new value of <code>hello</code>. If it helps, you can think of that line as split into two steps:</p>\n<pre><code>temp = hello + '!'\nhello = temp\n</code></pre>\n<p>or:</p>\n<pre><code>temp = hello\nhello = temp + '!'\n</code></pre>\n<p>This is very useful in a loop. Think about what this program will do, then run it:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>By the way, <code>''</code> is called the <em>empty string</em> - a string containing no characters.</p>",
          "<p>The details in the above program are important. What goes wrong if you swap the last two lines and run this program instead?</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    print(line)\n    line = line + char\n</code></pre>",
          "<p>The last character in <code>name</code> only gets added to <code>line</code> at the end of the loop, after <code>print(line)</code> has already run for the last time. So that character and the full <code>name</code> never get printed at the bottom of the triangle.</p>"
        ]
      },
      {
        "title": "Building Up Strings Exercises",
        "step_texts": [
          "<p>Modify this program:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>to add a space after every character in the triangle, so the output looks like this:</p>\n<pre><code>W\nW o\nW o r\nW o r l\nW o r l d\n</code></pre>",
          "<p>Tremendous! Now modify the program so that each line is backwards, like this:</p>\n<pre><code>W\noW\nroW\nlroW\ndlroW\n</code></pre>",
          "<p>Brilliant!</p>\n<p>Code like:</p>\n<pre><code>line = line + char\n</code></pre>\n<p>is so common that Python lets you abbreviate it. This means the same thing:</p>\n<pre><code>line += char\n</code></pre>\n<p>Note that there is no abbreviation for <code>line = char + line</code>.</p>\n<p>Now use <code>+=</code> and a for loop to write your own program which prints <code>name</code> 'underlined', like this:</p>\n<pre><code>World\n-----\n</code></pre>\n<p>There should be one <code>-</code> for each character in <code>name</code>.</p>",
          "<p>Fantastic!</p>\n<p>By the way, when you don't need to use a variable, it's common convention to name that variable <code>_</code> (underscore), e.g. <code>for _ in name:</code>. This doesn't change how the program runs, but it's helpful to readers.</p>\n<p>Let's make this fancier. Extend your program to draw a box around the name, like this:</p>\n<pre><code>+-------+\n| World |\n+-------+\n</code></pre>\n<p>Note that there is a space between the name and the pipes (<code>|</code>).</p>",
          "<p>You're getting good at this! Looks like you need more of a challenge...maybe instead of putting a name in a box, the name should be the box? Write a program that outputs this:</p>\n<pre><code>+World+\nW     W\no     o\nr     r\nl     l\nd     d\n+World+\n</code></pre>",
          "<p>Sweet! You're really getting the hang of this! If you want, here's one more optional bonus challenge. Try writing a program that outputs:</p>\n<pre><code>W\n o\n  r\n   l\n    d\n</code></pre>\n<p>Or don't, it's up to you.</p>"
        ]
      },
      {
        "title": "Basic Terminology",
        "step_texts": [
          "<p>Here's some words you need to know:</p>\n<p>An <strong><em>expression</em></strong> is a piece of code that has a value. For example, in this line of code:</p>\n<pre><code>sentence = 'Hello ' + name\n</code></pre>\n<p>there are three expressions:</p>\n<ol>\n<li><code>'Hello '</code></li>\n<li><code>name</code></li>\n<li><code>'Hello ' + name</code></li>\n</ol>\n<p>By contrast, the full line <code>sentence = ...</code> is a <strong><em>statement</em></strong>. It's a command that tells the computer to perform an action. It has no value of its own. This means, for example, that you can't add statements together. This code is invalid:</p>\n<pre><code>(word = 'Hello') + (name = 'Bob')\n</code></pre>\n<p>Specifically, a statement like <code>sentence = ...</code> where a variable is given a value is called <strong><em>assignment</em></strong> - the value is <em>assigned to</em> the the variable.</p>\n<p>A program is a list of statements which are executed in order. A <code>for</code> loop is a <em>compound statement</em>, meaning it has a body of its own which contains other statements. Most statements will also contain expressions, and expressions can contain other smaller expressions, but expressions cannot contain statements.</p>\n<p>The process of calculating the value of an expression is called <strong><em>evaluation</em></strong> - note how it almost contains the word 'value'. The computer <em>evaluates</em> <code>1 + 2</code> to get the value <code>3</code>.</p>\n<p>The process of executing a loop is called <strong><em>iteration</em></strong>. Code like <code>for char in 'Hello':</code> is <em>iterating over</em> the string <code>'Hello'</code>. The fact that it's possible means that strings are <em>iterable</em>. By contrast, numbers are not iterable, which is exactly what Python will tell you if you try <code>for char in 3:</code>. Each run through the loop is <em>one iteration</em>, so in this example there will be 5 iterations.</p>"
        ]
      },
      {
        "title": "Introducing If Statements",
        "step_texts": [
          "<p>Now we're going to learn how to tell the computer to make decisions and only run code\nunder certain conditions. For this we will need a new type of value. You've seen\nnumbers and strings, now meet <em>booleans</em>. There are only two boolean values:\n<code>True</code> and <code>False</code>. Try this program:</p>\n<pre><code>condition = True\nprint(condition)\ncondition = False\nprint(condition)\n</code></pre>",
          "<p>Booleans are meant to be used inside <em>if statements</em> (sometimes also called <em>conditionals</em>).</p>\n<p>Here is a simple example for you to run:</p>\n<pre><code>if True:\n    print('This gets printed')\n\nif False:\n    print('This does not')\n</code></pre>",
          "<p>Note how the code inside the first <code>if</code> statement ran, but not the second.</p>\n<p>In general, an <code>if</code> statement looks like this:</p>\n<pre><code>if &lt;condition&gt;:\n    &lt;body&gt;\n</code></pre>\n<p>where <code>&lt;condition&gt;</code> is any expression which evaluates to a boolean and <code>&lt;body&gt;</code> is an <strong>indented</strong> list\nof one or more statements. The structure is quite similar to a <code>for</code> loop. Note the colon (<code>:</code>) which\nis essential.</p>\n<p>When the computer sees <code>if &lt;condition&gt;:</code>, it checks if <code>&lt;condition&gt;</code> is <code>True</code>. If it is, it runs the body.\nIf not, it skips it and continues to the rest of the program.</p>\n<p>Here's a more interesting example for you to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence += '!'\nprint(sentence)\n</code></pre>",
          "<p>(Remember that <code>sentence += '!'</code> means <code>sentence = sentence + '!'</code>)</p>\n<p>Change <code>excited = True</code> to <code>excited = False</code> and run the program again to see what the difference is.</p>",
          "<p>Time for an exercise. Modify the program above to include an extra\nboolean parameter <code>confused</code>, so the program should start like this:</p>\n<pre><code>sentence = 'Hello World'\nexcited = False\nconfused = True\n</code></pre>\n<p>(<code>sentence</code> can be any string and the two booleans can be either <code>True</code> or <code>False</code>)</p>\n<p>When <code>confused</code> is true, the printed sentence should have a question mark added to the end.\nIf both <code>confused</code> and <code>excited</code> are true, the sentence should end with <code>!?</code>.</p>",
          "<p>Well done! This program can do 4 different things depending on how you combine <code>excited</code>\nand <code>confused</code>. Try them out if you want.</p>"
        ]
      },
      {
        "title": "Combining Compound Statements",
        "step_texts": [
          "<p>Compound statements like <code>for</code> loops and <code>if</code> statements have bodies which are a list\nof inner statements. Those inner statements can be anything, including other compound statements.\nTry this example of a <code>for</code> loop inside an <code>if</code> statement for when you want to show\nthat you're <em>really</em> excited:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    new_sentence = ''\n    for char in sentence:\n        new_sentence += char\n        new_sentence += '!'\n    sentence = new_sentence\n\nprint(sentence)\n</code></pre>",
          "<p>Note how the body of the <code>if</code> statement (5 lines) is indented as usual, while the body\nof the <code>for</code> loop (2 lines) is indented by an additional 4 spaces in each line to show that\nthose lines are within the <code>for</code> loop. You can see the overall structure of the program\njust by looking at the indentation.</p>\n<p>Alternatively, you can put an <code>if</code> inside a <code>for</code>:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nnew_sentence = ''\nfor char in sentence:\n    new_sentence += char\n    if excited:\n        new_sentence += '!'\n\nsentence = new_sentence\nprint(sentence)\n</code></pre>\n<p>These two programs have the exact same result. However the first one is more efficient as it\nonly iterates over the string if it needs to, since when <code>excited = False</code> nothing changes.</p>"
        ]
      },
      {
        "title": "Understanding Programs With Snoop",
        "step_texts": [
          "<p>Run this program:</p>\n<pre><code>sentence = 'Hello World'\n\ninclude = False\nnew_sentence = ''\nfor char in sentence:\n    if include:\n        new_sentence += char\n    include = True\n\nprint(new_sentence)\n</code></pre>",
          "<p>As you can see, it prints everything but the first character. Take some time to understand how this works.</p>\n<p>In fact, it's time to introduce a new tool to help you understand programs. Click the 'Snoop' button to run the same program while also showing what's happening.</p>",
          "<p>Tada! Scroll to the top of the terminal and let's walk through what snoop is showing you.\nIt starts out very straightforward:</p>\n<pre><code>    1 | sentence = 'Hello World'\n    3 | include = False\n    4 | new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The first lines are simply showing you the lines of the program that the computer ran.\nOn the left is the line number as seen in the editor.</p>\n<p>Running <code>for char in sentence:</code> assigns a value to the variable <code>char</code>, so snoop shows you that value.\nLines starting with <code>......</code> indicate a new variable or a change in the value of an existing variable.\nSuch lines will not be shown when they're redundant, which is why the snoop output doesn't start like this:</p>\n<pre><code>    1 | sentence = 'Hello World'\n ...... sentence = 'Hello World'\n    3 | include = False\n ...... include = False\n    4 | new_sentence = ''\n ...... new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The next two lines are:</p>\n<pre><code>    6 |     if include:\n    8 |     include = True\n</code></pre>\n<p>What's important here is what's not showing: because <code>include</code> is <code>False</code>, line 7 (<code>new_sentence += char</code>) gets skipped. But then <code>include</code> is set to <code>True</code>, so the next iteration of the loop is different:</p>\n<pre><code>    5 | for char in sentence:\n ...... char = 'e'\n    6 |     if include:\n    7 |         new_sentence += char\n .............. new_sentence = 'e'\n</code></pre>\n<p><code>new_sentence += char</code> runs for the first time and the variable <code>new_sentence</code> gets a new value.</p>\n<p>Now modify the program to do the opposite: only print the first character, leave out the rest.</p>",
          "<p>Great job! You're working with increasingly complex programs.</p>"
        ]
      },
      {
        "title": "<code>if</code> and <code>else</code>",
        "step_texts": [
          "<p>An <code>if</code> statement can optionally have an <code>else</code> part. Run this example:</p>\n<pre><code>condition = True\nif condition:\n    print('Yes')\nelse:\n    print('No')\n</code></pre>",
          "<p>Now change the first line to <code>condition = False</code> and run it again.</p>",
          "<p>Think of <code>else</code> as saying 'or else' or 'otherwise'. It means that if the condition in the <code>if</code>\nis false, then the body of the <code>else</code> will run instead. Whether the condition is true or false,\nexactly one of the two bodies will run.</p>\n<p>Here's a more interesting example to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence = sentence.upper()\nelse:\n    sentence = sentence.lower()\nprint(sentence)\n</code></pre>",
          "<p><code>sentence.upper()</code> is a new kind of expression we haven't encountered yet. What's going on here is that <code>sentence</code> is a string and strings have various <em>methods</em> that let you conveniently calculate new values from them, including <code>upper</code> and <code>lower</code>. The names refer to uppercase (capital letters) and lowercase (small letters). <code>'Hello World'.upper()</code> evaluates to <code>'HELLO WORLD'</code>. It doesn't change the contents of <code>sentence</code> though, so you have to assign the new value again with <code>sentence = sentence.upper()</code>.</p>\n<p>Now change <code>excited</code> to <code>False</code> and run it again.</p>",
          "<p>Here's a broken program:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    char = '!'\nsentence += char\n\nprint(sentence)\n</code></pre>\n<p>Can you see the problem? If you run it, everything seems fine. What could go wrong?</p>\n<p>Spoilers below! Have you figured it out?</p>\n<p>What happens if you change <code>excited</code> to <code>False</code>?</p>",
          "<p>If <code>excited</code> is true then <code>char</code> is defined and everything runs fine. But otherwise\n<code>char</code> never gets assigned a value, so trying to use it in <code>sentence += char</code> fails.</p>\n<p>Fix this by adding an <code>else</code> clause to the <code>if</code> so that if <code>excited</code> is false, a full stop (<code>.</code>)\nis added to the end of the sentence instead of an exclamation mark (<code>!</code>).</p>",
          "<p>Time for a challenge!</p>\n<p>Write a program which, given a string <code>sentence</code>, prints a modified version with\nthe same letters, where the first letter is capitalised and the rest are lowercase.\nFor example, the output should be <code>Hello world</code> whether the input <code>sentence = 'hello world'</code>\nor <code>'HELLO WORLD'</code>.</p>",
          "<p>Excellent!!!</p>\n<p>One more exercise, and then you can relax. </p>\n<p>Write a program which prints <code>sentence</code> mockingly, e.g:</p>\n<pre><code>OnE MoRe eXeRcIsE, aNd tHeN YoU CaN ReLaX.\n</code></pre>\n<p>Every second character should be lowercased, the rest should be uppercase.</p>",
          "<p>Perfect! Take a moment to be proud of what you've achieved. Can you feel your brain growing?</p>"
        ]
      },
      {
        "title": "The Equality Operator",
        "step_texts": [
          "<p>There are several ways to obtain booleans without assigning them directly,\nwhich allows you to construct very useful <code>if</code> statements. In particular there\nare many <em>comparison operators</em> which compare the values of two expressions.\nThe most common is the equality operator which checks if two values are equal.\nIt's denoted by two equals signs: <code>==</code>. Try running this:</p>\n<pre><code>print(1 + 2 == 3)\nprint(4 + 5 == 6)\nprint('ab' + 'c' == 'a' + 'bc')\n</code></pre>",
          "<p>As you can see, if the values are equal, the equality expression evaluates to <code>True</code>,\notherwise it's <code>False</code>.</p>\n<p>Note the difference between the equality operator <code>==</code> and a single <code>=</code> which has different meanings,\nparticularly in assignment statements as you've seen them so far. What happens if you try\nremoving a single <code>=</code> from the previous program?</p>",
          "<p>Let's use <code>==</code> in an <code>if</code> statement. In this program, the <code>if</code> body runs only when <code>c</code> is the character <code>'s'</code>. See for yourself.</p>\n<pre><code>name = 'kesha'\nnew_name = ''\nfor c in name:\n    if c == 's':\n        c = '$'\n    new_name += c\n\nprint(new_name)\n</code></pre>",
          "<p>Now extend the program to also replace <code>e</code> with <code>3</code> and <code>a</code> with <code>@</code>.</p>",
          "<p>Well done!</p>"
        ]
      },
      {
        "title": "Introducing <code>elif</code>",
        "step_texts": [
          "<p>Quick biology lesson! Most of the cells in your body contain your full genetic code in DNA.\nThis consists of strands of molecular units called nucleobases which come in four varieties:\nAdenine, Cytosine, Guanine, and Thymine, or ACGT for short.\nSo part of a single strand might be something like:</p>\n<pre><code>AGTAGCGTCCTTAGTTACAGGATGGCTTAT...\n</code></pre>\n<p>This will be paired with another strand where A is replaced by T and vice versa,\nand C is replaced by G and vice versa, e.g:</p>\n<pre><code>TCATCGCAGGAATCAATGTCCTACCGAATA...\n</code></pre>\n<p>The two strands are 'zipped' together into the famous double helix structure,\njoined by the matching A-T and C-G pairs. These pairings are essential in copying DNA when\ncells divide and reproduce. The double helix is unzipped and the code is transcribed\ninto its opposite version to make the copy.</p>\n<p>We're going to repeat that process. Let's try the same kind of program we just wrote:</p>\n<pre><code>dna = 'AGTAGCGTC'\nopposite_dna = ''\nfor char in dna:\n    if char == 'A':\n        char = 'T'\n    if char == 'T':\n        char = 'A'\n    if char == 'G':\n        char = 'C'\n    if char == 'C':\n        char = 'G'\n    opposite_dna += char\n\nprint(opposite_dna)\n</code></pre>",
          "<p>Oh dear, that doesn't quite work. <code>T</code> is changed to <code>A</code> but <code>A</code> isn't changed to anything.\nCan you see why?</p>\n<p>When <code>char == 'A'</code>, then the body <code>char = 'T'</code> does indeed run. But that means that the following\ncondition <code>char == 'T'</code> also passes and so <code>char = 'A'</code> and we're back where we started.\nWe need to only change <code>char</code> from <code>T</code> to <code>A</code> if <code>char</code> wasn't already <code>A</code> to begin with,\nmeaning <code>char == 'A'</code> was <code>False</code>. We can do that with an <code>else</code>, like so:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelse:\n    if char == 'T':\n        char = 'A'\n</code></pre>\n<p>Now fix the program to replace all characters correctly.</p>",
          "<p>Brilliant! You have mimicked what your own cells are constantly doing.</p>\n<p>An <code>if</code> inside an <code>else</code> can be replaced by a single keyword <code>elif</code>. For example,\nthe previous code can be changed to this:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelif char == 'T':\n    char = 'A'\nelif char == 'G':\n    char = 'C'\nelif char == 'C':\n    char = 'G'\n</code></pre>",
          "<p>It's common to have a chain of <code>elif</code> clauses when you want exactly one of many\nbodies to run, like in this case. In general, code like this:</p>\n<pre><code>if X:\n    ...\nelse:\n    if Y:\n        ...\n    else:\n        if Z:\n            ...\n        else:\n            ...\n</code></pre>\n<p>can be rewritten as:</p>\n<pre><code>if X:\n    ...\nelif Y:\n    ...\nelif Z:\n    ...\nelse:\n    ...\n</code></pre>\n<p>which is both shorter and saves you from unpleasant nested indentation.\nThe difference is only cosmetic: once the computer runs this code, it can't\ntell the difference between the two versions.</p>\n<p>Note that <code>elif</code>(s) can optionally be followed by one final <code>else</code>. We didn't include one\nin our DNA example, but we could add one to alert us to any unexpected characters\nin the input, or change <code>elif char == 'C':</code> to <code>else:</code> if we were confident\nabout the input being valid.</p>"
        ]
      },
      {
        "title": "Other Comparison Operators",
        "step_texts": [
          "<p>The opposite of the equals operator <code>==</code> is the <em>not equals</em> operator <code>!=</code>. If you squint it sort of looks like \u2260. It evaluates to <code>True</code> when two values are...not equal. Try it for yourself in the shell.</p>",
          "<p>Here's a cute little program using <code>!=</code>:</p>\n<pre><code>sentence = \"The e key on my keyboard is broken\"\nnew_sentence = ''\nfor c in sentence:\n    if c != 'e':\n        new_sentence += c\nprint(new_sentence)\n</code></pre>",
          "<p>Other handy operators are <code>&lt;</code> (less than) and <code>&gt;</code> (greater than). For example, <code>a &lt; b</code> means \"<code>a</code> is less than <code>b</code>\". Try using one of these in the shell to compare two numbers.</p>",
          "<p>You can also use these operators to compare strings. If you arrange two strings in alphabetical order, the first one is 'less than' the second. See for yourself.</p>",
          "<p>Here's a practical example of <code>&lt;</code> in action for you to try:</p>\n<pre><code>percentage = 73\n\nif percentage &lt; 20:\n    grade = \"F\"\nelif percentage &lt; 40:\n    grade = \"D\"\nelif percentage &lt; 60:\n    grade = \"C\"\nelif percentage &lt; 80:\n    grade = \"B\"\nelse:\n    grade = \"A\"\n\nprint(grade)\n</code></pre>\n<p>Recall that <code>elif percentage &lt; 40</code> after <code>if percentage &lt; 20</code> means \"if the percentage wasn't less than 20 and also is less than 40\", so it will pass for all numbers from 20 to 39 inclusive. Similarly a 'C' is for percentages from 40 to 59, and an 'A' is for any number 80 and up.</p>",
          "<p>Now for an exercise: write a program that takes three variables <code>x1</code>, <code>x2</code>, and <code>x3</code>, and prints the value of the smallest one. So for:</p>\n<pre><code>x1 = 'Charlie'\nx2 = 'Alice'\nx3 = 'Bob'\n</code></pre>\n<p>it should print <code>Alice</code>.</p>",
          "<p>Marvelous!</p>\n<p>There are many ways this could be solved. Here's one solution:</p>\n<pre><code>if x1 &lt; x2:\n    if x1 &lt; x3:\n        first = x1\n    else:\n        first = x3\nelse:\n    if x2 &lt; x3:\n        first = x2\n    else:\n        first = x3\n\nprint(first)\n</code></pre>\n<p>Here's another:</p>\n<pre><code>first = x1\n\nif x2 &lt; first:\n    first = x2\n\nif x3 &lt; first:\n    first = x3\n\nprint(first)\n</code></pre>\n<p>These programs (and yours too) all work equally well with numbers and strings,\nbut not a mixture.</p>\n<p><code>&lt;</code> and <code>&gt;</code> evaluate to False if the compared values are equal. For example,\n3 is not less than 3, so <code>3 &lt; 3</code> and <code>3 &gt; 3</code> are both False.\nTo allow equal values, use <code>&lt;=</code> and <code>&gt;=</code>.\nAgain, if you squint, they look a bit like \u2264 and \u2265.\nNote that the <code>=</code> comes second - there are no such operators as <code>=&lt;</code> or <code>=&gt;</code>.\nTo remember this, read them out loud as \"less than or equal to\"\nand \"greater than or equal to\".</p>\n<p>In summary, the main comparison operators are <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, and <code>&gt;=</code>.\nIf you ever have doubts about what they do, play with them in the shell!</p>"
        ]
      },
      {
        "title": "Introducing Lists",
        "step_texts": [
          "<p>It's time to learn about a powerful new type of value called lists. Here's an example:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor word in words:\n    print(word)\n</code></pre>",
          "<p>A list is a <em>sequence</em> (an ordered collection/container) of any number of values.\nThe values are often referred to as <em>elements</em>.\nThey can be anything: numbers, strings, booleans, even lists! They can also be a mixture of types.</p>\n<p>To create a list directly, like above:</p>\n<ol>\n<li>Write some square brackets: <code>[]</code></li>\n<li>If you don't want an empty list, write some expressions inside to be the elements.</li>\n<li>Put commas (<code>,</code>) between elements to separate them.</li>\n</ol>\n<p>Here's another example of making a list:</p>\n<pre><code>x = 1\nthings = ['Hello', x, x + 3]\nprint(things)\n</code></pre>",
          "<p>As you saw above, lists are <em>iterable</em>, meaning you can iterate over them with a <code>for loop</code>.\nHere's a program that adds up all the numbers in a list:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9]\n\ntotal = 0\nfor number in numbers:\n    total += number\n\nprint(total)\n</code></pre>",
          "<p>Now modify the program so that it can add up a list of strings instead of numbers.\nFor example, given:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n</code></pre>\n<p>it should print:</p>\n<pre><code>Thisisalist\n</code></pre>",
          "<p>Optional bonus challenge: extend the program to insert a separator string <em>between</em> each word.\nFor example, given</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\nseparator = ' - '\n</code></pre>\n<p>it would output:</p>\n<pre><code>This - is - a - list\n</code></pre>\n<p>Lists and strings have a lot in common.\nFor example, you can add two lists to combine them together into a new list.\nYou can also create an empty list that has no elements.\nCheck for yourself:</p>\n<pre><code>numbers = [1, 2] + [3, 4]\nprint(numbers)\nnew_numbers = []\nnew_numbers += numbers\nnew_numbers += [5]\nprint(new_numbers)\n</code></pre>\n<p>With that knowledge, write a program which takes a list of numbers\nand prints a list where each number has been doubled. For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[6, 2, 8, 2, 10, 18, 4, 12, 10]\n</code></pre>",
          "<p>Great!</p>\n<p>When you want to add a single element to the end of a list, instead of:</p>\n<pre><code>some_list += [element]\n</code></pre>\n<p>it's actually more common to write:</p>\n<pre><code>some_list.append(element)\n</code></pre>\n<p>There isn't really a big difference between these, but <code>.append</code>\nwill be more familiar and readable to most people.</p>\n<p>Now use <code>.append</code> to write a program which prints a list containing only the numbers bigger than 5.</p>\n<p>For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[9, 6]\n</code></pre>",
          "<p>Fantastic! We're making great progress.</p>"
        ]
      },
      {
        "title": "Using <code>break</code> to end a loop early",
        "step_texts": [
          "<p>Exercise: write a program which takes a list and a value and checks\nif the list contains the value. For example, given:</p>\n<pre><code>things = ['This', 'is', 'a', 'list']\nthing_to_find = 'is'\n</code></pre>\n<p>it should print <code>True</code>, but for</p>\n<pre><code>thing_to_find = 'other'\n</code></pre>\n<p>it should print <code>False</code>.</p>",
          "<p>Nice!</p>\n<p>A typical solution looks something like this:</p>\n<pre><code>found = False\nfor thing in things:\n    if thing == thing_to_find:\n        found = True\n\nprint(found)\n</code></pre>\n<p>Your solution is probably similar. It's fine, but it's a bit inefficient.\nThat's because it'll loop over the entire list even if it finds the element at the beginning.\nYou can stop any loop using a <code>break</code> statement, like so:</p>\n<pre><code>for thing in things:\n    if thing == thing_to_find:\n        found = True\n        break\n</code></pre>\n<p>This is just as correct but skips unnecessary iterations and checks once it finds the element.\nYou can use snoop to see the difference.</p>"
        ]
      },
      {
        "title": "Getting Elements at a Position",
        "step_texts": [
          "<p>Looping is great, but often you just want to retrieve a single element from the list at a known position.\nHere's how:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nprint(words[0])\nprint(words[1])\nprint(words[2])\nprint(words[3])\n</code></pre>",
          "<p>In general, you can get the element at the position <code>i</code> with <code>words[i]</code>. The operation is called <em>subscripting</em> or <em>indexing</em>, and the position is called the <em>index</em>.</p>\n<p>You've probably noticed that the first index is 0, not 1. In programming, counting starts at 0. It seems weird, but that's how most programming languages do it, and it's generally agreed to be better.</p>\n<p>This also means that the last index in this list of 4 elements is 3. What happens if you try getting an index greater than that?</p>",
          "<p>There you go. <code>words[4]</code> and beyond don't exist, so trying that will give you an error.</p>\n<p>By the way, you can get the number of elements in a list (commonly called the <em>length</em>) using <code>len(words)</code>.\nThat means that the last valid index of the list is <code>len(words) - 1</code>, so the last element is <code>words[len(words) - 1]</code>. Try these for yourself.</p>\n<p>So in general, the valid indices are:</p>\n<pre><code>[0, 1, 2, ..., len(words) - 2, len(words) - 1]\n</code></pre>\n<p>There's a handy built in function to give you these values, called <code>range</code>:</p>\n<pre><code>for i in range(10):\n    print(i)\n</code></pre>",
          "<p><code>range(n)</code> is similar to the list <code>[0, 1, 2, ..., n - 2, n - 1]</code>.\nThis gives us an alternative way to loop over a list:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor index in range(len(words)):\n    print(index)\n    print(words[index])\n</code></pre>",
          "<p>Let's get some exercise! Given a list <code>things</code> and a value <code>to_find</code>,\nprint the first index of <code>to_find</code> in the list, i.e. the lowest number <code>i</code> such that\n<code>things[i]</code> is <code>to_find</code>. For example, for</p>\n<pre><code>things = ['on', 'the', 'way', 'to', 'the', 'store']\nto_find = 'the'\n</code></pre>\n<p>your program should print <code>1</code>.</p>\n<p>You can assume that <code>to_find</code> appears at least once.</p>",
          "<p>Nice!</p>\n<p>By the way, indexing and <code>len()</code> also work on strings. Try them out in the shell.</p>\n<p>Here's another exercise. Given two strings of equal length, e.g:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"World\"\n</code></pre>\n<p>print them vertically side by side, with a space between each character:</p>\n<pre><code>H W\ne o\nl r\nl l\no d\n</code></pre>",
          "<p>Incredible!</p>\n<p>Your solution probably looks something like this:</p>\n<pre><code>for i in range(len(string1)):\n    char1 = string1[i]\n    char2 = string2[i]\n    print(char1 + ' ' + char2)\n</code></pre>\n<p>This doesn't work so well if the strings have different lengths.\nIn fact, it goes wrong in different ways depending on whether <code>string1</code> or <code>string2</code> is longer.\nYour next challenge is to fix this problem by filling in 'missing' characters with spaces.</p>\n<p>For example, for:</p>\n<pre><code>string1 = \"Goodbye\"\nstring2 = \"World\"\n</code></pre>\n<p>output:</p>\n<pre><code>G W\no o\no r\nd l\nb d\ny  \ne\n</code></pre>\n<p>and for:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"Elizabeth\"\n</code></pre>\n<p>output:</p>\n<pre><code>H E\ne l\nl i\nl z\no a\n  b\n  e\n  t\n  h\n</code></pre>",
          "<p>Magnificent! Take a break, you've earned it!</p>"
        ]
      },
      {
        "title": "Terminology: Calling functions and methods",
        "step_texts": [
          "<p>It's time to expand your vocabulary some more.</p>\n<p><code>print</code> and <code>len</code> are <strong><em>functions</em></strong>. See for yourself:</p>\n<pre><code>print(len)\nprint(print)\n</code></pre>",
          "<p>An expression like <code>len(things)</code> or <code>print(things)</code> is a function <strong><em>call</em></strong> - when you write that, you are <strong><em>calling</em></strong> the function <code>len</code> or <code>print</code>. The fact that this is possible means that functions are <strong><em>callable</em></strong>:</p>\n<pre><code>print(callable(len))\n</code></pre>",
          "<p>Most things are not callable, so trying to call them will give you an error:</p>\n<pre><code>f = 'a string'\nprint(callable(f))\nf()\n</code></pre>",
          "<p>In the call <code>len(things)</code>, <code>things</code> is an <strong><em>argument</em></strong>. Sometimes you will also see the word <strong><em>parameter</em></strong>, which means basically the same thing as argument. It's a bit like you're giving the argument to the function - specifically we say that the argument <code>things</code> is <em>passed</em> to <code>len</code>, and <code>len</code> <em>accepts</em> or <em>receives</em> the argument.</p>\n<p><code>len(things)</code> will evaluate to a number such as 3, in which case we say that <code>len</code> <strong><em>returned</em></strong> 3.</p>\n<p>All calls have to return something...even if it's nothing. For example, <code>print</code>'s job is to display something on screen, not to return a useful value. So it returns something useless instead:</p>\n<pre><code>things = [1, 2, 3]\nlength = len(things)\nprinted = print(length)\nprint(printed)\n</code></pre>",
          "<p><code>None</code> is a special 'null' value which can't do anything interesting. It's a common placeholder that represents the lack of a real useful value. Functions that don't want to return anything return <code>None</code> by default. If you see an error message about <code>None</code> or <code>NoneType</code>, it often means you assigned the wrong thing to a variable:</p>\n<pre><code>things = print([1, 2, 3])\nlength = len(things)\n</code></pre>",
          "<p>A <strong><em>method</em></strong> is a function which belongs to a type, and can be called on all values of that type using <code>.</code>. For example, <code>upper</code> and <code>lower</code> are methods of strings, which are called with e.g. <code>word.upper()</code>:</p>\n<pre><code>word = 'Hello'\nprint(word.upper)\nprint(word.upper())\n</code></pre>",
          "<p>Another example is that <code>append</code> is a method of lists. But you can't use <code>.upper</code> on a list or <code>.append</code> on a string:</p>\n<pre><code>word = 'Hello'\nword.append('!')\n</code></pre>",
          "<p>The word 'attribute' in the error message refers to the use of <code>.</code> - the error actually comes just from <code>word.append</code>, without even a call.</p>"
        ]
      },
      {
        "title": "Functions And Methods For Lists",
        "step_texts": [
          "<p>Let's review how to work with lists. Suppose we have a list <code>nums = [1, 2, 3]</code>. You can use:</p>\n<ul>\n<li><strong><code>append</code></strong>: Add an element to the end of the list. <code>nums.append(4)</code> changes the list to <code>[1, 2, 3, 4]</code>.</li>\n<li><strong><code>len</code></strong>: Returns the number of elements. <code>len(nums)</code> is <code>3</code>.</li>\n<li><strong><code>range</code></strong>: <code>range(n)</code> is an object similar to the list of numbers from 0 to <code>n - 1</code>. In particular, <code>range(len(nums))</code> is like <code>[0, 1, 2]</code>.</li>\n<li><strong><code>subscripting</code></strong>: Get a value at an index. <code>nums[0]</code> is 1, <code>nums[1]</code> is 2, <code>nums[2]</code> is 3.</li>\n<li><strong><code>+</code></strong>: Concatenates lists. <code>nums + [4, 5]</code> is <code>[1, 2, 3, 4, 5]</code>.</li>\n</ul>\n<p>Here's some new things. Try them out in the shell.</p>\n<ul>\n<li><strong><code>subscript assignment</code></strong>: Set a value at an index. <code>nums[0] = 9</code> changes the list to <code>[9, 2, 3]</code>.</li>\n<li><strong><code>join</code></strong>: Add a list of strings with a separator in between. This is a method of strings (the separator) which takes an iterable of strings as an argument. <code>'--'.join(['apples', 'oranges', 'bananas'])</code> returns <code>'apples--oranges--bananas'</code>. You can also use an empty string if you don't want a separator, e.g. <code>''.join(['apples', 'oranges', 'bananas'])</code> returns <code>'applesorangesbananas'</code>. </li>\n<li><strong><code>sum</code></strong>: Add a list of numbers. <code>sum(nums)</code> is 6.</li>\n<li><strong><code>in</code></strong>: A comparison operator that checks if a value is in a list. <code>2 in nums</code> is <code>True</code>, but <code>4 in nums</code> is <code>False</code>.</li>\n<li><strong><code>index</code></strong>: Returns the first index of a value in a list. <code>[7, 8, 9, 8].index(8)</code> is 1. Raises an error if the value isn't there.</li>\n</ul>\n<p>You may recognise some of these from your exercises. I assure you that those exercises were not pointless, as you've now learned valuable fundamental skills. For example, you can use <code>in</code> to check if a list contains 5, but there's no similarly easy way to check for a number bigger than 5.</p>\n<p>It's useful to know these functions, but it's not easy to learn them all, and there's many more. A more important skill is being able to look things up. For example, here are some typical ways you might Google the above functions if you forgot their names:</p>\n<ul>\n<li><code>append</code><ul>\n<li>python add element to list</li>\n<li>python add item at end of list</li>\n</ul>\n</li>\n<li><code>len</code><ul>\n<li>python size of list</li>\n<li>python number of elements in list</li>\n<li>python how many characters in string</li>\n</ul>\n</li>\n<li><code>join</code><ul>\n<li>python combine list of strings with separator</li>\n<li>python add together list of strings with string in between</li>\n</ul>\n</li>\n<li><code>sum</code><ul>\n<li>python add list of numbers</li>\n<li>python total of numbers</li>\n</ul>\n</li>\n<li><code>in</code><ul>\n<li>python check if list contains value</li>\n<li>python test if list has element</li>\n</ul>\n</li>\n<li><code>index</code><ul>\n<li>python get position of element</li>\n<li>python get index of value</li>\n</ul>\n</li>\n</ul>\n<p>Let's practice this skill now. Find a function/method that returns the value in a list which is bigger than any other value. For example, given the list <code>[21, 55, 4, 91, 62, 49]</code>, it will return <code>91</code>. You should write the answer in the shell as a single small expression. For example, if you were looking for the function <code>sum</code>, you could write <code>sum([21, 55, 4, 91, 62, 49])</code>. Don't solve this manually with a loop.</p>",
          "<p>Good find! Let's do one more. If you have a list:</p>\n<pre><code>nums = [1, 2, 3, 4, 5]\n</code></pre>\n<p>You could write <code>nums.append(9)</code> and <code>nums</code> would change to:</p>\n<pre><code>[1, 2, 3, 4, 5, 9]\n</code></pre>\n<p>But suppose you don't want the 9 to be at the end, you want it to go between the second and third elements:</p>\n<pre><code>[1, 2, 9, 3, 4, 5]\n</code></pre>\n<p>Call the right function/method in the shell to do that.</p>",
          "<p>Perfect!</p>\n<p>It can also be useful to Google things like \"python list tutorial\", e.g. if:</p>\n<ul>\n<li>Googling a specific method has failed so you want to find it manually.</li>\n<li>You're still confused about lists after this course.</li>\n<li>It's been a while since you learned about lists and you need a reminder.</li>\n<li>You're struggling to solve a problem with lists and you need to go back to basics and strengthen your foundations.</li>\n</ul>\n<p>There are also ways to find information without any googling. Try <code>dir([])</code> in the shell.</p>",
          "<p><code>dir()</code> returns a list of the argument's attributes, which are mostly methods. Many will start with <code>__</code> which you can ignore for now - scroll to the end of the list and you'll see some familiar methods.</p>\n<p>Here are a few more useful functions/methods. Suppose <code>nums = [28, 99, 10, 81, 59, 64]</code></p>\n<ul>\n<li><strong><code>sorted</code></strong>: Takes an iterable and returns a list of the elements in order. <code>sorted(nums)</code> returns <code>[10, 28, 59, 64, 81, 99]</code>.</li>\n<li><strong><code>pop</code></strong>: Removes and returns an element at a given index. <code>nums.pop(3)</code> removes <code>nums[3]</code> (<code>81</code>) from the list and returns it. Without an argument, i.e. just <code>nums.pop()</code>, it will remove and return the last element.</li>\n<li><strong><code>remove</code></strong>: Removes the first occurrence of the given element. <code>nums.remove(10)</code> will leave <code>nums</code> as <code>[28, 99, 81, 59, 64]</code>. Raises an error if the value doesn't exist. Equivalent to <code>nums.pop(nums.index(10))</code>.</li>\n<li><strong><code>count</code></strong>: Returns the number of times the argument appears in the list. <code>[1, 2, 3, 2, 7, 2, 5].count(2)</code> is 3.</li>\n</ul>\n<p>You've already seen that <code>len</code> and subscripting work with strings, a bit as if strings are lists of characters. Strings also support some of the new methods we've learned, not just for characters but for any substring. For example:</p>\n<ul>\n<li><code>'the' in 'feed the dog and the cat'</code> is <code>True</code></li>\n<li><code>'feed the dog and the cat'.count('the')</code> is 2</li>\n<li><code>'feed the dog and the cat'.index('the')</code> is 5</li>\n</ul>\n<p>Note that in most cases, methods which modify a list in place (<code>append</code>, <code>insert</code>, <code>remove</code>) merely return <code>None</code>, while the remaining functions/methods return a new useful value without changing the original argument. The only exception is the <code>pop</code> method.</p>\n<p>Modifying a value directly is called <em>mutation</em> - types of values which can be mutated are <em>mutable</em>, while those that can't are <em>immutable</em>. Strings are immutable - they don't have any methods like <code>append</code> or even subscript assignment. You simply can't change a string - you can only create new strings and use those instead. That means that this is a useless statement on its own:</p>\n<pre><code>word.upper()\n</code></pre>\n<p>The string referred to by <code>word</code> isn't modified, instead <code>word.upper()</code> returned a new string which was immediately discarded. If you want to change the value that <code>word</code> refers to, you have to assign a new value to the variable:</p>\n<pre><code>word = word.upper()\n</code></pre>\n<p>Or you can use <code>word.upper()</code> immediately in a larger expression, e.g.</p>\n<pre><code>if word.lower() == 'yes':\n</code></pre>"
        ]
      },
      {
        "title": "Understanding Programs With Python Tutor",
        "step_texts": [
          "<p>It's time to learn about another tool to explore programs. Put some code in the editor and then click the new \"Python Tutor\" button. Here's some example code if you want:</p>\n<pre><code>all_numbers = [2, 4, 8, 1, 9, 7]\n\nsmall_numbers = []\nbig_numbers = []\n\nfor number in all_numbers:\n    if number &lt;= 5:\n        small_numbers.append(number)\n    else:\n        big_numbers.append(number)\n\nprint(small_numbers)\nprint(big_numbers)\n</code></pre>\n<p>The button will open a new tab with a visualisation from <a href=\"http://pythontutor.com\">pythontutor.com</a>.\nThere you can navigate through the program step by step with the \"Prev\" or \"Next\" buttons, or drag\nthe slider left or right. You can also see the values of variables on the right.</p>"
        ]
      },
      {
        "title": "<code>==</code> vs <code>is</code>",
        "step_texts": [
          "<p>It's time to learn some technical details that are often misunderstood and lead to errors.\nRun this program:</p>\n<pre><code>list1 = [1, 2, 3]\nlist2 = [1, 2, 3]\n\nprint(list1)\nprint(list2)\nprint(list1 == list2)\n\nprint(list1 is list2)\n\nlist1.append(4)\n\nprint(list1)\nprint(list2)\n</code></pre>",
          "<p>This program is quite straightforward and mostly consists of things you're familiar with.\nWe create two variables which refer to lists.\nThe lists have the same elements, so they are equal: <code>list1 == list2</code> is <code>True</code>.</p>\n<p>But then there's a new comparison operator: <code>is</code>. Here <code>list1 is list2</code> is <code>False</code>.\nThat means that regardless of the two lists being equal,\nthey are still two separate, distinct, individual lists.\nAs a result, when you append 4 to <code>list1</code>, only <code>list1</code> changes.</p>\n<p>Now change <code>list2 = [1, 2, 3]</code> to <code>list2 = list1</code> and see what difference it makes.</p>",
          "<p>Now <code>list1 is list2</code> is <code>True</code>, because <em>there is only one list</em>, and the two variables\n<code>list1</code> and <code>list2</code> both refer to that same list. <code>list1.append(4)</code> appends to the one list\nand the result can be seen in both <code>print(list1)</code> and <code>print(list2)</code> because both lines\nare now just different ways of printing the same list.</p>\n<p>I recommend running both versions with Python Tutor to see how it visualises the difference.\nIn the second case, the two variables both have arrows pointing to a single list object.</p>\n<p><code>list2 = list1</code> doesn't create an eternal link between the variables. If you assign a new value\nto <em>either</em> of the variables, e.g. <code>list1 = [7, 8, 9]</code>, the other variable will be unaffected\nand will still point to the original list.</p>\n<p>Basically, an assignment like:</p>\n<pre><code>list2 = &lt;expression&gt;\n</code></pre>\n<p>means 'make the variable <code>list2</code> refer to whatever <code>&lt;expression&gt;</code> evaluates to'.\nIt doesn't make a copy of that value, which is how both variables can end up pointing to the same list.\nBut as we've learned before, <code>list2</code> doesn't remember <code>&lt;expression&gt;</code>, only the value.\nIt doesn't know about other variables.</p>\n<p>You can copy a list with the <code>copy</code> method:</p>\n<pre><code>list2 = list1.copy()\n</code></pre>\n<p>This will make the program behave like the first version again.</p>\n<p>If you come across this kind of problem and you're still having trouble understanding this stuff, read the essay <a href=\"https://nedbatchelder.com/text/names.html\">Facts and myths about Python names and values</a>.</p>"
        ]
      },
      {
        "title": "Modifying While Iterating",
        "step_texts": [
          "<p>Consider this program. It loops through a numbers and removes the ones smaller than 10. Or at least, it tries to. I recommend running it with Python Tutor.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor i in range(len(numbers)):\n    number = numbers[i]\n    if number &lt;= 10:\n        numbers.pop(i)\nprint(numbers)\n</code></pre>\n<p>(remember that <code>numbers.pop(i)</code> removes the element from <code>numbers</code> at index <code>i</code>)</p>\n<p>As it runs, it clearly skips even looking at 7 or 3 and doesn't remove them, and at the end it fails when it tries to access an index that's too high. Can you see why this happens?</p>\n<p>The index variable <code>i</code> runs through the usual values 0, 1, 2, ... as it's supposed to, but as the list changes those are no longer the positions we want. For example in the first iteration <code>i</code> is 0 and <code>number</code> is 10, which gets removed. This shifts the rest of the numbers left one position, so now 7 is in position 0. But then in the next iteration <code>i</code> is 1, and <code>numbers[i]</code> is 8. 7 got skipped. </p>\n<p>We could try writing the program to use <code>remove</code> instead of <code>pop</code> so we don't have to use indices. It even looks nicer this way.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor number in numbers:\n    if number &lt;= 10:\n        numbers.remove(number)\nprint(numbers)\n</code></pre>\n<p>But it turns out this does the same thing, for the same reason. Iterating over a list still goes through the indices under the hood.</p>\n<p>The lesson here is to <strong><em>never modify something while you iterate over it</em></strong>. Keep mutation and looping separate.</p>\n<p>The good news is that there are many ways to solve this. You can instead just loop over a copy, as in:</p>\n<pre><code>for number in numbers.copy():\n</code></pre>\n<p>Now the list being modified and the list being itererated over are separate objects, even if they start out with equal contents.</p>\n<p>Similarly, you could loop over the original and modify a copy:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = numbers.copy()\n\nfor number in numbers:\n    if number &lt;= 10:\n        big_numbers.remove(number)\nprint(big_numbers)\n</code></pre>\n<p>Or you could build up a new list from scratch. In this case, we've already done a similar thing in an exercise:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = []\n\nfor number in numbers:\n    if number &gt; 10:\n        big_numbers.append(number)\nprint(big_numbers)\n</code></pre>"
        ]
      },
      {
        "title": "Introducing Nested Loops",
        "step_texts": [
          "<p>You've seen that the indented body of an <code>if</code> or a loop can contain any kind of statement, including more <code>if</code> statements and loops. In particular a loop can contain another loop. Here's an example:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(number)\n</code></pre>",
          "<p>This is called a <em>nested loop</em>. Nothing about it is really new, it's just worth understanding properly because it can be very useful for writing interesting programs.</p>\n<p>Let's add a line to separate sections of the output:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(number)\n    print('---')\n</code></pre>",
          "<p>Make sure you fully grasp what's going on. <code>print(letter)</code> and <code>print('---')</code> each run 3 times, because their indentation puts them in the <em>outer loop</em>. <code>print(number)</code> is called 3 \u00d7 4 = 12 times, because it's in the <em>inner loop</em> <code>for number in range(4):</code> which has 4 iterations but is itself in the outer loop so it runs 3 times.</p>\n<p>One more tweak:</p>\n<pre><code>for letter in \"ABC\":\n    print(letter)\n    for number in range(4):\n        print(letter, number)\n    print('---')\n</code></pre>",
          "<p><code>print(letter, number)</code> gives <code>print</code> two arguments. <code>print</code> can take any number of arguments, and it will output them all on the same line, with spaces in between. If you try using <code>print(letter + ' ' + number)</code> instead you'll get an error, because you can't add strings and numbers. We'll come back to that later.</p>\n<p>Let's put this to use! Suppose you're a teacher and you need to print out all the multiplication tables from 1 to 12 for your students. You don't want to write them manually, but you can write a program to do it for you! Your program output should look like this including the lines of dashes:</p>\n<pre><code>1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n(you get the idea...)\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n</code></pre>",
          "<p>Perfect!</p>\n<p>Next exercise: you're organising a tournament for a game, such as chess or tennis. You have a list of player names:</p>\n<pre><code>players = [\"Alice\", \"Bob\", \"Charlie\"]\n</code></pre>\n<p>Every player is going to play against every other player twice: once where they get the advantage (e.g. by moving or serving first) and once not. Print out all the match combinations like this:</p>\n<pre><code>Alice vs Bob\nAlice vs Charlie\nBob vs Alice\nBob vs Charlie\nCharlie vs Alice\nCharlie vs Bob\n</code></pre>\n<p>Note that \"Alice vs Bob\" and \"Bob vs Alice\" are both in the list, but there's no \"Alice vs Alice\" - we don't want anyone playing with themselves.</p>",
          "<p>Well done! If you'd like a bonus challenge, remove the repetition and only output each pair of players once, e.g:</p>\n<pre><code>Alice vs Bob\nAlice vs Charlie\nBob vs Charlie\n</code></pre>\n<p>For your next exercise, you need to crack a password. You know that it's exactly four letters long and that only a few letters are possible, which you've written down:</p>\n<pre><code>letters = \"ABCD\"\n</code></pre>\n<p>You need to print out all possible passwords:</p>\n<pre><code>AAAA\nAAAB\nAAAC\nAAAD\nAABA\nAABB\n...skipping a few...\nDDDA\nDDDB\nDDDC\nDDDD\n</code></pre>",
          "<p>Wow, you're basically a hacker now!</p>\n<p>One more exercise. Given a size:</p>\n<pre><code>size = 5\n</code></pre>\n<p>Print out an 'upside down' triangle made of the letter <code>O</code> whose sides are as long as the given size, e.g:</p>\n<pre><code>OOOOO\nOOOO\nOOO\nOO\nO\n</code></pre>",
          "<p>Wow, you're an artist too!</p>"
        ]
      }
    ],
    "user": {
      "email": "[email protected]",
      "developerMode": true
    },
    "processing": false,
    "numHints": 0,
    "editorContent": "",
    "messages": [],
    "pastMessages": [],
    "showingPageIndex": 29,
    "requestingSolution": false,
    "solution": {
      "tokens": [],
      "maskedIndices": [],
      "mask": []
    }
  }
}

Swap variables exercise

Maybe we should add an exercise at the end of the variables chapter where users have to swap variables in the classic way:

x = 'x'
y = 'y'

z = x
x = y
y = z

print(x)
print(y)

Getting this right would reinforce their understanding of variables. However it's quite tricky for a beginner, so I think we should make it easier for them. There's many possible ways to do this. One possibility is to give them a bunch of possible lines to choose from:

x = x
x = y
x = z
y = x
y = y
y = z
z = x
z = y
z = z

and they have to pick the ones to put in the middle to solve the problem. Chances are they will first try x = y; y = x and when that doesn't work they realise the z lines are actually there for a reason. Thoughts?

Distributed architecture

While the web server handles all kinds of requests, it delegates running user code to the 'workers'. Each user has their own process running somewhere. Note that we don't simply have a pool of worker processes to which tasks are submitted using something like celery - that would work if we only ran isolated programs, but users need to be able to interact with a shell and use input().

The worker processes are managed by a 'master', a simple Flask server which directs requests from the web server to the correct user process. Currently there can only be one master. We need a system which:

  • Allows several masters, one per machine/container/instance/dyno, each with a distinct address.
  • Keeps track of which user process is on which machine (if any) so that the web server knows where to send code requests.
  • Scales up when needed (available CPU/memory are running low on existing machines) by starting a new machine with its own master and registering that new master globally.
  • Starts and stops processes strategically to keep them concentrated in fewer machines and allow scaling down when possible.

I'm hoping there are existing tools for this kind of stuff, but I have no experience with distributed systems.

It looks like heroku can't handle 'internal' web services, at least not without an enterprise plan, so we will need to choose a new cloud provider. It should be easy to use and have a decent free tier. Maybe Google Cloud?

Tic tac toe

Currently the course only contains isolated bite-sized exercises. Eventually students should work on a larger project. This is one idea for that.

Below is a simple implementation of a game to be played by 2 humans. It's broken up into several small functions which is helpful for many reasons. It could probably be broken up even further. For some functions I've provided several implementations at different levels using different concepts.

This project could also be taken to another level where the user has to implement automatic computer opponents, at least one which is completely random and one which is random except when there is an opportunity to win immediately. The two computer players plus the human player could be implemented as 3 classes in a hierarchy or as a case for higher order functions.

These are the minimal concepts that users will need:

  • Functions
    • At most one argument
    • Return value
      • Return can have different types (None or string)
      • None implicitly returned (although it's easy to add return None at the end of these functions)
    • Reusing functions
  • Lists
    • Indexing
    • Nested lists
  • Loops
    • Nested loop (over nested list)
    • while loop
    • range
  • Comparisons
    • ==
    • !=
  • Boolean operations
    • and
    • or
    • not (depending on how they write things, probably best that they know it anyway)

Here's the code:

def row_winner(board):
    """
    Version that we don't want to allow
    """
    if ['O', 'O', 'O'] in board:
        return 'O'
    if ['X', 'X', 'X'] in board:
        return 'X'


def row_winner(board):
    """
    Basic version
    """
    result = None
    for row in board:
        piece = row[0]
        if piece != None and piece == row[1] and piece == row[2]:
            result = piece
    return result


def row_winner(board):
    """
    Improved version using:
        Ending a loop with return
        Falsiness of None
        Chaining ==
    """
    for row in board:
        piece = row[0]
        if piece and piece == row[1] == row[2]:
            return piece


def column_winner(board):
    """
    This can have a basic version just like row_winner
    This version is like the improved row_winner
    """
    for col in range(3):
        piece = board[0][col]
        if piece and piece == board[1][col] and piece == board[2][col]:
            return piece


def column_winner(board):
    """
    Improved version using:
        enumerate
        Chaining ==
    """
    for col, piece in enumerate(board[0]):
        if piece and piece == board[1][col] == board[2][col]:
            return piece


def column_winner(board):
    """
    Ultimate version :D
    """
    return row_winner(zip(*board))


def diagonal_winner(board):
    piece = board[1][1]
    if (
            (piece == board[0][0] and piece == board[2][2]) or
            (piece == board[0][2] and piece == board[2][0])
    ):
        return piece


def winner(board):
    piece = row_winner(board)
    if piece != None:
        return piece
    else:
        piece = column_winner(board)
        if piece != None:
            return piece
        else:
            piece = diagonal_winner(board)
            if piece != None:
                return piece


def winner(board):
    """
    Improved version using:
        Falsiness of None
        Exiting by return
    """
    piece = row_winner(board)
    if piece:
        return piece

    piece = column_winner(board)
    if piece:
        return piece

    piece = diagonal_winner(board)
    if piece:
        return piece


def winner(board):
    """
    Best version using:
        Actual meaning of or
    """
    return row_winner(board) or column_winner(board) or diagonal_winner(board)


def print_board(board):
    """
    Using print() makes it easier to write this kind of thing
    instead of print(format_board())
    format_board() is easier to test but I wrote this a while back before
    I realised I would be testing user code that uses print() anyway.
    However in theory it might be nice to show the user actual simple tests
    that they are aiming to pass, and teach them a bit about unit testing.
    The other functions can already do this nicely.
    """
    for row in board:
        line = ''
        for c in row:
            if c == None:
                c = ' '
            line += c
        print(line)


def format_board(board):
    """
    Equivalent of print_board above
    Returns something like:

    XOX
     OO
     X
    """
    result = ''
    for row in board:
        for c in row:
            if c == None:
                c = ' '
            result += c
        result += '\n'
    return result


def format_board(board):
    """
    Improved version using:
        range(len())
        Converting int to str for concatenation
        Falsiness of None
        Actual meaning of or

    Returns something like:
     123
    1XOX
    2 OO
    3 X 
    """
    result = ' 123\n'
    for i in range(len(board)):
        row = board[i]
        result += str(i + 1)
        for c in row:
            result += c or ' '
        result += '\n'
    return result


def format_board(board):
    """
    Extreme version using:
        Comprehension (nested)
        join
        enumerate

    Returns something like:
      1 2 3
    1 X|O|X 
      -+-+-
    2  |O|O
      -+-+-
    3  |X| 
    """
    return '  1 2 3\n' + '\n  -+-+-\n'.join(
        str(i + 1) + ' ' + '|'.join(
            c or ' '
            for c in row
        )
        for i, row in enumerate(board)
    )


def get_coordinate(typ):
    result = input(f'Enter {typ}: ')
    while result not in ('1', '2', '3'):
        print('Invalid ' + typ)
        result = input(f'Enter {typ}: ')
    return int(result) - 1


def get_coordinate(typ):
    """
    Improved version using:
        while True
        Ending a loop with return
    """
    while True:
        result = input(f'Enter {typ}: ')
        if result in ('1', '2', '3'):
            return int(result) - 1
        print('Invalid ' + typ)


def get_coordinate(typ):
    """
    Alternative improved version not requiring 'in', using str.isdigit and <=
    """
    while True:
        result = input(f'Enter {typ}: ')
        if result.isdigit():
            result = int(result)
            if 1 <= result and result <= 3:
                return result - 1
        print('Invalid ' + typ)


def get_free_coordinates(board):
    while True:
        row = get_coordinate('row')
        col = get_coordinate('column')
        if board[row][col]:
            print("That spot is taken")
        else:
            return row, col


def next_player(current_player):
    if current_player == 'X':
        return 'O'
    else:
        return 'X'


def main():
    """
    This plays one game. This function could be wrapped
    in a loop that asks if the player wants to play again.
    """
    # Alternatively empty cells could be represented by ' '
    # This makes format_board nicer but makes the best versions
    # of other functions less elegant
    board = [
        [None, None, None],
        [None, None, None],
        [None, None, None],
    ]
    player = 'X'
    for _ in range(9):
        print(format_board(board))
        w = winner(board)
        if w:
            print(w + ' wins!')
            # Or break and have a tracking variable to check for draw
            # Definitely not gonna use for/else
            return
        print(player + ' to play')

        # If the user is not ready for tuple unpacking
        # then this function can just be inlined
        # and the while loop can be ended by break instead of return
        row, col = get_free_coordinates(board)
        board[row][col] = player
        player = next_player(player)

    print(format_board(board))
    print("It's a draw!")


main()

Process dies trying to run Python command on Docker

While runnning locally on Docker, when trying to run 1+2 on "Introducing The Shell", the in-browser command prompt returned:

The process died. Your code probably took too long. Maybe you have an infinite loop?

This was on first install. Now, on second run, I can't seem to reproduce the problem.

Parsons problems, i.e. rearranging shuffled code

An instruction/assessment method which seems to be very effective is Parsons problems, where the student is given complete code but out of order, and they have to rearrange the lines into the correct order. This is easier and less stressful, and allows practicing a concept even if you haven't mastered all of the details.

Some useful links:

I can imagine this being used in two ways:

  • As exercises in specific steps in the course.
  • As a way of 'revealing' the solution to arbitrary exercises. Automatically giving the user a shuffled solution for any exercise is easy. I'm just not sure what the user experience should be. We currently allow the user to reveal the solution bit by bit until they see the whole thing. If we simply replaced this entirely with a Parsons problem, what if the user gets really stuck and can't solve that either? If we add a final button to just show the correctly ordered solution, how do we prevent the temptation to just click that immediately? Is there anything from the existing solution reveal method that's worth keeping? Should we give the user a choice between solution reveal methods?

The simplest way to implement Parsons problems is to just display out of order code and let them copy/type into the editor. We can do that already. This relates a bit to #35.

A fancier solution would be to use https://js-parsons.github.io/ to allow nice dragging and dropping.

I'm keen to hear opinions and ideas, particularly about using Parsons problems to reveal the solution.

Chapter about quotes and f-strings

I'd like to add a chapter, tentatively called "A bit more about strings", after the chapter on lists and before nested loops, with two pages:

  1. Double quotes. So far I've only used single quotes, leaving students probably wondering how to write an apostrophe inside a string. They will learn about escape sequences later. This page should mention that both single and double quotes are allowed and they do the same thing. "abc" == 'abc' (they should actually see this), they both get reduced to single quotes in the shell, and become the same thing when printed. Double quotes are useful when you want your string to contain single quotes and vice versa. All pages prior to this page should only use single quotes, which I think currently isn't the case.
  2. f-strings. In the nested loops chapter I introduce print with multiple arguments which was a bad idea. Instead students should be shown the basics of f-strings and encouraged to use them instead of + in most situations. In particular they should be shown that adding a string and a number doesn't work but f-strings get around this. Then f-strings should be used in following pages where sensible, including modifying existing pages.

@BobAnkh you seemed interested in writing course content. This should be fairly simple, want to give it a go?

test issue

User Issue
Email: [email protected]
User Agent: PC / Mac OS X 10.13.6 / Chrome 80.0.3987

heroku test

Redux state

{
  "rpc": {
    "loading": [],
    "error": null
  },
  "book": {
    "server": {
      "hints": [
        "<p>The code should be almost exactly the same, just make a couple of small changes.</p>",
        "<p>Make sure that the code inside <code>if include:</code> runs at the beginning of the loop, in the first iteration.</p>",
        "<p>That means <code>include</code> should be <code>True</code> at that point.</p>",
        "<p>Make sure that the code inside <code>if include:</code> <em>doesn't</em> run after the first iteration.</p>",
        "<p>That means <code>include</code> should be <code>False</code> after the first iteration.</p>"
      ],
      "page_index": 16,
      "showBirdseye": true,
      "showEditor": true,
      "showPythonTutor": false,
      "showSnoop": true,
      "step_index": 2
    },
    "pages": [
      {
        "step_texts": [
          "<p>At the bottom right of the screen is the <em>shell</em>. This is a place for running small bits of Python code. Just type in some code, press enter, and it'll run! Try it now:</p>\n<ol>\n<li>Click anywhere on the shell (the black area).</li>\n<li>Type <code>1+2</code></li>\n<li>Press the Enter key on your keyboard.</li>\n</ol>",
          "<p>Great! Python evaluated <code>1+2</code> and got the result <code>3</code>, so the shell displays that.</p>\n<p>The shell is probably your most important tool for learning Python, and you should spend lots of time experimenting and exploring in it. Be curious! Constantly ask yourself \"What would happen if I ran X?\" and then immediately answer that question by running it! Never be scared to try something out - if you get something wrong, nothing bad will happen.</p>\n<p>Try doing some more calculations now. You can multiply numbers with <code>*</code>, divide with <code>/</code>, and subtract with <code>-</code>. You can also use parentheses, i.e. <code>(</code> and <code>)</code>.</p>",
          "<p>Excellent! Keep experimenting. When you're ready, click 'Next' to continue.</p>"
        ],
        "title": "Introducing The Shell"
      },
      {
        "step_texts": [
          "<p>Here's a tip: often you will want to re-run a previously entered bit of code, or a slightly modified version of it. You can copy and paste, but that's tedious and gets in the way of experimenting. A better method is to press the Up Arrow key on your keyboard. This will insert the previous line of code into the shell. Keep pressing it to go further back in your history, and if you go too far, press the Down Arrow key to go the other way. Try using it now.</p>"
        ],
        "title": "Navigating Shell History"
      },
      {
        "step_texts": [
          "<p>Python lets you do much more than calculate. In fact, we're not going to touch numbers or maths for a while. Instead, we're going to look at <em>strings</em>. Strings are essentially snippets of text. For example, enter the following into the shell, quotes (<code>'</code>) included:</p>\n<pre><code>'hello'\n</code></pre>",
          "<p>The shell simply gives the same thing back because there's nothing to further to calculate. <code>'hello'</code> is simply equal to <code>'hello'</code>.</p>\n<p>A string is a sequence of characters. A character is a single symbol such as a letter, number, punctuation, space, etc. In this case the string contains the 5 characters <code>hello</code>. The quotes are not part of the string - they are there to tell both humans and computers that this is a string consisting of whatever characters are between the quotes.</p>"
        ],
        "title": "Introducing Strings"
      },
      {
        "step_texts": [
          "<p>Strings can be added together using <code>+</code>, although this means something very different from adding numbers. For example, try:</p>\n<pre><code>'hello' + 'world'\n</code></pre>",
          "<p>You can see that <code>+</code> combines or joins two strings together end to end. Technically, this is called concatenation.</p>\n<p>Here's an exercise: change the previous code slightly so that the result is the string <code>'hello world'</code>, i.e. with a space between the words.</p>\n<p>By the way, if you get stuck, you can click the lightbulb icon in the bottom right for a hint.</p>",
          "<p>Well done! Any of the following are valid solutions:</p>\n<pre><code>'hello ' + 'world'\n'hello' + ' world'\n'hello' + ' ' + 'world'\n</code></pre>"
        ],
        "title": "Adding Strings"
      },
      {
        "step_texts": [
          "<p>To make interesting programs, we can't always manipulate the same values. We need a way to refer to values that are unknown ahead of time and can change - values that can vary. These are called <em>variables</em>.</p>\n<p>Run this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>",
          "<p>This creates a variable with the name <code>word</code> that refers to the string value <code>'Hello'</code>.</p>\n<p>Check now that this is true by simply running <code>word</code> in the shell by itself.</p>",
          "<p>Good. For comparison, run <code>'word'</code> in the shell by itself, with the quotes.</p>",
          "<p>As you can see, the quotes make all the difference. <code>'word'</code> is literally just <code>'word'</code>, hence it's technically called a <em>string literal</em>. On the other hand, <code>word</code> is a variable, whose value may be anything.</p>\n<p>Similarly, <code>'sunshine'</code> is <code>'sunshine'</code>, but what's <code>sunshine</code> without quotes?</p>",
          "<p>The answer is that <code>sunshine</code> looks like a variable, so Python tries to look up its value, but since we never defined a variable with that name we get an error.</p>"
        ],
        "title": "Introducing Variables"
      },
      {
        "step_texts": [
          "<p>Previously we made a variable called <code>word</code> with the value <code>'Hello'</code> with this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>\n<p>Now make a variable called <code>name</code> whose value is another string. The string can be anything...how about your name?</p>",
          "<p>You can use variables in calculations just like you would use literals. For example, try:</p>\n<pre><code>'Hello ' + name\n</code></pre>",
          "<p>Or you can just add variables together. Try:</p>\n<pre><code>word + name\n</code></pre>",
          "<p>Oops...that doesn't look nice. Can you modify the code above so that there's a space between the word and the name?</p>",
          "<p>Perfect!</p>\n<p>Variables can also change their values over time. Right now <code>word</code> has the value <code>'Hello'</code>. You can change its value in the same way that you set it for the first time. Run this:</p>\n<pre><code>word = 'Goodbye'\n</code></pre>",
          "<p>Now observe the effect of this change by running <code>word + ' ' + name</code> again.</p>",
          "<p>Those quotes around strings are getting annoying. Try running this:</p>\n<pre><code>print(word + ' ' + name)\n</code></pre>",
          "<p>Hooray! No more quotes! We'll break down what's happening in this code later. For now just know that <code>print(&lt;something&gt;)</code> displays <code>&lt;something&gt;</code> in the shell. In particular it displays the actual content of strings that we usually care about, instead of a representation of strings that's suitable for code which has things like quotes. The word <code>print</code> here has nothing to do with putting ink on paper.</p>"
        ],
        "title": "Using Variables"
      },
      {
        "step_texts": [
          "<p>It's time to stop doing everything in the shell. In the top right you can see the <em>editor</em>. This is a place where you can write and run longer programs. The shell is great and you should keep using it to explore, but the editor is where real programs live.</p>\n<p>Copy the program below into the editor, then click the 'Run' button:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nprint(word + ' ' + name)\nword = 'Goodbye'\nprint(word + ' ' + name)\n</code></pre>",
          "<p>Congratulations, you have run your first actual program!</p>\n<p>Take some time to understand this program. Python runs each line one at a time from top to bottom. You should try simulating this process in your head - think about what each line does. See how the value of <code>word</code> was changed and what effect this had. Note that when <code>print</code> is used multiple times, each thing (<code>Hello World</code> and <code>Goodbye World</code> in this case) is printed on its own line.</p>\n<p>Some things to note about programs in the editor:</p>\n<ol>\n<li>The program runs in the shell, meaning that the variables defined in the program now exist in the shell with the last values they had in the program. This lets you explore in the shell after the program completes. For example, <code>name</code> now has the value <code>'World'</code> in the shell.</li>\n<li>Programs run in isolation - they don't depend on any previously defined variables. The shell is reset and all previous variables are cleared. So even though <code>word</code> currently exists in the shell, if you delete the first line of the program and run it again, you'll get an error about <code>word</code> being undefined.</li>\n<li>If you enter code in the shell and it has a value, that value will automatically be displayed. That doesn't happen for programs in the editor - you have to print values. If you remove <code>print()</code> from the program, changing the two lines to just <code>word + ' ' + name</code>, nothing will be displayed.</li>\n</ol>\n<p>I recommend that you check all of these things for yourself.</p>"
        ],
        "title": "Writing Programs"
      },
      {
        "step_texts": [
          "<p>Often you will use variables to store the results of calculations. This will help to build more complex programs. For example, try this program:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nsentence = word + ' ' + name\nprint(sentence)\n</code></pre>",
          "<p>Now <code>sentence</code> has the value <code>'Hello World'</code> which can be used multiple times. Note that it will continue to have this value until it is directly reassigned, e.g. with another statement like <code>sentence = &lt;something&gt;</code>. For example, add these two lines to the end of the program:</p>\n<pre><code>word = 'Goodbye'\nprint(sentence)\n</code></pre>",
          "<p>Unlike a spreadsheet where formulas update automatically, a variable like <code>sentence</code> doesn't remember how it was calculated and won't change if the underlying values <code>word</code> or <code>name</code> are changed.</p>"
        ],
        "title": "Storing Calculations In Variables"
      },
      {
        "step_texts": [
          "<p>Good news! You've made it past the boring basics. We can start to write some interesting programs and have a bit of fun. One of the most powerful concepts in programming is the <em>loop</em>, which lets you repeat the same code over and over. Python has two kinds of loop: <code>for</code> loops and <code>while</code> loops. Here is an example of a for loop, try running this program:</p>\n<pre><code>name = 'World'\nfor character in name: print(character)\n</code></pre>",
          "<p>You can read the code almost like normal English:</p>\n<blockquote>\n<p>For each character in the string <code>name</code>, print that character.</p>\n</blockquote>\n<p>Each character is just a normal string. <code>character</code> is a normal variable that is given a new value before the code after the <code>:</code> runs. So the code above is equivalent to:</p>\n<pre><code>name = 'World'\n\ncharacter = 'W'\nprint(character)\n\ncharacter = 'o'\nprint(character)\n\ncharacter = 'r'\nprint(character)\n\ncharacter = 'l'\nprint(character)\n\ncharacter = 'd'\nprint(character)\n</code></pre>\n<p>Note that we could use a different variable name, <code>character</code> just makes it clearer.</p>\n<p>A for loop generally follows this structure:</p>\n<pre><code>for &lt;variable&gt; in &lt;collection&gt;: &lt;code to repeat&gt;\n</code></pre>\n<p>The <code>for</code>, <code>in</code>, and <code>:</code> are all essential.</p>"
        ],
        "title": "Introducing For Loops"
      },
      {
        "step_texts": [
          "<p>This example loop:</p>\n<pre><code>for character in name: print(character)\n</code></pre>\n<p>works, but actually it would usually (and should) be written like this:</p>\n<pre><code>for character in name:\n    print(character)\n</code></pre>\n<p>Specifically, the code to be repeated (known as the <em>body</em>) starts on a new line after the colon (<code>:</code>), and it must be <em>indented</em>, i.e. have some spaces before it. The code below without indentation is invalid, run it to see for yourself:</p>\n<pre><code>for character in name:\nprint(character)\n</code></pre>",
          "<p>The spaces are required to tell Python which lines of code belong to the body of the for loop. This is critical when the loop contains several lines, which it often will. For example, run this code:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>",
          "<p>There are two indented lines, so they're both part of the body, so <code>---</code> gets printed after each character. Now try running the same code without the indentation in the last line:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\nprint('---')\n</code></pre>",
          "<p>Since <code>print('---')</code> is not indented, it's not part of the loop body. This means it only runs once, after the whole loop has finished running. Both programs are valid, they just do different things.</p>\n<p>The program below is invalid. Both lines in the loop body are indented, but by different amounts. The first line starts with 4 spaces, the second line starts with 2. Try running it.</p>\n<pre><code>for character in name:\n    print(character)\n  print('---')\n</code></pre>",
          "<p>When you indent, you should always indent by 4 spaces. Any consistent indentation is actually acceptable, but 4 spaces is the convention that almost everyone follows. Note that the editor generally makes this easy for you. For example, if you press the 'Tab' key on your keyboard in the editor, it will insert 4 spaces for you.</p>"
        ],
        "title": "Indentation"
      },
      {
        "step_texts": [
          "<p>Time for some exercises! Modify this program:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>\n<p>to instead output:</p>\n<pre><code>---W\n---o\n---r\n---l\n---d\n</code></pre>",
          "<p>Splendid! Now write a program which prints <code>name</code> once for each character in <code>name</code>. For example, for <code>name = 'Amy'</code>, it should output:</p>\n<pre><code>Amy\nAmy\nAmy\n</code></pre>\n<p>For <code>name = 'World'</code>, it should output:</p>\n<pre><code>World\nWorld\nWorld\nWorld\nWorld\n</code></pre>\n<p>By the way, you can set <code>name</code> to anything in the first line. Only the rest of the program after that will be checked.</p>",
          "<p>We're making really good progress! You're solving problems and writing new code!\nLet's keep making things more interesting.</p>"
        ],
        "title": "Basic For Loop Exercises"
      },
      {
        "step_texts": [
          "<p>Before we look at some more loops, we need to quickly learn another concept. Look at this program:</p>\n<pre><code>hello = 'Hello'\nprint(hello)\nhello = hello + '!'\nprint(hello)\n</code></pre>\n<p>What do you think the line <code>hello = hello + '!'</code> does? What do you think the program will output? Make a prediction, then run it to find out.</p>",
          "<p>Python doesn't care that <code>hello</code> is on both the left and the right of the <code>=</code>, it just does what it would always do if the variables were different: it calculates <code>hello + '!'</code> which at the time is <code>'Hello' + '!'</code> which is <code>'Hello!'</code>, and that becomes the new value of <code>hello</code>. If it helps, you can think of that line as split into two steps:</p>\n<pre><code>temp = hello + '!'\nhello = temp\n</code></pre>\n<p>or:</p>\n<pre><code>temp = hello\nhello = temp + '!'\n</code></pre>\n<p>This is very useful in a loop. Think about what this program will do, then run it:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>By the way, <code>''</code> is called the <em>empty string</em> - a string containing no characters.</p>",
          "<p>The details in the above program are important. What goes wrong if you swap the last two lines and run this program instead?</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    print(line)\n    line = line + char\n</code></pre>",
          "<p>The last character in <code>name</code> only gets added to <code>line</code> at the end of the loop, after <code>print(line)</code> has already run for the last time. So that character and the full <code>name</code> never get printed at the bottom of the triangle.</p>"
        ],
        "title": "Building Up Strings"
      },
      {
        "step_texts": [
          "<p>Modify this program:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>to add a space after every character in the triangle, so the output looks like this:</p>\n<pre><code>W\nW o\nW o r\nW o r l\nW o r l d\n</code></pre>",
          "<p>Tremendous! Now modify the program so that each line is backwards, like this:</p>\n<pre><code>W\noW\nroW\nlroW\ndlroW\n</code></pre>",
          "<p>Brilliant!</p>\n<p>Code like:</p>\n<pre><code>line = line + char\n</code></pre>\n<p>is so common that Python lets you abbreviate it. This means the same thing:</p>\n<pre><code>line += char\n</code></pre>\n<p>Note that there is no abbreviation for <code>line = char + line</code>.</p>\n<p>Now use <code>+=</code> and a for loop to write your own program which prints <code>name</code> 'underlined', like this:</p>\n<pre><code>World\n-----\n</code></pre>\n<p>There should be one <code>-</code> for each character in <code>name</code>.</p>",
          "<p>Fantastic!</p>\n<p>By the way, when you don't need to use a variable, it's common convention to name that variable <code>_</code> (underscore), e.g. <code>for _ in name:</code>. This doesn't change how the program runs, but it's helpful to readers.</p>\n<p>Let's make this fancier. Extend your program to draw a box around the name, like this:</p>\n<pre><code>+-------+\n| World |\n+-------+\n</code></pre>\n<p>Note that there is a space between the name and the pipes (<code>|</code>).</p>",
          "<p>You're getting good at this! Looks like you need more of a challenge...maybe instead of putting a name in a box, the name should be the box? Write a program that outputs this:</p>\n<pre><code>+World+\nW     W\no     o\nr     r\nl     l\nd     d\n+World+\n</code></pre>",
          "<p>Sweet! You're really getting the hang of this! If you want, here's one more optional bonus challenge. Try writing a program that outputs:</p>\n<pre><code>W\n o\n  r\n   l\n    d\n</code></pre>\n<p>Or don't, it's up to you.</p>"
        ],
        "title": "Building Up Strings Exercises"
      },
      {
        "step_texts": [
          "<p>Here's some words you need to know:</p>\n<p>An <strong><em>expression</em></strong> is a piece of code that has a value. For example, in this line of code:</p>\n<pre><code>sentence = 'Hello ' + name\n</code></pre>\n<p>there are three expressions:</p>\n<ol>\n<li><code>'Hello '</code></li>\n<li><code>name</code></li>\n<li><code>'Hello ' + name</code></li>\n</ol>\n<p>By contrast, the full line <code>sentence = ...</code> is a <strong><em>statement</em></strong>. It's a command that tells the computer to perform an action. It has no value of its own. This means, for example, that you can't add statements together. This code is invalid:</p>\n<pre><code>(word = 'Hello') + (name = 'Bob')\n</code></pre>\n<p>Specifically, a statement like <code>sentence = ...</code> where a variable is given a value is called <strong><em>assignment</em></strong> - the value is <em>assigned to</em> the the variable.</p>\n<p>A program is a list of statements which are executed in order. A <code>for</code> loop is a <em>compound statement</em>, meaning it has a body of its own which contains other statements. Most statements will also contain expressions, and expressions can contain other smaller expressions, but expressions cannot contain statements.</p>\n<p>The process of calculating the value of an expression is called <strong><em>evaluation</em></strong> - note how it almost contains the word 'value'. The computer <em>evaluates</em> <code>1 + 2</code> to get the value <code>3</code>.</p>\n<p>The process of executing a loop is called <strong><em>iteration</em></strong>. Code like <code>for char in 'Hello':</code> is <em>iterating over</em> the string <code>'Hello'</code>. The fact that it's possible means that strings are <em>iterable</em>. By contrast, numbers are not iterable, which is exactly what Python will tell you if you try <code>for char in 3:</code>. Each run through the loop is <em>one iteration</em>, so in this example there will be 5 iterations.</p>"
        ],
        "title": "Basic Terminology"
      },
      {
        "step_texts": [
          "<p>Now we're going to learn how to tell the computer to make decisions and only run code\nunder certain conditions. For this we will need a new type of value. You've seen\nnumbers and strings, now meet <em>booleans</em>. There are only two boolean values:\n<code>True</code> and <code>False</code>. Try this program:</p>\n<pre><code>condition = True\nprint(condition)\ncondition = False\nprint(condition)\n</code></pre>",
          "<p>Booleans are meant to be used inside <em>if statements</em> (sometimes also called <em>conditionals</em>).</p>\n<p>Here is a simple example for you to run:</p>\n<pre><code>if True:\n    print('This gets printed')\n\nif False:\n    print('This does not')\n</code></pre>",
          "<p>Note how the code inside the first <code>if</code> statement ran, but not the second.</p>\n<p>In general, an <code>if</code> statement looks like this:</p>\n<pre><code>if &lt;condition&gt;:\n    &lt;body&gt;\n</code></pre>\n<p>where <code>&lt;condition&gt;</code> is any expression which evaluates to a boolean and <code>&lt;body&gt;</code> is an <strong>indented</strong> list\nof one or more statements. The structure is quite similar to a <code>for</code> loop. Note the colon (<code>:</code>) which\nis essential.</p>\n<p>When the computer sees <code>if &lt;condition&gt;:</code>, it checks if <code>&lt;condition&gt;</code> is <code>True</code>. If it is, it runs the body.\nIf not, it skips it and continues to the rest of the program.</p>\n<p>Here's a more interesting example for you to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence += '!'\nprint(sentence)\n</code></pre>",
          "<p>(Remember that <code>sentence += '!'</code> means <code>sentence = sentence + '!'</code>)</p>\n<p>Change <code>excited = True</code> to <code>excited = False</code> and run the program again to see what the difference is.</p>",
          "<p>Time for an exercise. Modify the program above to include an extra\nboolean parameter <code>confused</code>, so the program should start like this:</p>\n<pre><code>sentence = 'Hello World'\nexcited = False\nconfused = True\n</code></pre>\n<p>(<code>sentence</code> can be any string and the two booleans can be either <code>True</code> or <code>False</code>)</p>\n<p>When <code>confused</code> is true, the printed sentence should have a question mark added to the end.\nIf both <code>confused</code> and <code>excited</code> are true, the sentence should end with <code>!?</code>.</p>",
          "<p>Well done! This program can do 4 different things depending on how you combine <code>excited</code>\nand <code>confused</code>. Try them out if you want.</p>"
        ],
        "title": "Introducing If Statements"
      },
      {
        "step_texts": [
          "<p>Compound statements like <code>for</code> loops and <code>if</code> statements have bodies which are a list\nof inner statements. Those inner statements can be anything, including other compound statements.\nTry this example of a <code>for</code> loop inside an <code>if</code> statement for when you want to show\nthat you're <em>really</em> excited:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    new_sentence = ''\n    for char in sentence:\n        new_sentence += char\n        new_sentence += '!'\n    sentence = new_sentence\n\nprint(sentence)\n</code></pre>",
          "<p>Note how the body of the <code>if</code> statement (5 lines) is indented as usual, while the body\nof the <code>for</code> loop (2 lines) is indented by an additional 4 spaces in each line to show that\nthose lines are within the <code>for</code> loop. You can see the overall structure of the program\njust by looking at the indentation.</p>\n<p>Alternatively, you can put an <code>if</code> inside a <code>for</code>:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nnew_sentence = ''\nfor char in sentence:\n    new_sentence += char\n    if excited:\n        new_sentence += '!'\n\nsentence = new_sentence\nprint(sentence)\n</code></pre>\n<p>These two programs have the exact same result. However the first one is more efficient as it\nonly iterates over the string if it needs to, since when <code>excited = False</code> nothing changes.</p>"
        ],
        "title": "Combining Compound Statements"
      },
      {
        "step_texts": [
          "<p>Run this program:</p>\n<pre><code>sentence = 'Hello World'\n\ninclude = False\nnew_sentence = ''\nfor char in sentence:\n    if include:\n        new_sentence += char\n    include = True\n\nprint(new_sentence)\n</code></pre>",
          "<p>As you can see, it prints everything but the first character. Take some time to understand how this works.</p>\n<p>In fact, it's time to introduce a new tool to help you understand programs. Click the 'Snoop' button to run the same program while also showing what's happening.</p>",
          "<p>Tada! Scroll to the top of the terminal and let's walk through what snoop is showing you.\nIt starts out very straightforward:</p>\n<pre><code>    1 | sentence = 'Hello World'\n    3 | include = False\n    4 | new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The first lines are simply showing you the lines of the program that the computer ran.\nOn the left is the line number as seen in the editor.</p>\n<p>Running <code>for char in sentence:</code> assigns a value to the variable <code>char</code>, so snoop shows you that value.\nLines starting with <code>......</code> indicate a new variable or a change in the value of an existing variable.\nSuch lines will not be shown when they're redundant, which is why the snoop output doesn't start like this:</p>\n<pre><code>    1 | sentence = 'Hello World'\n ...... sentence = 'Hello World'\n    3 | include = False\n ...... include = False\n    4 | new_sentence = ''\n ...... new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The next two lines are:</p>\n<pre><code>    6 |     if include:\n    8 |     include = True\n</code></pre>\n<p>What's important here is what's not showing: because <code>include</code> is <code>False</code>, line 7 (<code>new_sentence += char</code>) gets skipped. But then <code>include</code> is set to <code>True</code>, so the next iteration of the loop is different:</p>\n<pre><code>    5 | for char in sentence:\n ...... char = 'e'\n    6 |     if include:\n    7 |         new_sentence += char\n .............. new_sentence = 'e'\n</code></pre>\n<p><code>new_sentence += char</code> runs for the first time and the variable <code>new_sentence</code> gets a new value.</p>\n<p>Now modify the program to do the opposite: only print the first character, leave out the rest.</p>",
          "<p>Great job! You're working with increasingly complex programs.</p>"
        ],
        "title": "Understanding Programs With Snoop"
      },
      {
        "step_texts": [
          "<p>An <code>if</code> statement can optionally have an <code>else</code> part. Run this example:</p>\n<pre><code>condition = True\nif condition:\n    print('Yes')\nelse:\n    print('No')\n</code></pre>",
          "<p>Now change the first line to <code>condition = False</code> and run it again.</p>",
          "<p>Think of <code>else</code> as saying 'or else' or 'otherwise'. It means that if the condition in the <code>if</code>\nis false, then the body of the <code>else</code> will run instead. Whether the condition is true or false,\nexactly one of the two bodies will run.</p>\n<p>Here's a more interesting example to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence = sentence.upper()\nelse:\n    sentence = sentence.lower()\nprint(sentence)\n</code></pre>",
          "<p><code>sentence.upper()</code> is a new kind of expression we haven't encountered yet. What's going on here is that <code>sentence</code> is a string and strings have various <em>methods</em> that let you conveniently calculate new values from them, including <code>upper</code> and <code>lower</code>. The names refer to uppercase (capital letters) and lowercase (small letters). <code>'Hello World'.upper()</code> evaluates to <code>'HELLO WORLD'</code>. It doesn't change the contents of <code>sentence</code> though, so you have to assign the new value again with <code>sentence = sentence.upper()</code>.</p>\n<p>Now change <code>excited</code> to <code>False</code> and run it again.</p>",
          "<p>Here's a broken program:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    char = '!'\nsentence += char\n\nprint(sentence)\n</code></pre>\n<p>Can you see the problem? If you run it, everything seems fine. What could go wrong?</p>\n<p>Spoilers below! Have you figured it out?</p>\n<p>What happens if you change <code>excited</code> to <code>False</code>?</p>",
          "<p>If <code>excited</code> is true then <code>char</code> is defined and everything runs fine. But otherwise\n<code>char</code> never gets assigned a value, so trying to use it in <code>sentence += char</code> fails.</p>\n<p>Fix this by adding an <code>else</code> clause to the <code>if</code> so that if <code>excited</code> is false, a full stop (<code>.</code>)\nis added to the end of the sentence instead of an exclamation mark (<code>!</code>).</p>",
          "<p>Time for a challenge!</p>\n<p>Write a program which, given a string <code>sentence</code>, prints a modified version with\nthe same letters, where the first letter is capitalised and the rest are lowercase.\nFor example, the output should be <code>Hello world</code> whether the input <code>sentence = 'hello world'</code>\nor <code>'HELLO WORLD'</code>.</p>",
          "<p>Excellent!!!</p>\n<p>One more exercise, and then you can relax. </p>\n<p>Write a program which prints <code>sentence</code> mockingly, e.g:</p>\n<pre><code>OnE MoRe eXeRcIsE, aNd tHeN YoU CaN ReLaX.\n</code></pre>\n<p>Every second character should be lowercased, the rest should be uppercase.</p>",
          "<p>Perfect! Take a moment to be proud of what you've achieved. Can you feel your brain growing?</p>"
        ],
        "title": "<code>if</code> and <code>else</code>"
      },
      {
        "step_texts": [
          "<p>There are several ways to obtain booleans without assigning them directly,\nwhich allows you to construct very useful <code>if</code> statements. In particular there\nare many <em>comparison operators</em> which compare the values of two expressions.\nThe most common is the equality operator which checks if two values are equal.\nIt's denoted by two equals signs: <code>==</code>. Try running this:</p>\n<pre><code>print(1 + 2 == 3)\nprint(4 + 5 == 6)\nprint('ab' + 'c' == 'a' + 'bc')\n</code></pre>",
          "<p>As you can see, if the values are equal, the equality expression evaluates to <code>True</code>,\notherwise it's <code>False</code>.</p>\n<p>Note the difference between the equality operator <code>==</code> and a single <code>=</code> which has different meanings,\nparticularly in assignment statements as you've seen them so far. What happens if you try\nremoving a single <code>=</code> from the previous program?</p>",
          "<p>Let's use <code>==</code> in an <code>if</code> statement. In this program, the <code>if</code> body runs only when <code>c</code> is the character <code>'s'</code>. See for yourself.</p>\n<pre><code>name = 'kesha'\nnew_name = ''\nfor c in name:\n    if c == 's':\n        c = '$'\n    new_name += c\n\nprint(new_name)\n</code></pre>",
          "<p>Now extend the program to also replace <code>e</code> with <code>3</code> and <code>a</code> with <code>@</code>.</p>",
          "<p>Well done!</p>"
        ],
        "title": "The Equality Operator"
      },
      {
        "step_texts": [
          "<p>Quick biology lesson! Most of the cells in your body contain your full genetic code in DNA.\nThis consists of strands of molecular units called nucleobases which come in four varieties:\nAdenine, Cytosine, Guanine, and Thymine, or ACGT for short.\nSo part of a single strand might be something like:</p>\n<pre><code>AGTAGCGTCCTTAGTTACAGGATGGCTTAT...\n</code></pre>\n<p>This will be paired with another strand where A is replaced by T and vice versa,\nand C is replaced by G and vice versa, e.g:</p>\n<pre><code>TCATCGCAGGAATCAATGTCCTACCGAATA...\n</code></pre>\n<p>The two strands are 'zipped' together into the famous double helix structure,\njoined by the matching A-T and C-G pairs. These pairings are essential in copying DNA when\ncells divide and reproduce. The double helix is unzipped and the code is transcribed\ninto its opposite version to make the copy.</p>\n<p>We're going to repeat that process. Let's try the same kind of program we just wrote:</p>\n<pre><code>dna = 'AGTAGCGTC'\nopposite_dna = ''\nfor char in dna:\n    if char == 'A':\n        char = 'T'\n    if char == 'T':\n        char = 'A'\n    if char == 'G':\n        char = 'C'\n    if char == 'C':\n        char = 'G'\n    opposite_dna += char\n\nprint(opposite_dna)\n</code></pre>",
          "<p>Oh dear, that doesn't quite work. <code>T</code> is changed to <code>A</code> but <code>A</code> isn't changed to anything.\nCan you see why?</p>\n<p>When <code>char == 'A'</code>, then the body <code>char = 'T'</code> does indeed run. But that means that the following\ncondition <code>char == 'T'</code> also passes and so <code>char = 'A'</code> and we're back where we started.\nWe need to only change <code>char</code> from <code>T</code> to <code>A</code> if <code>char</code> wasn't already <code>A</code> to begin with,\nmeaning <code>char == 'A'</code> was <code>False</code>. We can do that with an <code>else</code>, like so:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelse:\n    if char == 'T':\n        char = 'A'\n</code></pre>\n<p>Now fix the program to replace all characters correctly.</p>",
          "<p>Brilliant! You have mimicked what your own cells are constantly doing.</p>\n<p>An <code>if</code> inside an <code>else</code> can be replaced by a single keyword <code>elif</code>. For example,\nthe previous code can be changed to this:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelif char == 'T':\n    char = 'A'\nelif char == 'G':\n    char = 'C'\nelif char == 'C':\n    char = 'G'\n</code></pre>",
          "<p>It's common to have a chain of <code>elif</code> clauses when you want exactly one of many\nbodies to run, like in this case. In general, code like this:</p>\n<pre><code>if X:\n    ...\nelse:\n    if Y:\n        ...\n    else:\n        if Z:\n            ...\n        else:\n            ...\n</code></pre>\n<p>can be rewritten as:</p>\n<pre><code>if X:\n    ...\nelif Y:\n    ...\nelif Z:\n    ...\nelse:\n    ...\n</code></pre>\n<p>which is both shorter and saves you from unpleasant nested indentation.\nThe difference is only cosmetic: once the computer runs this code, it can't\ntell the difference between the two versions.</p>\n<p>Note that <code>elif</code>(s) can optionally be followed by one final <code>else</code>. We didn't include one\nin our DNA example, but we could add one to alert us to any unexpected characters\nin the input, or change <code>elif char == 'C':</code> to <code>else:</code> if we were confident\nabout the input being valid.</p>"
        ],
        "title": "Introducing <code>elif</code>"
      },
      {
        "step_texts": [
          "<p>The opposite of the equals operator <code>==</code> is the <em>not equals</em> operator <code>!=</code>. If you squint it sort of looks like \u2260. It evaluates to <code>True</code> when two values are...not equal. Try it for yourself in the shell.</p>",
          "<p>Here's a cute little program using <code>!=</code>:</p>\n<pre><code>sentence = \"The e key on my keyboard is broken\"\nnew_sentence = ''\nfor c in sentence:\n    if c != 'e':\n        new_sentence += c\nprint(new_sentence)\n</code></pre>",
          "<p>Other handy operators are <code>&lt;</code> (less than) and <code>&gt;</code> (greater than). For example, <code>a &lt; b</code> means \"<code>a</code> is less than <code>b</code>\". Try using one of these in the shell to compare two numbers.</p>",
          "<p>You can also use these operators to compare strings. If you arrange two strings in alphabetical order, the first one is 'less than' the second. See for yourself.</p>",
          "<p>Here's a practical example of <code>&lt;</code> in action for you to try:</p>\n<pre><code>percentage = 73\n\nif percentage &lt; 20:\n    grade = \"F\"\nelif percentage &lt; 40:\n    grade = \"D\"\nelif percentage &lt; 60:\n    grade = \"C\"\nelif percentage &lt; 80:\n    grade = \"B\"\nelse:\n    grade = \"A\"\n\nprint(grade)\n</code></pre>\n<p>Recall that <code>elif percentage &lt; 40</code> after <code>if percentage &lt; 20</code> means \"if the percentage wasn't less than 20 and also is less than 40\", so it will pass for all numbers from 20 to 39 inclusive. Similarly a 'C' is for percentages from 40 to 59, and an 'A' is for any number 80 and up.</p>",
          "<p>Now for an exercise: write a program that takes three variables <code>x1</code>, <code>x2</code>, and <code>x3</code>, and prints the value of the smallest one. So for:</p>\n<pre><code>x1 = 'Charlie'\nx2 = 'Alice'\nx3 = 'Bob'\n</code></pre>\n<p>it should print <code>Alice</code>.</p>",
          "<p>Marvelous!</p>\n<p>There are many ways this could be solved. Here's one solution:</p>\n<pre><code>if x1 &lt; x2:\n    if x1 &lt; x3:\n        first = x1\n    else:\n        first = x3\nelse:\n    if x2 &lt; x3:\n        first = x2\n    else:\n        first = x3\n\nprint(first)\n</code></pre>\n<p>Here's another:</p>\n<pre><code>first = x1\n\nif x2 &lt; first:\n    first = x2\n\nif x3 &lt; first:\n    first = x3\n\nprint(first)\n</code></pre>\n<p>These programs (and yours too) all work equally well with numbers and strings,\nbut not a mixture.</p>\n<p><code>&lt;</code> and <code>&gt;</code> evaluate to False if the compared values are equal. For example,\n3 is not less than 3, so <code>3 &lt; 3</code> and <code>3 &gt; 3</code> are both False.\nTo allow equal values, use <code>&lt;=</code> and <code>&gt;=</code>.\nAgain, if you squint, they look a bit like \u2264 and \u2265.\nNote that the <code>=</code> comes second - there are no such operators as <code>=&lt;</code> or <code>=&gt;</code>.\nTo remember this, read them out loud as \"less than or equal to\"\nand \"greater than or equal to\".</p>\n<p>In summary, the main comparison operators are <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, and <code>&gt;=</code>.\nIf you ever have doubts about what they do, play with them in the shell!</p>"
        ],
        "title": "Other Comparison Operators"
      },
      {
        "step_texts": [
          "<p>It's time to learn about a powerful new type of value called lists. Here's an example:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor word in words:\n    print(word)\n</code></pre>",
          "<p>A list is a <em>sequence</em> (an ordered collection/container) of any number of values.\nThe values are often referred to as <em>elements</em>.\nThey can be anything: numbers, strings, booleans, even lists! They can also be a mixture of types.</p>\n<p>To create a list directly, like above:</p>\n<ol>\n<li>Write some square brackets: <code>[]</code></li>\n<li>If you don't want an empty list, write some expressions inside to be the elements.</li>\n<li>Put commas (<code>,</code>) between elements to separate them.</li>\n</ol>\n<p>Here's another example of making a list:</p>\n<pre><code>x = 1\nthings = ['Hello', x, x + 3]\nprint(things)\n</code></pre>",
          "<p>As you saw above, lists are <em>iterable</em>, meaning you can iterate over them with a <code>for loop</code>.\nHere's a program that adds up all the numbers in a list:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9]\n\ntotal = 0\nfor number in numbers:\n    total += number\n\nprint(total)\n</code></pre>",
          "<p>Now modify the program so that it can add up a list of strings instead of numbers.\nFor example, given:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n</code></pre>\n<p>it should print:</p>\n<pre><code>Thisisalist\n</code></pre>",
          "<p>Optional bonus challenge: extend the program to insert a separator string <em>between</em> each word.\nFor example, given</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\nseparator = ' - '\n</code></pre>\n<p>it would output:</p>\n<pre><code>This - is - a - list\n</code></pre>\n<p>Lists and strings have a lot in common.\nFor example, you can add two lists to combine them together into a new list.\nYou can also create an empty list that has no elements.\nCheck for yourself:</p>\n<pre><code>numbers = [1, 2] + [3, 4]\nprint(numbers)\nnew_numbers = []\nnew_numbers += numbers\nnew_numbers += [5]\nprint(new_numbers)\n</code></pre>\n<p>With that knowledge, write a program which takes a list of numbers\nand prints a list where each number has been doubled. For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[6, 2, 8, 2, 10, 18, 4, 12, 10]\n</code></pre>",
          "<p>Great!</p>\n<p>When you want to add a single element to the end of a list, instead of:</p>\n<pre><code>some_list += [element]\n</code></pre>\n<p>it's actually more common to write:</p>\n<pre><code>some_list.append(element)\n</code></pre>\n<p>There isn't really a big difference between these, but <code>.append</code>\nwill be more familiar and readable to most people.</p>\n<p>Now use <code>.append</code> to write a program which prints a list containing only the numbers bigger than 5.</p>\n<p>For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[9, 6]\n</code></pre>",
          "<p>Fantastic! We're making great progress.</p>"
        ],
        "title": "Introducing Lists"
      },
      {
        "step_texts": [
          "<p>Exercise: write a program which takes a list and a value and checks\nif the list contains the value. For example, given:</p>\n<pre><code>things = ['This', 'is', 'a', 'list']\nthing_to_find = 'is'\n</code></pre>\n<p>it should print <code>True</code>, but for</p>\n<pre><code>thing_to_find = 'other'\n</code></pre>\n<p>it should print <code>False</code>.</p>",
          "<p>Nice!</p>\n<p>A typical solution looks something like this:</p>\n<pre><code>found = False\nfor thing in things:\n    if thing == thing_to_find:\n        found = True\n\nprint(found)\n</code></pre>\n<p>Your solution is probably similar. It's fine, but it's a bit inefficient.\nThat's because it'll loop over the entire list even if it finds the element at the beginning.\nYou can stop any loop using a <code>break</code> statement, like so:</p>\n<pre><code>for thing in things:\n    if thing == thing_to_find:\n        found = True\n        break\n</code></pre>\n<p>This is just as correct but skips unnecessary iterations and checks once it finds the element.\nYou can use snoop to see the difference.</p>"
        ],
        "title": "Using <code>break</code> to end a loop early"
      },
      {
        "step_texts": [
          "<p>Looping is great, but often you just want to retrieve a single element from the list at a known position.\nHere's how:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nprint(words[0])\nprint(words[1])\nprint(words[2])\nprint(words[3])\n</code></pre>",
          "<p>In general, you can get the element at the position <code>i</code> with <code>words[i]</code>. The operation is called <em>subscripting</em> or <em>indexing</em>, and the position is called the <em>index</em>.</p>\n<p>You've probably noticed that the first index is 0, not 1. In programming, counting starts at 0. It seems weird, but that's how most programming languages do it, and it's generally agreed to be better.</p>\n<p>This also means that the last index in this list of 4 elements is 3. What happens if you try getting an index greater than that?</p>",
          "<p>There you go. <code>words[4]</code> and beyond don't exist, so trying that will give you an error.</p>\n<p>By the way, you can get the number of elements in a list (commonly called the <em>length</em>) using <code>len(words)</code>.\nThat means that the last valid index of the list is <code>len(words) - 1</code>, so the last element is <code>words[len(words) - 1]</code>. Try these for yourself.</p>\n<p>So in general, the valid indices are:</p>\n<pre><code>[0, 1, 2, ..., len(words) - 2, len(words) - 1]\n</code></pre>\n<p>There's a handy built in function to give you these values, called <code>range</code>:</p>\n<pre><code>for i in range(10):\n    print(i)\n</code></pre>",
          "<p><code>range(n)</code> is similar to the list <code>[0, 1, 2, ..., n - 2, n - 1]</code>.\nThis gives us an alternative way to loop over a list:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor index in range(len(words)):\n    print(index)\n    print(words[index])\n</code></pre>",
          "<p>Let's get some exercise! Given a list <code>things</code> and a value <code>to_find</code>,\nprint the first index of <code>to_find</code> in the list, i.e. the lowest number <code>i</code> such that\n<code>things[i]</code> is <code>to_find</code>. For example, for</p>\n<pre><code>things = ['on', 'the', 'way', 'to', 'the', 'store']\nto_find = 'the'\n</code></pre>\n<p>your program should print <code>1</code>.</p>\n<p>You can assume that <code>to_find</code> appears at least once.</p>",
          "<p>Nice!</p>\n<p>By the way, indexing and <code>len()</code> also work on strings. Try them out in the shell.</p>\n<p>Here's another exercise. Given two strings of equal length, e.g:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"World\"\n</code></pre>\n<p>print them vertically side by side, with a space between each character:</p>\n<pre><code>H W\ne o\nl r\nl l\no d\n</code></pre>",
          "<p>Incredible!</p>\n<p>Your solution probably looks something like this:</p>\n<pre><code>for i in range(len(string1)):\n    char1 = string1[i]\n    char2 = string2[i]\n    print(char1 + ' ' + char2)\n</code></pre>\n<p>This doesn't work so well if the strings have different lengths.\nIn fact, it goes wrong in different ways depending on whether <code>string1</code> or <code>string2</code> is longer.\nYour next challenge is to fix this problem by filling in 'missing' characters with spaces.</p>\n<p>For example, for:</p>\n<pre><code>string1 = \"Goodbye\"\nstring2 = \"World\"\n</code></pre>\n<p>output:</p>\n<pre><code>G W\no o\no r\nd l\nb d\ny  \ne\n</code></pre>\n<p>and for:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"Elizabeth\"\n</code></pre>\n<p>output:</p>\n<pre><code>H E\ne l\nl i\nl z\no a\n  b\n  e\n  t\n  h\n</code></pre>",
          "<p>Magnificent! Take a break, you've earned it!</p>"
        ],
        "title": "Getting Elements at a Position"
      },
      {
        "step_texts": [
          "<p>It's time to expand your vocabulary some more.</p>\n<p><code>print</code> and <code>len</code> are <strong><em>functions</em></strong>. See for yourself:</p>\n<pre><code>print(len)\nprint(print)\n</code></pre>",
          "<p>An expression like <code>len(things)</code> or <code>print(things)</code> is a function <strong><em>call</em></strong> - when you write that, you are <strong><em>calling</em></strong> the function <code>len</code> or <code>print</code>. The fact that this is possible means that functions are <strong><em>callable</em></strong>:</p>\n<pre><code>print(callable(len))\n</code></pre>",
          "<p>Most things are not callable, so trying to call them will give you an error:</p>\n<pre><code>f = 'a string'\nprint(callable(f))\nf()\n</code></pre>",
          "<p>In the call <code>len(things)</code>, <code>things</code> is an <strong><em>argument</em></strong>. Sometimes you will also see the word <strong><em>parameter</em></strong>, which means basically the same thing as argument. It's a bit like you're giving the argument to the function - specifically we say that the argument <code>things</code> is <em>passed</em> to <code>len</code>, and <code>len</code> <em>accepts</em> or <em>receives</em> the argument.</p>\n<p><code>len(things)</code> will evaluate to a number such as 3, in which case we say that <code>len</code> <strong><em>returned</em></strong> 3.</p>\n<p>All calls have to return something...even if it's nothing. For example, <code>print</code>'s job is to display something on screen, not to return a useful value. So it returns something useless instead:</p>\n<pre><code>things = [1, 2, 3]\nlength = len(things)\nprinted = print(length)\nprint(printed)\n</code></pre>",
          "<p><code>None</code> is a special 'null' value which can't do anything interesting. It's a common placeholder that represents the lack of a real useful value. Functions that don't want to return anything return <code>None</code> by default. If you see an error message about <code>None</code> or <code>NoneType</code>, it often means you assigned the wrong thing to a variable:</p>\n<pre><code>things = print([1, 2, 3])\nlength = len(things)\n</code></pre>",
          "<p>A <strong><em>method</em></strong> is a function which belongs to a type, and can be called on all values of that type using <code>.</code>. For example, <code>upper</code> and <code>lower</code> are methods of strings, which are called with e.g. <code>word.upper()</code>:</p>\n<pre><code>word = 'Hello'\nprint(word.upper)\nprint(word.upper())\n</code></pre>",
          "<p>Another example is that <code>append</code> is a method of lists. But you can't use <code>.upper</code> on a list or <code>.append</code> on a string:</p>\n<pre><code>word = 'Hello'\nword.append('!')\n</code></pre>",
          "<p>The word 'attribute' in the error message refers to the use of <code>.</code> - the error actually comes just from <code>word.append</code>, without even a call.</p>"
        ],
        "title": "Terminology: Calling functions and methods"
      },
      {
        "step_texts": [
          "<p>Let's review how to work with lists. Suppose we have a list <code>nums = [1, 2, 3]</code>. You can use:</p>\n<ul>\n<li><strong><code>append</code></strong>: Add an element to the end of the list. <code>nums.append(4)</code> changes the list to <code>[1, 2, 3, 4]</code>.</li>\n<li><strong><code>len</code></strong>: Returns the number of elements. <code>len(nums)</code> is <code>3</code>.</li>\n<li><strong><code>range</code></strong>: <code>range(n)</code> is an object similar to the list of numbers from 0 to <code>n - 1</code>. In particular, <code>range(len(nums))</code> is like <code>[0, 1, 2]</code>.</li>\n<li><strong><code>subscripting</code></strong>: Get a value at an index. <code>nums[0]</code> is 1, <code>nums[1]</code> is 2, <code>nums[2]</code> is 3.</li>\n<li><strong><code>+</code></strong>: Concatenates lists. <code>nums + [4, 5]</code> is <code>[1, 2, 3, 4, 5]</code>.</li>\n</ul>\n<p>Here's some new things. Try them out in the shell.</p>\n<ul>\n<li><strong><code>subscript assignment</code></strong>: Set a value at an index. <code>nums[0] = 9</code> changes the list to <code>[9, 2, 3]</code>.</li>\n<li><strong><code>join</code></strong>: Add a list of strings with a separator in between. This is a method of strings (the separator) which takes an iterable of strings as an argument. <code>'--'.join(['apples', 'oranges', 'bananas'])</code> returns <code>'apples--oranges--bananas'</code>. You can also use an empty string if you don't want a separator, e.g. <code>''.join(['apples', 'oranges', 'bananas'])</code> returns <code>'applesorangesbananas'</code>. </li>\n<li><strong><code>sum</code></strong>: Add a list of numbers. <code>sum(nums)</code> is 6.</li>\n<li><strong><code>in</code></strong>: A comparison operator that checks if a value is in a list. <code>2 in nums</code> is <code>True</code>, but <code>4 in nums</code> is <code>False</code>.</li>\n<li><strong><code>index</code></strong>: Returns the first index of a value in a list. <code>[7, 8, 9, 8].index(8)</code> is 1. Raises an error if the value isn't there.</li>\n</ul>\n<p>You may recognise some of these from your exercises. I assure you that those exercises were not pointless, as you've now learned valuable fundamental skills. For example, you can use <code>in</code> to check if a list contains 5, but there's no similarly easy way to check for a number bigger than 5.</p>\n<p>It's useful to know these functions, but it's not easy to learn them all, and there's many more. A more important skill is being able to look things up. For example, here are some typical ways you might Google the above functions if you forgot their names:</p>\n<ul>\n<li><code>append</code><ul>\n<li>python add element to list</li>\n<li>python add item at end of list</li>\n</ul>\n</li>\n<li><code>len</code><ul>\n<li>python size of list</li>\n<li>python number of elements in list</li>\n<li>python how many characters in string</li>\n</ul>\n</li>\n<li><code>join</code><ul>\n<li>python combine list of strings with separator</li>\n<li>python add together list of strings with string in between</li>\n</ul>\n</li>\n<li><code>sum</code><ul>\n<li>python add list of numbers</li>\n<li>python total of numbers</li>\n</ul>\n</li>\n<li><code>in</code><ul>\n<li>python check if list contains value</li>\n<li>python test if list has element</li>\n</ul>\n</li>\n<li><code>index</code><ul>\n<li>python get position of element</li>\n<li>python get index of value</li>\n</ul>\n</li>\n</ul>\n<p>Let's practice this skill now. Find a function/method that returns the value in a list which is bigger than any other value. For example, given the list <code>[21, 55, 4, 91, 62, 49]</code>, it will return <code>91</code>. You should write the answer in the shell as a single small expression. For example, if you were looking for the function <code>sum</code>, you could write <code>sum([21, 55, 4, 91, 62, 49])</code>. Don't solve this manually with a loop.</p>",
          "<p>Good find! Let's do one more. If you have a list:</p>\n<pre><code>nums = [1, 2, 3, 4, 5]\n</code></pre>\n<p>You could write <code>nums.append(9)</code> and <code>nums</code> would change to:</p>\n<pre><code>[1, 2, 3, 4, 5, 9]\n</code></pre>\n<p>But suppose you don't want the 9 to be at the end, you want it to go between the second and third elements:</p>\n<pre><code>[1, 2, 9, 3, 4, 5]\n</code></pre>\n<p>Call the right function/method in the shell to do that.</p>",
          "<p>Perfect!</p>\n<p>It can also be useful to Google things like \"python list tutorial\", e.g. if:</p>\n<ul>\n<li>Googling a specific method has failed so you want to find it manually.</li>\n<li>You're still confused about lists after this course.</li>\n<li>It's been a while since you learned about lists and you need a reminder.</li>\n<li>You're struggling to solve a problem with lists and you need to go back to basics and strengthen your foundations.</li>\n</ul>\n<p>There are also ways to find information without any googling. Try <code>dir([])</code> in the shell.</p>",
          "<p><code>dir()</code> returns a list of the argument's attributes, which are mostly methods. Many will start with <code>__</code> which you can ignore for now - scroll to the end of the list and you'll see some familiar methods.</p>\n<p>Here are a few more useful functions/methods. Suppose <code>nums = [28, 99, 10, 81, 59, 64]</code></p>\n<ul>\n<li><strong><code>sorted</code></strong>: Takes an iterable and returns a list of the elements in order. <code>sorted(nums)</code> returns <code>[10, 28, 59, 64, 81, 99]</code>.</li>\n<li><strong><code>pop</code></strong>: Removes and returns an element at a given index. <code>nums.pop(3)</code> removes <code>nums[3]</code> (<code>81</code>) from the list and returns it. Without an argument, i.e. just <code>nums.pop()</code>, it will remove and return the last element.</li>\n<li><strong><code>remove</code></strong>: Removes the first occurrence of the given element. <code>nums.remove(10)</code> will leave <code>nums</code> as <code>[28, 99, 81, 59, 64]</code>. Raises an error if the value doesn't exist. Equivalent to <code>nums.pop(nums.index(10))</code>.</li>\n<li><strong><code>count</code></strong>: Returns the number of times the argument appears in the list. <code>[1, 2, 3, 2, 7, 2, 5].count(2)</code> is 3.</li>\n</ul>\n<p>You've already seen that <code>len</code> and subscripting work with strings, a bit as if strings are lists of characters. Strings also support some of the new methods we've learned, not just for characters but for any substring. For example:</p>\n<ul>\n<li><code>'the' in 'feed the dog and the cat'</code> is <code>True</code></li>\n<li><code>'feed the dog and the cat'.count('the')</code> is 2</li>\n<li><code>'feed the dog and the cat'.index('the')</code> is 5</li>\n</ul>\n<p>Note that in most cases, methods which modify a list in place (<code>append</code>, <code>insert</code>, <code>remove</code>) merely return <code>None</code>, while the remaining functions/methods return a new useful value without changing the original argument. The only exception is the <code>pop</code> method.</p>\n<p>Modifying a value directly is called <em>mutation</em> - types of values which can be mutated are <em>mutable</em>, while those that can't are <em>immutable</em>. Strings are immutable - they don't have any methods like <code>append</code> or even subscript assignment. You simply can't change a string - you can only create new strings and use those instead. That means that this is a useless statement on its own:</p>\n<pre><code>word.upper()\n</code></pre>\n<p>The string referred to by <code>word</code> isn't modified, instead <code>word.upper()</code> returned a new string which was immediately discarded. If you want to change the value that <code>word</code> refers to, you have to assign a new value to the variable:</p>\n<pre><code>word = word.upper()\n</code></pre>\n<p>Or you can use <code>word.upper()</code> immediately in a larger expression, e.g.</p>\n<pre><code>if word.lower() == 'yes':\n</code></pre>"
        ],
        "title": "Functions And Methods For Lists"
      },
      {
        "step_texts": [
          "<p>It's time to learn about another tool to explore programs. Put some code in the editor and then click the new \"Python Tutor\" button. Here's some example code if you want:</p>\n<pre><code>all_numbers = [2, 4, 8, 1, 9, 7]\n\nsmall_numbers = []\nbig_numbers = []\n\nfor number in all_numbers:\n    if number &lt;= 5:\n        small_numbers.append(number)\n    else:\n        big_numbers.append(number)\n\nprint(small_numbers)\nprint(big_numbers)\n</code></pre>\n<p>The button will open a new tab with a visualisation from <a href=\"http://pythontutor.com\">pythontutor.com</a>.\nThere you can navigate through the program step by step with the \"Prev\" or \"Next\" buttons, or drag\nthe slider left or right. You can also see the values of variables on the right.</p>"
        ],
        "title": "Understanding Programs With Python Tutor"
      },
      {
        "step_texts": [
          "<p>It's time to learn some technical details that are often misunderstood and lead to errors.\nRun this program:</p>\n<pre><code>list1 = [1, 2, 3]\nlist2 = [1, 2, 3]\n\nprint(list1)\nprint(list2)\nprint(list1 == list2)\n\nprint(list1 is list2)\n\nlist1.append(4)\n\nprint(list1)\nprint(list2)\n</code></pre>",
          "<p>This program is quite straightforward and mostly consists of things you're familiar with.\nWe create two variables which refer to lists.\nThe lists have the same elements, so they are equal: <code>list1 == list2</code> is <code>True</code>.</p>\n<p>But then there's a new comparison operator: <code>is</code>. Here <code>list1 is list2</code> is <code>False</code>.\nThat means that regardless of the two lists being equal,\nthey are still two separate, distinct, individual lists.\nAs a result, when you append 4 to <code>list1</code>, only <code>list1</code> changes.</p>\n<p>Now change <code>list2 = [1, 2, 3]</code> to <code>list2 = list1</code> and see what difference it makes.</p>",
          "<p>Now <code>list1 is list2</code> is <code>True</code>, because <em>there is only one list</em>, and the two variables\n<code>list1</code> and <code>list2</code> both refer to that same list. <code>list1.append(4)</code> appends to the one list\nand the result can be seen in both <code>print(list1)</code> and <code>print(list2)</code> because both lines\nare now just different ways of printing the same list.</p>\n<p>I recommend running both versions with Python Tutor to see how it visualises the difference.\nIn the second case, the two variables both have arrows pointing to a single list object.</p>\n<p><code>list2 = list1</code> doesn't create an eternal link between the variables. If you assign a new value\nto <em>either</em> of the variables, e.g. <code>list1 = [7, 8, 9]</code>, the other variable will be unaffected\nand will still point to the original list.</p>\n<p>Basically, an assignment like:</p>\n<pre><code>list2 = &lt;expression&gt;\n</code></pre>\n<p>means 'make the variable <code>list2</code> refer to whatever <code>&lt;expression&gt;</code> evaluates to'.\nIt doesn't make a copy of that value, which is how both variables can end up pointing to the same list.\nBut as we've learned before, <code>list2</code> doesn't remember <code>&lt;expression&gt;</code>, only the value.\nIt doesn't know about other variables.</p>\n<p>You can copy a list with the <code>copy</code> method:</p>\n<pre><code>list2 = list1.copy()\n</code></pre>\n<p>This will make the program behave like the first version again.</p>\n<p>If you come across this kind of problem and you're still having trouble understanding this stuff, read the essay <a href=\"https://nedbatchelder.com/text/names.html\">Facts and myths about Python names and values</a>.</p>"
        ],
        "title": "<code>==</code> vs <code>is</code>"
      },
      {
        "step_texts": [
          "<p>Consider this program. It loops through a numbers and removes the ones smaller than 10. Or at least, it tries to. I recommend running it with Python Tutor.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor i in range(len(numbers)):\n    number = numbers[i]\n    if number &lt;= 10:\n        numbers.pop(i)\nprint(numbers)\n</code></pre>\n<p>(remember that <code>numbers.pop(i)</code> removes the element from <code>numbers</code> at index <code>i</code>)</p>\n<p>As it runs, it clearly skips even looking at 7 or 3 and doesn't remove them, and at the end it fails when it tries to access an index that's too high. Can you see why this happens?</p>\n<p>The index variable <code>i</code> runs through the usual values 0, 1, 2, ... as it's supposed to, but as the list changes those are no longer the positions we want. For example in the first iteration <code>i</code> is 0 and <code>number</code> is 10, which gets removed. This shifts the rest of the numbers left one position, so now 7 is in position 0. But then in the next iteration <code>i</code> is 1, and <code>numbers[i]</code> is 8. 7 got skipped. </p>\n<p>We could try writing the program to use <code>remove</code> instead of <code>pop</code> so we don't have to use indices. It even looks nicer this way.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor number in numbers:\n    if number &lt;= 10:\n        numbers.remove(number)\nprint(numbers)\n</code></pre>\n<p>But it turns out this does the same thing, for the same reason. Iterating over a list still goes through the indices under the hood.</p>\n<p>The lesson here is to <strong><em>never modify something while you iterate over it</em></strong>. Keep mutation and looping separate.</p>\n<p>The good news is that there are many ways to solve this. You can instead just loop over a copy, as in:</p>\n<pre><code>for number in numbers.copy():\n</code></pre>\n<p>Now the list being modified and the list being itererated over are separate objects, even if they start out with equal contents.</p>\n<p>Similarly, you could loop over the original and modify a copy:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = numbers.copy()\n\nfor number in numbers:\n    if number &lt;= 10:\n        big_numbers.remove(number)\nprint(big_numbers)\n</code></pre>\n<p>Or you could build up a new list from scratch. In this case, we've already done a similar thing in an exercise:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = []\n\nfor number in numbers:\n    if number &gt; 10:\n        big_numbers.append(number)\nprint(big_numbers)\n</code></pre>"
        ],
        "title": "Modifying While Iterating"
      }
    ],
    "user": {
      "developerMode": true,
      "email": "[email protected]"
    },
    "processing": false,
    "numHints": 0,
    "editorContent": "sentence = 'Hello World'\n\ninclude = False\nnew_sentence = ''\nfor char in sentence:\n    if include:\n        new_sentence += char\n    include = True\n\nprint(new_sentence)",
    "messages": [],
    "pastMessages": [],
    "showingPageIndex": 16,
    "requestingSolution": false,
    "solution": {
      "tokens": [],
      "maskedIndices": [],
      "mask": []
    }
  }
}

Introducing calling with multiple arguments

In the course I try hard to introduce one concept at a time, so that the user learns gradually. Currently this is violated in an exercise under the page "Functions And Methods For Lists" where the user has to do some googling and submit the code nums.insert(2, 9). They've seen function and method calls a few times by now, but critically they've never seen multiple arguments separated by commas before. At some point before this exercise, this syntax needs to be shown to them.

Add copy button to code in completed steps

Once the user has completed a step, I think it would be nice if the Copy button appeared in any code snippets in that step. That way they can easily review the material if they want and don't need to feel like they're supposed to type it in a second time.

Allow starting the course without an account

To make the site more appealing, people should be able to start using it without signing up with an email and password.

Here's how this should work:

  1. When someone views the course without logging in, it currently hits this code:

    def load_data(self):
    user = self.user
    if user.is_anonymous:
    return {}

    This ultimately tells the JS to redirect to the login page. Instead of return {}, it should create a new 'guest' account with a dummy email and password and login as that user (which sets a cookie in the browser or something so the login lasts for a while). Then the user can keep browsing and it will keep track of their progress.

  2. Inform users with a 'guest' account that they need to sign up. Above the editor/shell, just left of the hamburger menu, show signup and login buttons. For logged in users, show their email instead of hiding it in the menu.

  3. When giving feedback, add an optional field to enter an email (usually this is filled in automatically by looking at the logged in user).

Optional extensions after the above is merged:

  • If the user signs up, preserve their progress and other data. Either copy data from the old user object into the newly created one, or don't create a new user at all and just set the email and password upon signup. Note that the site uses django-allauth to manage users, you will probably need to interface with that.
  • After completing each chapter show a popup suggesting that they create an account to keep track of their progress. Link to the signup page. The user should be able to ignore this if they want, i.e. close the popup and continue.
  • Add a "don't remind me again" checkbox to the above popup.
  • In the very first page, insert some text about signing up within the content before talking about the shell. The text should only show to guest users.
  • Make the "start coding" button go straight to a course page instead of the table of contents. For logged in users, go to the page they were last on as linked in the TOC. For guest users, go to the first page. Add some text at the beginning of the first page pointing to the TOC in the menu, and mention that more features are unlocked in later chapters.

[enhancement] Suggestions for UI design and TOC

I'm new to this project so please forgive me if I get something wrong.

Here is just my suggestions for the UI design and TOC after experiencing several chapters.

  1. Is it possible to place the shell on the right or upper right in the first few chapters? Placing the shell in the lower right part with the upper right part all blank is a little bit uncoordinated to me.
  2. Is it possible to place the TOC(table of content) first and let users to choose the part to learn ? I think different users may have different foundations and knowledge for python. And they can directly jump to the part they are more concerned about and bypass the basic parts they have already mastered that will surely cost them some time

Besides, is it more convinient for users to learn with it if we have translations?

Thank you for considering my suggestions.

Bonus challenges

Sometimes we'd like to give users more difficult exercises which are optional and not part of the linear course flow. Currently neither the frontend nor the backend are equipped to handle this. I'd like to design a user interface that lets users complete challenges on the side. Any thoughts on how this should look?

Test issue

User Issue
Email: [email protected]
User Agent: PC / Mac OS X 10.13.6 / Chrome 80.0.3987

description here

Redux state

{
  "rpc": {
    "loading": [],
    "error": null
  },
  "book": {
    "server": {
      "hints": [
        "<p>Forget loops for a moment. How would you write a program which prints <code>name</code> 3 times?</p>",
        "<p>The solution looks very similar to the other programs we've seen in this section.</p>",
        "<p>The for loop will create a variable such as <code>character</code>, but the program doesn't need to use it.</p>"
      ],
      "page_index": 10,
      "showBirdseye": true,
      "showEditor": true,
      "showPythonTutor": false,
      "showSnoop": false,
      "step_index": 1
    },
    "pages": [
      {
        "step_texts": [
          "<p>At the bottom right of the screen is the <em>shell</em>. This is a place for running small bits of Python code. Just type in some code, press enter, and it'll run! Try it now:</p>\n<ol>\n<li>Click anywhere on the shell (the black area).</li>\n<li>Type <code>1+2</code></li>\n<li>Press the Enter key on your keyboard.</li>\n</ol>",
          "<p>Great! Python evaluated <code>1+2</code> and got the result <code>3</code>, so the shell displays that.</p>\n<p>The shell is probably your most important tool for learning Python, and you should spend lots of time experimenting and exploring in it. Be curious! Constantly ask yourself \"What would happen if I ran X?\" and then immediately answer that question by running it! Never be scared to try something out - if you get something wrong, nothing bad will happen.</p>\n<p>Try doing some more calculations now. You can multiply numbers with <code>*</code>, divide with <code>/</code>, and subtract with <code>-</code>. You can also use parentheses, i.e. <code>(</code> and <code>)</code>.</p>",
          "<p>Excellent! Keep experimenting. When you're ready, click 'Next' to continue.</p>"
        ],
        "title": "Introducing The Shell"
      },
      {
        "step_texts": [
          "<p>Here's a tip: often you will want to re-run a previously entered bit of code, or a slightly modified version of it. You can copy and paste, but that's tedious and gets in the way of experimenting. A better method is to press the Up Arrow key on your keyboard. This will insert the previous line of code into the shell. Keep pressing it to go further back in your history, and if you go too far, press the Down Arrow key to go the other way. Try using it now.</p>"
        ],
        "title": "Navigating Shell History"
      },
      {
        "step_texts": [
          "<p>Python lets you do much more than calculate. In fact, we're not going to touch numbers or maths for a while. Instead, we're going to look at <em>strings</em>. Strings are essentially snippets of text. For example, enter the following into the shell, quotes (<code>'</code>) included:</p>\n<pre><code>'hello'\n</code></pre>",
          "<p>The shell simply gives the same thing back because there's nothing to further to calculate. <code>'hello'</code> is simply equal to <code>'hello'</code>.</p>\n<p>A string is a sequence of characters. A character is a single symbol such as a letter, number, punctuation, space, etc. In this case the string contains the 5 characters <code>hello</code>. The quotes are not part of the string - they are there to tell both humans and computers that this is a string consisting of whatever characters are between the quotes.</p>"
        ],
        "title": "Introducing Strings"
      },
      {
        "step_texts": [
          "<p>Strings can be added together using <code>+</code>, although this means something very different from adding numbers. For example, try:</p>\n<pre><code>'hello' + 'world'\n</code></pre>",
          "<p>You can see that <code>+</code> combines or joins two strings together end to end. Technically, this is called concatenation.</p>\n<p>Here's an exercise: change the previous code slightly so that the result is the string <code>'hello world'</code>, i.e. with a space between the words.</p>\n<p>By the way, if you get stuck, you can click the lightbulb icon in the bottom right for a hint.</p>",
          "<p>Well done! Any of the following are valid solutions:</p>\n<pre><code>'hello ' + 'world'\n'hello' + ' world'\n'hello' + ' ' + 'world'\n</code></pre>"
        ],
        "title": "Adding Strings"
      },
      {
        "step_texts": [
          "<p>To make interesting programs, we can't always manipulate the same values. We need a way to refer to values that are unknown ahead of time and can change - values that can vary. These are called <em>variables</em>.</p>\n<p>Run this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>",
          "<p>This creates a variable with the name <code>word</code> that refers to the string value <code>'Hello'</code>.</p>\n<p>Check now that this is true by simply running <code>word</code> in the shell by itself.</p>",
          "<p>Good. For comparison, run <code>'word'</code> in the shell by itself, with the quotes.</p>",
          "<p>As you can see, the quotes make all the difference. <code>'word'</code> is literally just <code>'word'</code>, hence it's technically called a <em>string literal</em>. On the other hand, <code>word</code> is a variable, whose value may be anything.</p>\n<p>Similarly, <code>'sunshine'</code> is <code>'sunshine'</code>, but what's <code>sunshine</code> without quotes?</p>",
          "<p>The answer is that <code>sunshine</code> looks like a variable, so Python tries to look up its value, but since we never defined a variable with that name we get an error.</p>"
        ],
        "title": "Introducing Variables"
      },
      {
        "step_texts": [
          "<p>Previously we made a variable called <code>word</code> with the value <code>'Hello'</code> with this code:</p>\n<pre><code>word = 'Hello'\n</code></pre>\n<p>Now make a variable called <code>name</code> whose value is another string. The string can be anything...how about your name?</p>",
          "<p>You can use variables in calculations just like you would use literals. For example, try:</p>\n<pre><code>'Hello ' + name\n</code></pre>",
          "<p>Or you can just add variables together. Try:</p>\n<pre><code>word + name\n</code></pre>",
          "<p>Oops...that doesn't look nice. Can you modify the code above so that there's a space between the word and the name?</p>",
          "<p>Perfect!</p>\n<p>Variables can also change their values over time. Right now <code>word</code> has the value <code>'Hello'</code>. You can change its value in the same way that you set it for the first time. Run this:</p>\n<pre><code>word = 'Goodbye'\n</code></pre>",
          "<p>Now observe the effect of this change by running <code>word + ' ' + name</code> again.</p>",
          "<p>Those quotes around strings are getting annoying. Try running this:</p>\n<pre><code>print(word + ' ' + name)\n</code></pre>",
          "<p>Hooray! No more quotes! We'll break down what's happening in this code later. For now just know that <code>print(&lt;something&gt;)</code> displays <code>&lt;something&gt;</code> in the shell. In particular it displays the actual content of strings that we usually care about, instead of a representation of strings that's suitable for code which has things like quotes. The word <code>print</code> here has nothing to do with putting ink on paper.</p>"
        ],
        "title": "Using Variables"
      },
      {
        "step_texts": [
          "<p>It's time to stop doing everything in the shell. In the top right you can see the <em>editor</em>. This is a place where you can write and run longer programs. The shell is great and you should keep using it to explore, but the editor is where real programs live.</p>\n<p>Copy the program below into the editor, then click the 'Run' button:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nprint(word + ' ' + name)\nword = 'Goodbye'\nprint(word + ' ' + name)\n</code></pre>",
          "<p>Congratulations, you have run your first actual program!</p>\n<p>Take some time to understand this program. Python runs each line one at a time from top to bottom. You should try simulating this process in your head - think about what each line does. See how the value of <code>word</code> was changed and what effect this had. Note that when <code>print</code> is used multiple times, each thing (<code>Hello World</code> and <code>Goodbye World</code> in this case) is printed on its own line.</p>\n<p>Some things to note about programs in the editor:</p>\n<ol>\n<li>The program runs in the shell, meaning that the variables defined in the program now exist in the shell with the last values they had in the program. This lets you explore in the shell after the program completes. For example, <code>name</code> now has the value <code>'World'</code> in the shell.</li>\n<li>Programs run in isolation - they don't depend on any previously defined variables. The shell is reset and all previous variables are cleared. So even though <code>word</code> currently exists in the shell, if you delete the first line of the program and run it again, you'll get an error about <code>word</code> being undefined.</li>\n<li>If you enter code in the shell and it has a value, that value will automatically be displayed. That doesn't happen for programs in the editor - you have to print values. If you remove <code>print()</code> from the program, changing the two lines to just <code>word + ' ' + name</code>, nothing will be displayed.</li>\n</ol>\n<p>I recommend that you check all of these things for yourself.</p>"
        ],
        "title": "Writing Programs"
      },
      {
        "step_texts": [
          "<p>Often you will use variables to store the results of calculations. This will help to build more complex programs. For example, try this program:</p>\n<pre><code>word = 'Hello'\nname = 'World'\nsentence = word + ' ' + name\nprint(sentence)\n</code></pre>",
          "<p>Now <code>sentence</code> has the value <code>'Hello World'</code> which can be used multiple times. Note that it will continue to have this value until it is directly reassigned, e.g. with another statement like <code>sentence = &lt;something&gt;</code>. For example, add these two lines to the end of the program:</p>\n<pre><code>word = 'Goodbye'\nprint(sentence)\n</code></pre>",
          "<p>Unlike a spreadsheet where formulas update automatically, a variable like <code>sentence</code> doesn't remember how it was calculated and won't change if the underlying values <code>word</code> or <code>name</code> are changed.</p>"
        ],
        "title": "Storing Calculations In Variables"
      },
      {
        "step_texts": [
          "<p>Good news! You've made it past the boring basics. We can start to write some interesting programs and have a bit of fun. One of the most powerful concepts in programming is the <em>loop</em>, which lets you repeat the same code over and over. Python has two kinds of loop: <code>for</code> loops and <code>while</code> loops. Here is an example of a for loop, try running this program:</p>\n<pre><code>name = 'World'\nfor character in name: print(character)\n</code></pre>",
          "<p>You can read the code almost like normal English:</p>\n<blockquote>\n<p>For each character in the string <code>name</code>, print that character.</p>\n</blockquote>\n<p>Each character is just a normal string. <code>character</code> is a normal variable that is given a new value before the code after the <code>:</code> runs. So the code above is equivalent to:</p>\n<pre><code>name = 'World'\n\ncharacter = 'W'\nprint(character)\n\ncharacter = 'o'\nprint(character)\n\ncharacter = 'r'\nprint(character)\n\ncharacter = 'l'\nprint(character)\n\ncharacter = 'd'\nprint(character)\n</code></pre>\n<p>Note that we could use a different variable name, <code>character</code> just makes it clearer.</p>\n<p>A for loop generally follows this structure:</p>\n<pre><code>for &lt;variable&gt; in &lt;collection&gt;: &lt;code to repeat&gt;\n</code></pre>\n<p>The <code>for</code>, <code>in</code>, and <code>:</code> are all essential.</p>"
        ],
        "title": "Introducing For Loops"
      },
      {
        "step_texts": [
          "<p>This example loop:</p>\n<pre><code>for character in name: print(character)\n</code></pre>\n<p>works, but actually it would usually (and should) be written like this:</p>\n<pre><code>for character in name:\n    print(character)\n</code></pre>\n<p>Specifically, the code to be repeated (known as the <em>body</em>) starts on a new line after the colon (<code>:</code>), and it must be <em>indented</em>, i.e. have some spaces before it. The code below without indentation is invalid, run it to see for yourself:</p>\n<pre><code>for character in name:\nprint(character)\n</code></pre>",
          "<p>The spaces are required to tell Python which lines of code belong to the body of the for loop. This is critical when the loop contains several lines, which it often will. For example, run this code:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>",
          "<p>There are two indented lines, so they're both part of the body, so <code>---</code> gets printed after each character. Now try running the same code without the indentation in the last line:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\nprint('---')\n</code></pre>",
          "<p>Since <code>print('---')</code> is not indented, it's not part of the loop body. This means it only runs once, after the whole loop has finished running. Both programs are valid, they just do different things.</p>\n<p>The program below is invalid. Both lines in the loop body are indented, but by different amounts. The first line starts with 4 spaces, the second line starts with 2. Try running it.</p>\n<pre><code>for character in name:\n    print(character)\n  print('---')\n</code></pre>",
          "<p>When you indent, you should always indent by 4 spaces. Any consistent indentation is actually acceptable, but 4 spaces is the convention that almost everyone follows. Note that the editor generally makes this easy for you. For example, if you press the 'Tab' key on your keyboard in the editor, it will insert 4 spaces for you.</p>"
        ],
        "title": "Indentation"
      },
      {
        "step_texts": [
          "<p>Time for some exercises! Modify this program:</p>\n<pre><code>name = 'World'\n\nfor character in name:\n    print(character)\n    print('---')\n</code></pre>\n<p>to instead output:</p>\n<pre><code>---W\n---o\n---r\n---l\n---d\n</code></pre>",
          "<p>Splendid! Now write a program which prints <code>name</code> once for each character in <code>name</code>. For example, for <code>name = 'Amy'</code>, it should output:</p>\n<pre><code>Amy\nAmy\nAmy\n</code></pre>\n<p>For <code>name = 'World'</code>, it should output:</p>\n<pre><code>World\nWorld\nWorld\nWorld\nWorld\n</code></pre>\n<p>By the way, you can set <code>name</code> to anything in the first line. Only the rest of the program after that will be checked.</p>",
          "<p>We're making really good progress! You're solving problems and writing new code!\nLet's keep making things more interesting.</p>"
        ],
        "title": "Basic For Loop Exercises"
      },
      {
        "step_texts": [
          "<p>Before we look at some more loops, we need to quickly learn another concept. Look at this program:</p>\n<pre><code>hello = 'Hello'\nprint(hello)\nhello = hello + '!'\nprint(hello)\n</code></pre>\n<p>What do you think the line <code>hello = hello + '!'</code> does? What do you think the program will output? Make a prediction, then run it to find out.</p>",
          "<p>Python doesn't care that <code>hello</code> is on both the left and the right of the <code>=</code>, it just does what it would always do if the variables were different: it calculates <code>hello + '!'</code> which at the time is <code>'Hello' + '!'</code> which is <code>'Hello!'</code>, and that becomes the new value of <code>hello</code>. If it helps, you can think of that line as split into two steps:</p>\n<pre><code>temp = hello + '!'\nhello = temp\n</code></pre>\n<p>or:</p>\n<pre><code>temp = hello\nhello = temp + '!'\n</code></pre>\n<p>This is very useful in a loop. Think about what this program will do, then run it:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>By the way, <code>''</code> is called the <em>empty string</em> - a string containing no characters.</p>",
          "<p>The details in the above program are important. What goes wrong if you swap the last two lines and run this program instead?</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    print(line)\n    line = line + char\n</code></pre>",
          "<p>The last character in <code>name</code> only gets added to <code>line</code> at the end of the loop, after <code>print(line)</code> has already run for the last time. So that character and the full <code>name</code> never get printed at the bottom of the triangle.</p>"
        ],
        "title": "Building Up Strings"
      },
      {
        "step_texts": [
          "<p>Modify this program:</p>\n<pre><code>name = 'World'\nline = ''\nfor char in name:\n    line = line + char\n    print(line)\n</code></pre>\n<p>to add a space after every character in the triangle, so the output looks like this:</p>\n<pre><code>W\nW o\nW o r\nW o r l\nW o r l d\n</code></pre>",
          "<p>Tremendous! Now modify the program so that each line is backwards, like this:</p>\n<pre><code>W\noW\nroW\nlroW\ndlroW\n</code></pre>",
          "<p>Brilliant!</p>\n<p>Code like:</p>\n<pre><code>line = line + char\n</code></pre>\n<p>is so common that Python lets you abbreviate it. This means the same thing:</p>\n<pre><code>line += char\n</code></pre>\n<p>Note that there is no abbreviation for <code>line = char + line</code>.</p>\n<p>Now use <code>+=</code> and a for loop to write your own program which prints <code>name</code> 'underlined', like this:</p>\n<pre><code>World\n-----\n</code></pre>\n<p>There should be one <code>-</code> for each character in <code>name</code>.</p>",
          "<p>Fantastic!</p>\n<p>By the way, when you don't need to use a variable, it's common convention to name that variable <code>_</code> (underscore), e.g. <code>for _ in name:</code>. This doesn't change how the program runs, but it's helpful to readers.</p>\n<p>Let's make this fancier. Extend your program to draw a box around the name, like this:</p>\n<pre><code>+-------+\n| World |\n+-------+\n</code></pre>\n<p>Note that there is a space between the name and the pipes (<code>|</code>).</p>",
          "<p>You're getting good at this! Looks like you need more of a challenge...maybe instead of putting a name in a box, the name should be the box? Write a program that outputs this:</p>\n<pre><code>+World+\nW     W\no     o\nr     r\nl     l\nd     d\n+World+\n</code></pre>",
          "<p>Sweet! You're really getting the hang of this! If you want, here's one more optional bonus challenge. Try writing a program that outputs:</p>\n<pre><code>W\n o\n  r\n   l\n    d\n</code></pre>\n<p>Or don't, it's up to you.</p>"
        ],
        "title": "Building Up Strings Exercises"
      },
      {
        "step_texts": [
          "<p>Here's some words you need to know:</p>\n<p>An <strong><em>expression</em></strong> is a piece of code that has a value. For example, in this line of code:</p>\n<pre><code>sentence = 'Hello ' + name\n</code></pre>\n<p>there are three expressions:</p>\n<ol>\n<li><code>'Hello '</code></li>\n<li><code>name</code></li>\n<li><code>'Hello ' + name</code></li>\n</ol>\n<p>By contrast, the full line <code>sentence = ...</code> is a <strong><em>statement</em></strong>. It's a command that tells the computer to perform an action. It has no value of its own. This means, for example, that you can't add statements together. This code is invalid:</p>\n<pre><code>(word = 'Hello') + (name = 'Bob')\n</code></pre>\n<p>Specifically, a statement like <code>sentence = ...</code> where a variable is given a value is called <strong><em>assignment</em></strong> - the value is <em>assigned to</em> the the variable.</p>\n<p>A program is a list of statements which are executed in order. A <code>for</code> loop is a <em>compound statement</em>, meaning it has a body of its own which contains other statements. Most statements will also contain expressions, and expressions can contain other smaller expressions, but expressions cannot contain statements.</p>\n<p>The process of calculating the value of an expression is called <strong><em>evaluation</em></strong> - note how it almost contains the word 'value'. The computer <em>evaluates</em> <code>1 + 2</code> to get the value <code>3</code>.</p>\n<p>The process of executing a loop is called <strong><em>iteration</em></strong>. Code like <code>for char in 'Hello':</code> is <em>iterating over</em> the string <code>'Hello'</code>. The fact that it's possible means that strings are <em>iterable</em>. By contrast, numbers are not iterable, which is exactly what Python will tell you if you try <code>for char in 3:</code>. Each run through the loop is <em>one iteration</em>, so in this example there will be 5 iterations.</p>"
        ],
        "title": "Basic Terminology"
      },
      {
        "step_texts": [
          "<p>Now we're going to learn how to tell the computer to make decisions and only run code\nunder certain conditions. For this we will need a new type of value. You've seen\nnumbers and strings, now meet <em>booleans</em>. There are only two boolean values:\n<code>True</code> and <code>False</code>. Try this program:</p>\n<pre><code>condition = True\nprint(condition)\ncondition = False\nprint(condition)\n</code></pre>",
          "<p>Booleans are meant to be used inside <em>if statements</em> (sometimes also called <em>conditionals</em>).</p>\n<p>Here is a simple example for you to run:</p>\n<pre><code>if True:\n    print('This gets printed')\n\nif False:\n    print('This does not')\n</code></pre>",
          "<p>Note how the code inside the first <code>if</code> statement ran, but not the second.</p>\n<p>In general, an <code>if</code> statement looks like this:</p>\n<pre><code>if &lt;condition&gt;:\n    &lt;body&gt;\n</code></pre>\n<p>where <code>&lt;condition&gt;</code> is any expression which evaluates to a boolean and <code>&lt;body&gt;</code> is an <strong>indented</strong> list\nof one or more statements. The structure is quite similar to a <code>for</code> loop. Note the colon (<code>:</code>) which\nis essential.</p>\n<p>When the computer sees <code>if &lt;condition&gt;:</code>, it checks if <code>&lt;condition&gt;</code> is <code>True</code>. If it is, it runs the body.\nIf not, it skips it and continues to the rest of the program.</p>\n<p>Here's a more interesting example for you to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence += '!'\nprint(sentence)\n</code></pre>",
          "<p>(Remember that <code>sentence += '!'</code> means <code>sentence = sentence + '!'</code>)</p>\n<p>Change <code>excited = True</code> to <code>excited = False</code> and run the program again to see what the difference is.</p>",
          "<p>Time for an exercise. Modify the program above to include an extra\nboolean parameter <code>confused</code>, so the program should start like this:</p>\n<pre><code>sentence = 'Hello World'\nexcited = False\nconfused = True\n</code></pre>\n<p>(<code>sentence</code> can be any string and the two booleans can be either <code>True</code> or <code>False</code>)</p>\n<p>When <code>confused</code> is true, the printed sentence should have a question mark added to the end.\nIf both <code>confused</code> and <code>excited</code> are true, the sentence should end with <code>!?</code>.</p>",
          "<p>Well done! This program can do 4 different things depending on how you combine <code>excited</code>\nand <code>confused</code>. Try them out if you want.</p>"
        ],
        "title": "Introducing If Statements"
      },
      {
        "step_texts": [
          "<p>Compound statements like <code>for</code> loops and <code>if</code> statements have bodies which are a list\nof inner statements. Those inner statements can be anything, including other compound statements.\nTry this example of a <code>for</code> loop inside an <code>if</code> statement for when you want to show\nthat you're <em>really</em> excited:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    new_sentence = ''\n    for char in sentence:\n        new_sentence += char\n        new_sentence += '!'\n    sentence = new_sentence\n\nprint(sentence)\n</code></pre>",
          "<p>Note how the body of the <code>if</code> statement (5 lines) is indented as usual, while the body\nof the <code>for</code> loop (2 lines) is indented by an additional 4 spaces in each line to show that\nthose lines are within the <code>for</code> loop. You can see the overall structure of the program\njust by looking at the indentation.</p>\n<p>Alternatively, you can put an <code>if</code> inside a <code>for</code>:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nnew_sentence = ''\nfor char in sentence:\n    new_sentence += char\n    if excited:\n        new_sentence += '!'\n\nsentence = new_sentence\nprint(sentence)\n</code></pre>\n<p>These two programs have the exact same result. However the first one is more efficient as it\nonly iterates over the string if it needs to, since when <code>excited = False</code> nothing changes.</p>"
        ],
        "title": "Combining Compound Statements"
      },
      {
        "step_texts": [
          "<p>Run this program:</p>\n<pre><code>sentence = 'Hello World'\n\ninclude = False\nnew_sentence = ''\nfor char in sentence:\n    if include:\n        new_sentence += char\n    include = True\n\nprint(new_sentence)\n</code></pre>",
          "<p>As you can see, it prints everything but the first character. Take some time to understand how this works.</p>\n<p>In fact, it's time to introduce a new tool to help you understand programs. Click the 'Snoop' button to run the same program while also showing what's happening.</p>",
          "<p>Tada! Scroll to the top of the terminal and let's walk through what snoop is showing you.\nIt starts out very straightforward:</p>\n<pre><code>    1 | sentence = 'Hello World'\n    3 | include = False\n    4 | new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The first lines are simply showing you the lines of the program that the computer ran.\nOn the left is the line number as seen in the editor.</p>\n<p>Running <code>for char in sentence:</code> assigns a value to the variable <code>char</code>, so snoop shows you that value.\nLines starting with <code>......</code> indicate a new variable or a change in the value of an existing variable.\nSuch lines will not be shown when they're redundant, which is why the snoop output doesn't start like this:</p>\n<pre><code>    1 | sentence = 'Hello World'\n ...... sentence = 'Hello World'\n    3 | include = False\n ...... include = False\n    4 | new_sentence = ''\n ...... new_sentence = ''\n    5 | for char in sentence:\n ...... char = 'H'\n</code></pre>\n<p>The next two lines are:</p>\n<pre><code>    6 |     if include:\n    8 |     include = True\n</code></pre>\n<p>What's important here is what's not showing: because <code>include</code> is <code>False</code>, line 7 (<code>new_sentence += char</code>) gets skipped. But then <code>include</code> is set to <code>True</code>, so the next iteration of the loop is different:</p>\n<pre><code>    5 | for char in sentence:\n ...... char = 'e'\n    6 |     if include:\n    7 |         new_sentence += char\n .............. new_sentence = 'e'\n</code></pre>\n<p><code>new_sentence += char</code> runs for the first time and the variable <code>new_sentence</code> gets a new value.</p>\n<p>Now modify the program to do the opposite: only print the first character, leave out the rest.</p>",
          "<p>Great job! You're working with increasingly complex programs.</p>"
        ],
        "title": "Understanding Programs With Snoop"
      },
      {
        "step_texts": [
          "<p>An <code>if</code> statement can optionally have an <code>else</code> part. Run this example:</p>\n<pre><code>condition = True\nif condition:\n    print('Yes')\nelse:\n    print('No')\n</code></pre>",
          "<p>Now change the first line to <code>condition = False</code> and run it again.</p>",
          "<p>Think of <code>else</code> as saying 'or else' or 'otherwise'. It means that if the condition in the <code>if</code>\nis false, then the body of the <code>else</code> will run instead. Whether the condition is true or false,\nexactly one of the two bodies will run.</p>\n<p>Here's a more interesting example to run:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\nif excited:\n    sentence = sentence.upper()\nelse:\n    sentence = sentence.lower()\nprint(sentence)\n</code></pre>",
          "<p><code>sentence.upper()</code> is a new kind of expression we haven't encountered yet. What's going on here is that <code>sentence</code> is a string and strings have various <em>methods</em> that let you conveniently calculate new values from them, including <code>upper</code> and <code>lower</code>. The names refer to uppercase (capital letters) and lowercase (small letters). <code>'Hello World'.upper()</code> evaluates to <code>'HELLO WORLD'</code>. It doesn't change the contents of <code>sentence</code> though, so you have to assign the new value again with <code>sentence = sentence.upper()</code>.</p>\n<p>Now change <code>excited</code> to <code>False</code> and run it again.</p>",
          "<p>Here's a broken program:</p>\n<pre><code>sentence = 'Hello World'\nexcited = True\n\nif excited:\n    char = '!'\nsentence += char\n\nprint(sentence)\n</code></pre>\n<p>Can you see the problem? If you run it, everything seems fine. What could go wrong?</p>\n<p>Spoilers below! Have you figured it out?</p>\n<p>What happens if you change <code>excited</code> to <code>False</code>?</p>",
          "<p>If <code>excited</code> is true then <code>char</code> is defined and everything runs fine. But otherwise\n<code>char</code> never gets assigned a value, so trying to use it in <code>sentence += char</code> fails.</p>\n<p>Fix this by adding an <code>else</code> clause to the <code>if</code> so that if <code>excited</code> is false, a full stop (<code>.</code>)\nis added to the end of the sentence instead of an exclamation mark (<code>!</code>).</p>",
          "<p>Time for a challenge!</p>\n<p>Write a program which, given a string <code>sentence</code>, prints a modified version with\nthe same letters, where the first letter is capitalised and the rest are lowercase.\nFor example, the output should be <code>Hello world</code> whether the input <code>sentence = 'hello world'</code>\nor <code>'HELLO WORLD'</code>.</p>",
          "<p>Excellent!!!</p>\n<p>One more exercise, and then you can relax. </p>\n<p>Write a program which prints <code>sentence</code> mockingly, e.g:</p>\n<pre><code>OnE MoRe eXeRcIsE, aNd tHeN YoU CaN ReLaX.\n</code></pre>\n<p>Every second character should be lowercased, the rest should be uppercase.</p>",
          "<p>Perfect! Take a moment to be proud of what you've achieved. Can you feel your brain growing?</p>"
        ],
        "title": "<code>if</code> and <code>else</code>"
      },
      {
        "step_texts": [
          "<p>There are several ways to obtain booleans without assigning them directly,\nwhich allows you to construct very useful <code>if</code> statements. In particular there\nare many <em>comparison operators</em> which compare the values of two expressions.\nThe most common is the equality operator which checks if two values are equal.\nIt's denoted by two equals signs: <code>==</code>. Try running this:</p>\n<pre><code>print(1 + 2 == 3)\nprint(4 + 5 == 6)\nprint('ab' + 'c' == 'a' + 'bc')\n</code></pre>",
          "<p>As you can see, if the values are equal, the equality expression evaluates to <code>True</code>,\notherwise it's <code>False</code>.</p>\n<p>Note the difference between the equality operator <code>==</code> and a single <code>=</code> which has different meanings,\nparticularly in assignment statements as you've seen them so far. What happens if you try\nremoving a single <code>=</code> from the previous program?</p>",
          "<p>Let's use <code>==</code> in an <code>if</code> statement. In this program, the <code>if</code> body runs only when <code>c</code> is the character <code>'s'</code>. See for yourself.</p>\n<pre><code>name = 'kesha'\nnew_name = ''\nfor c in name:\n    if c == 's':\n        c = '$'\n    new_name += c\n\nprint(new_name)\n</code></pre>",
          "<p>Now extend the program to also replace <code>e</code> with <code>3</code> and <code>a</code> with <code>@</code>.</p>",
          "<p>Well done!</p>"
        ],
        "title": "The Equality Operator"
      },
      {
        "step_texts": [
          "<p>Quick biology lesson! Most of the cells in your body contain your full genetic code in DNA.\nThis consists of strands of molecular units called nucleobases which come in four varieties:\nAdenine, Cytosine, Guanine, and Thymine, or ACGT for short.\nSo part of a single strand might be something like:</p>\n<pre><code>AGTAGCGTCCTTAGTTACAGGATGGCTTAT...\n</code></pre>\n<p>This will be paired with another strand where A is replaced by T and vice versa,\nand C is replaced by G and vice versa, e.g:</p>\n<pre><code>TCATCGCAGGAATCAATGTCCTACCGAATA...\n</code></pre>\n<p>The two strands are 'zipped' together into the famous double helix structure,\njoined by the matching A-T and C-G pairs. These pairings are essential in copying DNA when\ncells divide and reproduce. The double helix is unzipped and the code is transcribed\ninto its opposite version to make the copy.</p>\n<p>We're going to repeat that process. Let's try the same kind of program we just wrote:</p>\n<pre><code>dna = 'AGTAGCGTC'\nopposite_dna = ''\nfor char in dna:\n    if char == 'A':\n        char = 'T'\n    if char == 'T':\n        char = 'A'\n    if char == 'G':\n        char = 'C'\n    if char == 'C':\n        char = 'G'\n    opposite_dna += char\n\nprint(opposite_dna)\n</code></pre>",
          "<p>Oh dear, that doesn't quite work. <code>T</code> is changed to <code>A</code> but <code>A</code> isn't changed to anything.\nCan you see why?</p>\n<p>When <code>char == 'A'</code>, then the body <code>char = 'T'</code> does indeed run. But that means that the following\ncondition <code>char == 'T'</code> also passes and so <code>char = 'A'</code> and we're back where we started.\nWe need to only change <code>char</code> from <code>T</code> to <code>A</code> if <code>char</code> wasn't already <code>A</code> to begin with,\nmeaning <code>char == 'A'</code> was <code>False</code>. We can do that with an <code>else</code>, like so:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelse:\n    if char == 'T':\n        char = 'A'\n</code></pre>\n<p>Now fix the program to replace all characters correctly.</p>",
          "<p>Brilliant! You have mimicked what your own cells are constantly doing.</p>\n<p>An <code>if</code> inside an <code>else</code> can be replaced by a single keyword <code>elif</code>. For example,\nthe previous code can be changed to this:</p>\n<pre><code>if char == 'A':\n    char = 'T'\nelif char == 'T':\n    char = 'A'\nelif char == 'G':\n    char = 'C'\nelif char == 'C':\n    char = 'G'\n</code></pre>",
          "<p>It's common to have a chain of <code>elif</code> clauses when you want exactly one of many\nbodies to run, like in this case. In general, code like this:</p>\n<pre><code>if X:\n    ...\nelse:\n    if Y:\n        ...\n    else:\n        if Z:\n            ...\n        else:\n            ...\n</code></pre>\n<p>can be rewritten as:</p>\n<pre><code>if X:\n    ...\nelif Y:\n    ...\nelif Z:\n    ...\nelse:\n    ...\n</code></pre>\n<p>which is both shorter and saves you from unpleasant nested indentation.\nThe difference is only cosmetic: once the computer runs this code, it can't\ntell the difference between the two versions.</p>\n<p>Note that <code>elif</code>(s) can optionally be followed by one final <code>else</code>. We didn't include one\nin our DNA example, but we could add one to alert us to any unexpected characters\nin the input, or change <code>elif char == 'C':</code> to <code>else:</code> if we were confident\nabout the input being valid.</p>"
        ],
        "title": "Introducing <code>elif</code>"
      },
      {
        "step_texts": [
          "<p>The opposite of the equals operator <code>==</code> is the <em>not equals</em> operator <code>!=</code>. If you squint it sort of looks like \u2260. It evaluates to <code>True</code> when two values are...not equal. Try it for yourself in the shell.</p>",
          "<p>Here's a cute little program using <code>!=</code>:</p>\n<pre><code>sentence = \"The e key on my keyboard is broken\"\nnew_sentence = ''\nfor c in sentence:\n    if c != 'e':\n        new_sentence += c\nprint(new_sentence)\n</code></pre>",
          "<p>Other handy operators are <code>&lt;</code> (less than) and <code>&gt;</code> (greater than). For example, <code>a &lt; b</code> means \"<code>a</code> is less than <code>b</code>\". Try using one of these in the shell to compare two numbers.</p>",
          "<p>You can also use these operators to compare strings. If you arrange two strings in alphabetical order, the first one is 'less than' the second. See for yourself.</p>",
          "<p>Here's a practical example of <code>&lt;</code> in action for you to try:</p>\n<pre><code>percentage = 73\n\nif percentage &lt; 20:\n    grade = \"F\"\nelif percentage &lt; 40:\n    grade = \"D\"\nelif percentage &lt; 60:\n    grade = \"C\"\nelif percentage &lt; 80:\n    grade = \"B\"\nelse:\n    grade = \"A\"\n\nprint(grade)\n</code></pre>\n<p>Recall that <code>elif percentage &lt; 40</code> after <code>if percentage &lt; 20</code> means \"if the percentage wasn't less than 20 and also is less than 40\", so it will pass for all numbers from 20 to 39 inclusive. Similarly a 'C' is for percentages from 40 to 59, and an 'A' is for any number 80 and up.</p>",
          "<p>Now for an exercise: write a program that takes three variables <code>x1</code>, <code>x2</code>, and <code>x3</code>, and prints the value of the smallest one. So for:</p>\n<pre><code>x1 = 'Charlie'\nx2 = 'Alice'\nx3 = 'Bob'\n</code></pre>\n<p>it should print <code>Alice</code>.</p>",
          "<p>Marvelous!</p>\n<p>There are many ways this could be solved. Here's one solution:</p>\n<pre><code>if x1 &lt; x2:\n    if x1 &lt; x3:\n        first = x1\n    else:\n        first = x3\nelse:\n    if x2 &lt; x3:\n        first = x2\n    else:\n        first = x3\n\nprint(first)\n</code></pre>\n<p>Here's another:</p>\n<pre><code>first = x1\n\nif x2 &lt; first:\n    first = x2\n\nif x3 &lt; first:\n    first = x3\n\nprint(first)\n</code></pre>\n<p>These programs (and yours too) all work equally well with numbers and strings,\nbut not a mixture.</p>\n<p><code>&lt;</code> and <code>&gt;</code> evaluate to False if the compared values are equal. For example,\n3 is not less than 3, so <code>3 &lt; 3</code> and <code>3 &gt; 3</code> are both False.\nTo allow equal values, use <code>&lt;=</code> and <code>&gt;=</code>.\nAgain, if you squint, they look a bit like \u2264 and \u2265.\nNote that the <code>=</code> comes second - there are no such operators as <code>=&lt;</code> or <code>=&gt;</code>.\nTo remember this, read them out loud as \"less than or equal to\"\nand \"greater than or equal to\".</p>\n<p>In summary, the main comparison operators are <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, and <code>&gt;=</code>.\nIf you ever have doubts about what they do, play with them in the shell!</p>"
        ],
        "title": "Other Comparison Operators"
      },
      {
        "step_texts": [
          "<p>It's time to learn about a powerful new type of value called lists. Here's an example:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor word in words:\n    print(word)\n</code></pre>",
          "<p>A list is a <em>sequence</em> (an ordered collection/container) of any number of values.\nThe values are often referred to as <em>elements</em>.\nThey can be anything: numbers, strings, booleans, even lists! They can also be a mixture of types.</p>\n<p>To create a list directly, like above:</p>\n<ol>\n<li>Write some square brackets: <code>[]</code></li>\n<li>If you don't want an empty list, write some expressions inside to be the elements.</li>\n<li>Put commas (<code>,</code>) between elements to separate them.</li>\n</ol>\n<p>Here's another example of making a list:</p>\n<pre><code>x = 1\nthings = ['Hello', x, x + 3]\nprint(things)\n</code></pre>",
          "<p>As you saw above, lists are <em>iterable</em>, meaning you can iterate over them with a <code>for loop</code>.\nHere's a program that adds up all the numbers in a list:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9]\n\ntotal = 0\nfor number in numbers:\n    total += number\n\nprint(total)\n</code></pre>",
          "<p>Now modify the program so that it can add up a list of strings instead of numbers.\nFor example, given:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n</code></pre>\n<p>it should print:</p>\n<pre><code>Thisisalist\n</code></pre>",
          "<p>Optional bonus challenge: extend the program to insert a separator string <em>between</em> each word.\nFor example, given</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\nseparator = ' - '\n</code></pre>\n<p>it would output:</p>\n<pre><code>This - is - a - list\n</code></pre>\n<p>Lists and strings have a lot in common.\nFor example, you can add two lists to combine them together into a new list.\nYou can also create an empty list that has no elements.\nCheck for yourself:</p>\n<pre><code>numbers = [1, 2] + [3, 4]\nprint(numbers)\nnew_numbers = []\nnew_numbers += numbers\nnew_numbers += [5]\nprint(new_numbers)\n</code></pre>\n<p>With that knowledge, write a program which takes a list of numbers\nand prints a list where each number has been doubled. For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[6, 2, 8, 2, 10, 18, 4, 12, 10]\n</code></pre>",
          "<p>Great!</p>\n<p>When you want to add a single element to the end of a list, instead of:</p>\n<pre><code>some_list += [element]\n</code></pre>\n<p>it's actually more common to write:</p>\n<pre><code>some_list.append(element)\n</code></pre>\n<p>There isn't really a big difference between these, but <code>.append</code>\nwill be more familiar and readable to most people.</p>\n<p>Now use <code>.append</code> to write a program which prints a list containing only the numbers bigger than 5.</p>\n<p>For example, given:</p>\n<pre><code>numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]\n</code></pre>\n<p>it would print:</p>\n<pre><code>[9, 6]\n</code></pre>",
          "<p>Fantastic! We're making great progress.</p>"
        ],
        "title": "Introducing Lists"
      },
      {
        "step_texts": [
          "<p>Exercise: write a program which takes a list and a value and checks\nif the list contains the value. For example, given:</p>\n<pre><code>things = ['This', 'is', 'a', 'list']\nthing_to_find = 'is'\n</code></pre>\n<p>it should print <code>True</code>, but for</p>\n<pre><code>thing_to_find = 'other'\n</code></pre>\n<p>it should print <code>False</code>.</p>",
          "<p>Nice!</p>\n<p>A typical solution looks something like this:</p>\n<pre><code>found = False\nfor thing in things:\n    if thing == thing_to_find:\n        found = True\n\nprint(found)\n</code></pre>\n<p>Your solution is probably similar. It's fine, but it's a bit inefficient.\nThat's because it'll loop over the entire list even if it finds the element at the beginning.\nYou can stop any loop using a <code>break</code> statement, like so:</p>\n<pre><code>for thing in things:\n    if thing == thing_to_find:\n        found = True\n        break\n</code></pre>\n<p>This is just as correct but skips unnecessary iterations and checks once it finds the element.\nYou can use snoop to see the difference.</p>"
        ],
        "title": "Using <code>break</code> to end a loop early"
      },
      {
        "step_texts": [
          "<p>Looping is great, but often you just want to retrieve a single element from the list at a known position.\nHere's how:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nprint(words[0])\nprint(words[1])\nprint(words[2])\nprint(words[3])\n</code></pre>",
          "<p>In general, you can get the element at the position <code>i</code> with <code>words[i]</code>. The operation is called <em>subscripting</em> or <em>indexing</em>, and the position is called the <em>index</em>.</p>\n<p>You've probably noticed that the first index is 0, not 1. In programming, counting starts at 0. It seems weird, but that's how most programming languages do it, and it's generally agreed to be better.</p>\n<p>This also means that the last index in this list of 4 elements is 3. What happens if you try getting an index greater than that?</p>",
          "<p>There you go. <code>words[4]</code> and beyond don't exist, so trying that will give you an error.</p>\n<p>By the way, you can get the number of elements in a list (commonly called the <em>length</em>) using <code>len(words)</code>.\nThat means that the last valid index of the list is <code>len(words) - 1</code>, so the last element is <code>words[len(words) - 1]</code>. Try these for yourself.</p>\n<p>So in general, the valid indices are:</p>\n<pre><code>[0, 1, 2, ..., len(words) - 2, len(words) - 1]\n</code></pre>\n<p>There's a handy built in function to give you these values, called <code>range</code>:</p>\n<pre><code>for i in range(10):\n    print(i)\n</code></pre>",
          "<p><code>range(n)</code> is similar to the list <code>[0, 1, 2, ..., n - 2, n - 1]</code>.\nThis gives us an alternative way to loop over a list:</p>\n<pre><code>words = ['This', 'is', 'a', 'list']\n\nfor index in range(len(words)):\n    print(index)\n    print(words[index])\n</code></pre>",
          "<p>Let's get some exercise! Given a list <code>things</code> and a value <code>to_find</code>,\nprint the first index of <code>to_find</code> in the list, i.e. the lowest number <code>i</code> such that\n<code>things[i]</code> is <code>to_find</code>. For example, for</p>\n<pre><code>things = ['on', 'the', 'way', 'to', 'the', 'store']\nto_find = 'the'\n</code></pre>\n<p>your program should print <code>1</code>.</p>\n<p>You can assume that <code>to_find</code> appears at least once.</p>",
          "<p>Nice!</p>\n<p>By the way, indexing and <code>len()</code> also work on strings. Try them out in the shell.</p>\n<p>Here's another exercise. Given two strings of equal length, e.g:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"World\"\n</code></pre>\n<p>print them vertically side by side, with a space between each character:</p>\n<pre><code>H W\ne o\nl r\nl l\no d\n</code></pre>",
          "<p>Incredible!</p>\n<p>Your solution probably looks something like this:</p>\n<pre><code>for i in range(len(string1)):\n    char1 = string1[i]\n    char2 = string2[i]\n    print(char1 + ' ' + char2)\n</code></pre>\n<p>This doesn't work so well if the strings have different lengths.\nIn fact, it goes wrong in different ways depending on whether <code>string1</code> or <code>string2</code> is longer.\nYour next challenge is to fix this problem by filling in 'missing' characters with spaces.</p>\n<p>For example, for:</p>\n<pre><code>string1 = \"Goodbye\"\nstring2 = \"World\"\n</code></pre>\n<p>output:</p>\n<pre><code>G W\no o\no r\nd l\nb d\ny  \ne\n</code></pre>\n<p>and for:</p>\n<pre><code>string1 = \"Hello\"\nstring2 = \"Elizabeth\"\n</code></pre>\n<p>output:</p>\n<pre><code>H E\ne l\nl i\nl z\no a\n  b\n  e\n  t\n  h\n</code></pre>",
          "<p>Magnificent! Take a break, you've earned it!</p>"
        ],
        "title": "Getting Elements at a Position"
      },
      {
        "step_texts": [
          "<p>It's time to expand your vocabulary some more.</p>\n<p><code>print</code> and <code>len</code> are <strong><em>functions</em></strong>. See for yourself:</p>\n<pre><code>print(len)\nprint(print)\n</code></pre>",
          "<p>An expression like <code>len(things)</code> or <code>print(things)</code> is a function <strong><em>call</em></strong> - when you write that, you are <strong><em>calling</em></strong> the function <code>len</code> or <code>print</code>. The fact that this is possible means that functions are <strong><em>callable</em></strong>:</p>\n<pre><code>print(callable(len))\n</code></pre>",
          "<p>Most things are not callable, so trying to call them will give you an error:</p>\n<pre><code>f = 'a string'\nprint(callable(f))\nf()\n</code></pre>",
          "<p>In the call <code>len(things)</code>, <code>things</code> is an <strong><em>argument</em></strong>. Sometimes you will also see the word <strong><em>parameter</em></strong>, which means basically the same thing as argument. It's a bit like you're giving the argument to the function - specifically we say that the argument <code>things</code> is <em>passed</em> to <code>len</code>, and <code>len</code> <em>accepts</em> or <em>receives</em> the argument.</p>\n<p><code>len(things)</code> will evaluate to a number such as 3, in which case we say that <code>len</code> <strong><em>returned</em></strong> 3.</p>\n<p>All calls have to return something...even if it's nothing. For example, <code>print</code>'s job is to display something on screen, not to return a useful value. So it returns something useless instead:</p>\n<pre><code>things = [1, 2, 3]\nlength = len(things)\nprinted = print(length)\nprint(printed)\n</code></pre>",
          "<p><code>None</code> is a special 'null' value which can't do anything interesting. It's a common placeholder that represents the lack of a real useful value. Functions that don't want to return anything return <code>None</code> by default. If you see an error message about <code>None</code> or <code>NoneType</code>, it often means you assigned the wrong thing to a variable:</p>\n<pre><code>things = print([1, 2, 3])\nlength = len(things)\n</code></pre>",
          "<p>A <strong><em>method</em></strong> is a function which belongs to a type, and can be called on all values of that type using <code>.</code>. For example, <code>upper</code> and <code>lower</code> are methods of strings, which are called with e.g. <code>word.upper()</code>:</p>\n<pre><code>word = 'Hello'\nprint(word.upper)\nprint(word.upper())\n</code></pre>",
          "<p>Another example is that <code>append</code> is a method of lists. But you can't use <code>.upper</code> on a list or <code>.append</code> on a string:</p>\n<pre><code>word = 'Hello'\nword.append('!')\n</code></pre>",
          "<p>The word 'attribute' in the error message refers to the use of <code>.</code> - the error actually comes just from <code>word.append</code>, without even a call.</p>"
        ],
        "title": "Terminology: Calling functions and methods"
      },
      {
        "step_texts": [
          "<p>Let's review how to work with lists. Suppose we have a list <code>nums = [1, 2, 3]</code>. You can use:</p>\n<ul>\n<li><strong><code>append</code></strong>: Add an element to the end of the list. <code>nums.append(4)</code> changes the list to <code>[1, 2, 3, 4]</code>.</li>\n<li><strong><code>len</code></strong>: Returns the number of elements. <code>len(nums)</code> is <code>3</code>.</li>\n<li><strong><code>range</code></strong>: <code>range(n)</code> is an object similar to the list of numbers from 0 to <code>n - 1</code>. In particular, <code>range(len(nums))</code> is like <code>[0, 1, 2]</code>.</li>\n<li><strong><code>subscripting</code></strong>: Get a value at an index. <code>nums[0]</code> is 1, <code>nums[1]</code> is 2, <code>nums[2]</code> is 3.</li>\n<li><strong><code>+</code></strong>: Concatenates lists. <code>nums + [4, 5]</code> is <code>[1, 2, 3, 4, 5]</code>.</li>\n</ul>\n<p>Here's some new things. Try them out in the shell.</p>\n<ul>\n<li><strong><code>subscript assignment</code></strong>: Set a value at an index. <code>nums[0] = 9</code> changes the list to <code>[9, 2, 3]</code>.</li>\n<li><strong><code>join</code></strong>: Add a list of strings with a separator in between. This is a method of strings (the separator) which takes an iterable of strings as an argument. <code>'--'.join(['apples', 'oranges', 'bananas'])</code> returns <code>'apples--oranges--bananas'</code>. You can also use an empty string if you don't want a separator, e.g. <code>''.join(['apples', 'oranges', 'bananas'])</code> returns <code>'applesorangesbananas'</code>. </li>\n<li><strong><code>sum</code></strong>: Add a list of numbers. <code>sum(nums)</code> is 6.</li>\n<li><strong><code>in</code></strong>: A comparison operator that checks if a value is in a list. <code>2 in nums</code> is <code>True</code>, but <code>4 in nums</code> is <code>False</code>.</li>\n<li><strong><code>index</code></strong>: Returns the first index of a value in a list. <code>[7, 8, 9, 8].index(8)</code> is 1. Raises an error if the value isn't there.</li>\n</ul>\n<p>You may recognise some of these from your exercises. I assure you that those exercises were not pointless, as you've now learned valuable fundamental skills. For example, you can use <code>in</code> to check if a list contains 5, but there's no similarly easy way to check for a number bigger than 5.</p>\n<p>It's useful to know these functions, but it's not easy to learn them all, and there's many more. A more important skill is being able to look things up. For example, here are some typical ways you might Google the above functions if you forgot their names:</p>\n<ul>\n<li><code>append</code><ul>\n<li>python add element to list</li>\n<li>python add item at end of list</li>\n</ul>\n</li>\n<li><code>len</code><ul>\n<li>python size of list</li>\n<li>python number of elements in list</li>\n<li>python how many characters in string</li>\n</ul>\n</li>\n<li><code>join</code><ul>\n<li>python combine list of strings with separator</li>\n<li>python add together list of strings with string in between</li>\n</ul>\n</li>\n<li><code>sum</code><ul>\n<li>python add list of numbers</li>\n<li>python total of numbers</li>\n</ul>\n</li>\n<li><code>in</code><ul>\n<li>python check if list contains value</li>\n<li>python test if list has element</li>\n</ul>\n</li>\n<li><code>index</code><ul>\n<li>python get position of element</li>\n<li>python get index of value</li>\n</ul>\n</li>\n</ul>\n<p>Let's practice this skill now. Find a function/method that returns the value in a list which is bigger than any other value. For example, given the list <code>[21, 55, 4, 91, 62, 49]</code>, it will return <code>91</code>. You should write the answer in the shell as a single small expression. For example, if you were looking for the function <code>sum</code>, you could write <code>sum([21, 55, 4, 91, 62, 49])</code>. Don't solve this manually with a loop.</p>",
          "<p>Good find! Let's do one more. If you have a list:</p>\n<pre><code>nums = [1, 2, 3, 4, 5]\n</code></pre>\n<p>You could write <code>nums.append(9)</code> and <code>nums</code> would change to:</p>\n<pre><code>[1, 2, 3, 4, 5, 9]\n</code></pre>\n<p>But suppose you don't want the 9 to be at the end, you want it to go between the second and third elements:</p>\n<pre><code>[1, 2, 9, 3, 4, 5]\n</code></pre>\n<p>Call the right function/method in the shell to do that.</p>",
          "<p>Perfect!</p>\n<p>It can also be useful to Google things like \"python list tutorial\", e.g. if:</p>\n<ul>\n<li>Googling a specific method has failed so you want to find it manually.</li>\n<li>You're still confused about lists after this course.</li>\n<li>It's been a while since you learned about lists and you need a reminder.</li>\n<li>You're struggling to solve a problem with lists and you need to go back to basics and strengthen your foundations.</li>\n</ul>\n<p>There are also ways to find information without any googling. Try <code>dir([])</code> in the shell.</p>",
          "<p><code>dir()</code> returns a list of the argument's attributes, which are mostly methods. Many will start with <code>__</code> which you can ignore for now - scroll to the end of the list and you'll see some familiar methods.</p>\n<p>Here are a few more useful functions/methods. Suppose <code>nums = [28, 99, 10, 81, 59, 64]</code></p>\n<ul>\n<li><strong><code>sorted</code></strong>: Takes an iterable and returns a list of the elements in order. <code>sorted(nums)</code> returns <code>[10, 28, 59, 64, 81, 99]</code>.</li>\n<li><strong><code>pop</code></strong>: Removes and returns an element at a given index. <code>nums.pop(3)</code> removes <code>nums[3]</code> (<code>81</code>) from the list and returns it. Without an argument, i.e. just <code>nums.pop()</code>, it will remove and return the last element.</li>\n<li><strong><code>remove</code></strong>: Removes the first occurrence of the given element. <code>nums.remove(10)</code> will leave <code>nums</code> as <code>[28, 99, 81, 59, 64]</code>. Raises an error if the value doesn't exist. Equivalent to <code>nums.pop(nums.index(10))</code>.</li>\n<li><strong><code>count</code></strong>: Returns the number of times the argument appears in the list. <code>[1, 2, 3, 2, 7, 2, 5].count(2)</code> is 3.</li>\n</ul>\n<p>You've already seen that <code>len</code> and subscripting work with strings, a bit as if strings are lists of characters. Strings also support some of the new methods we've learned, not just for characters but for any substring. For example:</p>\n<ul>\n<li><code>'the' in 'feed the dog and the cat'</code> is <code>True</code></li>\n<li><code>'feed the dog and the cat'.count('the')</code> is 2</li>\n<li><code>'feed the dog and the cat'.index('the')</code> is 5</li>\n</ul>\n<p>Note that in most cases, methods which modify a list in place (<code>append</code>, <code>insert</code>, <code>remove</code>) merely return <code>None</code>, while the remaining functions/methods return a new useful value without changing the original argument. The only exception is the <code>pop</code> method.</p>\n<p>Modifying a value directly is called <em>mutation</em> - types of values which can be mutated are <em>mutable</em>, while those that can't are <em>immutable</em>. Strings are immutable - they don't have any methods like <code>append</code> or even subscript assignment. You simply can't change a string - you can only create new strings and use those instead. That means that this is a useless statement on its own:</p>\n<pre><code>word.upper()\n</code></pre>\n<p>The string referred to by <code>word</code> isn't modified, instead <code>word.upper()</code> returned a new string which was immediately discarded. If you want to change the value that <code>word</code> refers to, you have to assign a new value to the variable:</p>\n<pre><code>word = word.upper()\n</code></pre>\n<p>Or you can use <code>word.upper()</code> immediately in a larger expression, e.g.</p>\n<pre><code>if word.lower() == 'yes':\n</code></pre>"
        ],
        "title": "Functions And Methods For Lists"
      },
      {
        "step_texts": [
          "<p>It's time to learn about another tool to explore programs. Put some code in the editor and then click the new \"Python Tutor\" button. Here's some example code if you want:</p>\n<pre><code>all_numbers = [2, 4, 8, 1, 9, 7]\n\nsmall_numbers = []\nbig_numbers = []\n\nfor number in all_numbers:\n    if number &lt;= 5:\n        small_numbers.append(number)\n    else:\n        big_numbers.append(number)\n\nprint(small_numbers)\nprint(big_numbers)\n</code></pre>\n<p>The button will open a new tab with a visualisation from <a href=\"http://pythontutor.com\">pythontutor.com</a>.\nThere you can navigate through the program step by step with the \"Prev\" or \"Next\" buttons, or drag\nthe slider left or right. You can also see the values of variables on the right.</p>"
        ],
        "title": "Understanding Programs With Python Tutor"
      },
      {
        "step_texts": [
          "<p>It's time to learn some technical details that are often misunderstood and lead to errors.\nRun this program:</p>\n<pre><code>list1 = [1, 2, 3]\nlist2 = [1, 2, 3]\n\nprint(list1)\nprint(list2)\nprint(list1 == list2)\n\nprint(list1 is list2)\n\nlist1.append(4)\n\nprint(list1)\nprint(list2)\n</code></pre>",
          "<p>This program is quite straightforward and mostly consists of things you're familiar with.\nWe create two variables which refer to lists.\nThe lists have the same elements, so they are equal: <code>list1 == list2</code> is <code>True</code>.</p>\n<p>But then there's a new comparison operator: <code>is</code>. Here <code>list1 is list2</code> is <code>False</code>.\nThat means that regardless of the two lists being equal,\nthey are still two separate, distinct, individual lists.\nAs a result, when you append 4 to <code>list1</code>, only <code>list1</code> changes.</p>\n<p>Now change <code>list2 = [1, 2, 3]</code> to <code>list2 = list1</code> and see what difference it makes.</p>",
          "<p>Now <code>list1 is list2</code> is <code>True</code>, because <em>there is only one list</em>, and the two variables\n<code>list1</code> and <code>list2</code> both refer to that same list. <code>list1.append(4)</code> appends to the one list\nand the result can be seen in both <code>print(list1)</code> and <code>print(list2)</code> because both lines\nare now just different ways of printing the same list.</p>\n<p>I recommend running both versions with Python Tutor to see how it visualises the difference.\nIn the second case, the two variables both have arrows pointing to a single list object.</p>\n<p><code>list2 = list1</code> doesn't create an eternal link between the variables. If you assign a new value\nto <em>either</em> of the variables, e.g. <code>list1 = [7, 8, 9]</code>, the other variable will be unaffected\nand will still point to the original list.</p>\n<p>Basically, an assignment like:</p>\n<pre><code>list2 = &lt;expression&gt;\n</code></pre>\n<p>means 'make the variable <code>list2</code> refer to whatever <code>&lt;expression&gt;</code> evaluates to'.\nIt doesn't make a copy of that value, which is how both variables can end up pointing to the same list.\nBut as we've learned before, <code>list2</code> doesn't remember <code>&lt;expression&gt;</code>, only the value.\nIt doesn't know about other variables.</p>\n<p>You can copy a list with the <code>copy</code> method:</p>\n<pre><code>list2 = list1.copy()\n</code></pre>\n<p>This will make the program behave like the first version again.</p>\n<p>If you come across this kind of problem and you're still having trouble understanding this stuff, read the essay <a href=\"https://nedbatchelder.com/text/names.html\">Facts and myths about Python names and values</a>.</p>"
        ],
        "title": "<code>==</code> vs <code>is</code>"
      },
      {
        "step_texts": [
          "<p>Consider this program. It loops through a numbers and removes the ones smaller than 10. Or at least, it tries to. I recommend running it with Python Tutor.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor i in range(len(numbers)):\n    number = numbers[i]\n    if number &lt;= 10:\n        numbers.pop(i)\nprint(numbers)\n</code></pre>\n<p>(remember that <code>numbers.pop(i)</code> removes the element from <code>numbers</code> at index <code>i</code>)</p>\n<p>As it runs, it clearly skips even looking at 7 or 3 and doesn't remove them, and at the end it fails when it tries to access an index that's too high. Can you see why this happens?</p>\n<p>The index variable <code>i</code> runs through the usual values 0, 1, 2, ... as it's supposed to, but as the list changes those are no longer the positions we want. For example in the first iteration <code>i</code> is 0 and <code>number</code> is 10, which gets removed. This shifts the rest of the numbers left one position, so now 7 is in position 0. But then in the next iteration <code>i</code> is 1, and <code>numbers[i]</code> is 8. 7 got skipped. </p>\n<p>We could try writing the program to use <code>remove</code> instead of <code>pop</code> so we don't have to use indices. It even looks nicer this way.</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nfor number in numbers:\n    if number &lt;= 10:\n        numbers.remove(number)\nprint(numbers)\n</code></pre>\n<p>But it turns out this does the same thing, for the same reason. Iterating over a list still goes through the indices under the hood.</p>\n<p>The lesson here is to <strong><em>never modify something while you iterate over it</em></strong>. Keep mutation and looping separate.</p>\n<p>The good news is that there are many ways to solve this. You can instead just loop over a copy, as in:</p>\n<pre><code>for number in numbers.copy():\n</code></pre>\n<p>Now the list being modified and the list being itererated over are separate objects, even if they start out with equal contents.</p>\n<p>Similarly, you could loop over the original and modify a copy:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = numbers.copy()\n\nfor number in numbers:\n    if number &lt;= 10:\n        big_numbers.remove(number)\nprint(big_numbers)\n</code></pre>\n<p>Or you could build up a new list from scratch. In this case, we've already done a similar thing in an exercise:</p>\n<pre><code>numbers = [10, 7, 8, 3, 12, 15]\nbig_numbers = []\n\nfor number in numbers:\n    if number &gt; 10:\n        big_numbers.append(number)\nprint(big_numbers)\n</code></pre>"
        ],
        "title": "Modifying While Iterating"
      }
    ],
    "user": {
      "developerMode": true,
      "email": "[email protected]"
    },
    "processing": false,
    "numHints": 0,
    "editorContent": "",
    "messages": [],
    "pastMessages": [],
    "showingPageIndex": 10,
    "requestingSolution": false,
    "solution": {
      "tokens": [],
      "maskedIndices": [],
      "mask": []
    }
  }
}

Frontend tests, e.g. selenium

We need tests that automate browser interactions, thus testing both the frontend and backend at the same time.

Some things we could test:

  • Login or sign up
  • Open the TOC
  • Click on a TOC link to go to a page
  • Run some code in the shell, confirm output
  • Run some code in the editor, confirm output
  • Run some code in the editor with snoop, confirm output. We can leave out birdseye and pythontutor.
  • Run some code which advances a step.
  • Confirm that the Next button appears only when reaching the end of a page.
  • Click Next and Previous buttons.
  • For an exercise, click the hint button, get all hints, reveal a few tokens of the solution.
  • Run some code which doesn't advance but causes a message to appear. For example, running any code other than 1+2 in the very first step.
  • Click X to clear the message.
  • Message shouldn't reappear when running the same code.
  • Trigger a different message, e.g. by running code in the wrong case. Confirm that the message automatically disappears when advancing a step.
  • Turn on developer mode. Go back and forth a step.
  • Turn off developer mode, confirm that buttons disappear.
  • Confirm content of hamburger menu, including user email and links to TOC and sign out (no need to click).
  • Click Give Feedback in menu, fill in and submit form, confirm submission in backend (requires mocking the request to github).

Better tracebacks

Currently I use https://github.com/alexmojaki/stack_data to format tracebacks, and they look pretty good:

traceback

We can definitely do more. I'd like to make these as good as possible. Some ideas:

Personally I would rather develop and test functionality here first and worry about integrating it back into the appropriate library like friendly-traceback or DidYouMean later. It's more difficult to develop a polished generic API than one concrete use case. But @aroberge seems to prefer the opposite.

Improve the lists chapter

Towards the end of the chapter on lists, particularly on the page FunctionsAndMethodsForLists, the quality is not great. A lot of information is dumped on the user and it's not easy for them to process it. There's lots of reading and not much interactivity.

Here is what I'm trying to accomplish:

  • Summarise the essential things you can do with lists, like len and append. This is to refresh their memory in the moment and also provide one easy place that they can come back to later if they need a reminder.
  • Show that there are many other useful functions available for lists (and also strings). They don't actually need to memorise any of these - they just need to know that many useful functions exist, and have a vague sense of the kinds of things they do so that when they encounter a use case they have a chance of guessing that a function might exist and can be found with google.
  • Show how to look things up, e.g. with google.

The reason there are no exercises and only a light encouragement to "Try them out in the shell" is because remembering the actual functions is not important. But the way the page is now is lots of dry, boring reading. That's bad.

I'm looking for opinions on how to deal with this. Should we:

  • Add some steps where users are required to try out functions in the shell, or even complete exercises? This makes the section less boring. But it also puts more pressure on the user to learn information that is not essential at this stage. I've described my concerns about that here. Maybe it's fine, and this is just the time to learn those things.
  • Emphasise more and earlier that they don't need to memorise the functions so that they feel comfortable skimming through the list if it's boring.
  • Do something completely different? I'm keen for ideas.

Then there's this section:

Note that in most cases, methods which modify a list in place (append, insert, remove) merely return None, while the remaining functions/methods return a new useful value without changing the original argument. The only exception is the pop method.

Modifying a value directly is called mutation - types of values which can be mutated are mutable, while those that can't are immutable. Strings are immutable - they don't have any methods like append or even subscript assignment. You simply can't change a string - you can only create new strings and use those instead. That means that this is a useless statement on its own:

word.upper()

The string referred to by word isn't modified, instead word.upper() returned a new string which was immediately discarded. If you want to change the value that word refers to, you have to assign a new value to the variable:

word = word.upper()

Or you can use word.upper() immediately in a larger expression, e.g.

if word.lower() == 'yes':

This is all very important information that is worth learning properly. Adding some interactive steps (e.g. showing that word.upper() on its own doesn't change word) would be great. I think the only reason I didn't was that I was tired and lazy. It should maybe be on its own page, the reason I hesitate is that I refer to method names like pop and it's useful to be able to scroll up and see the definitions of those methods. They can still use the Previous and Next buttons if the pages are separated though, and that might even be better.

The pages EqualsVsIs and ModifyingWhileIterating are also heavy reading and not great, but maybe less of a priority.

Package into offline installable desktop app, e.g. with pyinstaller

EDIT: now that production is using pyodide, this is a lower priority. Plus, the code is going through a major transformation, and Django is probably going to be removed. So this isn't a great time for this.


We need a futurecoder 'app' that is entirely self contained and runs locally. The advantages for the user are:

  • Doesn't require internet access once installed
  • Works faster since it doesn't need to wait for communication with a server
  • The web version restricts CPU time and filesystem access to prevent abuse and security issues. A local version doesn't need these restrictions, which means:
    • No limits on CPU
    • Can do lessons and exercises involving files
    • Can install external packages
    • System is more stable in general, no more processes intermittently dying

The big advantage for us is reduced load on servers.

I've never done this before so I don't know the best way to do it. The important requirements are:

  • Must be easy to install for non-technical users.
    • Standard click to download on website and then click a few buttons in a GUI installer.
    • No terminal commands.
    • No previous installation of Python required.
  • Prefer cross-platform technologies and solutions. The less work that has to be done to support a specific OS, the better.

EDIT: Initially we looked into using Electron before we realised this is not important. As a first step, let's just make a program which runs the server and opens a browser tab for localhost:3000 or something. Electron just makes things look a bit fancier.

Syntax highlighting code in the text

This requires:

  1. Finding the various places where text is converted to HTML using the markdown function. Some might not be applicable, e.g. page titles.
  2. Using a pygments formatter on the code blocks. Look up how other people have done this. There might even be an easy extension to the markdown library.
  3. Including the CSS file generated by pygments for the monokai style in the frontend.

Custom courses

@alexmojaki I haven't been able to check the demo, will try later. I am using python for business analytics which means I pretty much have to train each person that comes into my team or that wants to use my tools in my company, so I train a lot of people on python. One reason I have to check futurecoder for me is to see if I can create custom courses. Me and my team have developed a python library for data analytics and I would love to have a standard course for new team mates for instance.

To give you a rough idea of this industry. Enterprise "UI" based tools to do what me and my team do with Python are between $4,000 (Alteryx) and $9,000 (DataIku) per user per year.

Originally posted by @acivitillo in #23 (comment)

Animating the appearance of new steps in the course

Each time the user passes a step, a new step appears in the text on the left. Right now this is easy to miss, especially since their attention is usually focused on the right, particularly after answering an output prediction question and/or if the new step is short. It should be made more obvious so that users know they've succeeded. I'm thinking some animation would be helpful here. Perhaps a 'wipe' transition (like the output prediction questions) and/or a change in background (e.g. if the new step started out a pale yellow for a few seconds). Suggestions welcome!

2D Parsons problems, i.e. inferring indentation

Follow-up to #53 and #69

Students can now solve Parsons problems instead of writing code, which is great. However these may be more effective (especially for shorter, simpler problems) if they also have to figure out how much each line is indented rather than being given that information. That is, the shuffled lines all start out completely unindented, and students need to correctly adjust them.

An ideal user interface for this can be seen in https://runestone.academy/runestone/static/instructorguide/Directives/mixedUp.html#indenting-the-blocks where the indentation can be set by dragging the block horizontally and it snaps to indentation guides. Runestone uses their own custom version of https://js-parsons.github.io/ which has the same feature. I'm not using js-parsons because it's undocumented, unmaintained, and jQuery, but if someone wants to try then they can.

The simplest way I can think of to reimplement this feature in futurecoder is to add a little button or two to each code block which the user can click to adjust the indentation. This seems easier than dealing with the intricacies of drag and drop.

We will also need to disable this for certain exercises where the solution is already complicated enough, but that's the easy part of this issue.

Increasing motivation with gamification

I want to explore ways we can reward success to encourage better performance. For example there could be a page dedicated to statistics, progress, achievements, etc. Or we could show some rewarding graphics or animations on some occassions, like the confetti that currently shows when a user gets an output prediction question right.

Here are some things we can currently measure. I'm sure some of these are bad ideas, but I'm going to list everything I can think of just to get brain juices flowing:

  • Number of steps/exercises/pages completed
  • Exercises solved without looking at:
    • any hints
    • more than X hints
    • any kind of solution, including Parsons problems
    • the gradual reveal solution, regardless of how much was revealed
    • more than X% of the solution revealed
  • Steps completed without copy pasting
  • Outputs predicted correctly
    • On the first guess
    • Within two guesses
  • Speed of completing steps/exercises
  • Number of attempts to complete an exercise

An idea that really excites me is to encourage the user to explore and experiment and reward them for discovering new concepts, especially if they discover something before it's been covered in the course. For example, we could reward discovering:

  • Any new error message, whether syntax or runtime. Trying to break things is a great sign.
  • Mathematical operators, parentheses, floating point numbers, negative numbers, any calculation that produces a number with more than 20 digits...
  • Nested things: loops, if statements, function definitions, function calls, lists...

Thoughts? Ideas?

Show program and output in text

As you go through the course and run programs, you can see the results in the shell. That's fine at the time, but once you move on, the output gets replaced by the output of a different program. If you want to look back, either in the current page to the stuff you just saw or to review material in previous pages, you can't actually see what happened when you ran each program. It just shows this:

screencapture-localhost-3000-course-2020-10-21-15_38_20

Implementing #84 would help with this problem, making it easy to rerun past snippets. But that's still unnecessary effort, and could be especially annoying if you're currently trying to write a solution to an exercise. You could open another tab, but this isn't great and people may not think of it. Reviewing past material should be quick and easy, like reading a book. Users shouldn't have to repeat the work they've already done of running the code, they should be able to quickly skim through and find what they're looking for. Plus it means less load on the servers for us.

So what I'd like is for the output to be copied into the text as each step is completed. If the program wasn't already included in the text, that gets shown too. This also means that students can review their solutions to exercises. The example above would then roughly look something like this:

screencapture-localhost-3000-course-2020-10-21-15_49_15

I don't have any actual evidence that this is a serious problem, but I imagine the above would be a much nicer experience for a student reviewing the course than the first (current) screenshot.

Thoughts? Ideas?

Revisiting difficult exercises

In learning in general it's helpful to revisit problems which you struggled with in the past to make sure you've overcome the past difficulties. I think it would be good if the site had a page with a list of exercises the user didn't solve easily, in this order:

  • The user had to show the actual solution, starting with those where they revealed the greatest percentage of pieces.
  • The user solved the Parsons problem solution
  • The user had to request hints, starting with those where they got the most hints

Clicking on any such exercise in the list lets them easily redo the exercise as if they were doing it for the first time, including hints/solutions and the text steps that came before.

Any thoughts on this?

Output predictions in List Functions pages

Now that #73 is merged, I think we should use it in the new and improved pages about functions/methods for lists. For example, we currently have this:

Here's some new things. Try them out in the shell. Again suppose we have a list nums = [1, 2, 3].

  • subscript assignment: Set a value at an index. nums[0] = 9 changes the list to [9, 2, 3].

This should be changed to something like:

Here's some new things.

  • subscript assignment: Set a value at an index using the syntax some_list[index] = new_value. For example, run this program:
nums = [1, 2, 3]
nums[0] = 9
print(nums)

Then they have to pass a verbatim step with an appropriate predicted_output_choices. This is documented now under https://github.com/alexmojaki/futurecoder/blob/master/how_to_contribute.md#steps, it's pretty straightforward.

@spamegg1 I think it makes sense for you to do this, are you keen?

Specifying Python-specific information

Would it be worthwhile to mention that certain things (particularly types) are Python-specific? It could make the instructions more complicated, but it could reduce confusion in case users plan on using the same high-level concepts in other languages.

This isn't really for low-level stuff and wouldn't have anything to do with the compiler or the machine arch side of things, but instead for things like the following:

The values are often referred to as elements. They can be anything: numbers, strings, booleans, even lists! They can also be a mixture of types.

This could be rewritten as:

The values are often referred to as elements. They can be anything: numbers, strings, booleans, even lists! In Python, they can also be a mixture of types.

Suggesting fixes for syntax errors using sensibility

Continuing from #53 (comment)

In a nutshell for newcomers: https://github.com/naturalness/sensibility suggests fixes for syntax errors with machine learning, but training a Python model requires a lot of computation power. A pre-trained model for Python is not currently available.

  1. Do you have pre-trained models for any languages? It'd be nice just to be able to play with the code directly.
  2. Did you actually train and evaluate the model for Python at some point, or was that just some unfinished work in the repo?
  3. Can you give an idea of what the computational cost of the LSTM is like for prediction once the model has already been trained?

This idea has become less relevant now that we have friendly-tracebacks suggesting fixes for many common syntax errors.

Should we encourage or discourage copy/pasting code from the text into the editor/shell?

The text has a lot of steps that say "run this exact code". The easiest thing for the user to do is then select the code and copy and paste it.

The problem is that students learn and absorb much better if they manually type in the code (citation needed, too lazy right now). So I want to prevent or discourage copy/pasting.

On the other hand, students will get annoyed if they have to type in lots of code. Sometimes the code they have to run is quite long, and if they don't get it exactly right (except some small differences like spacing or quotes which are OK - the AST has to match) they won't proceed.

Possible courses of action:

  1. Prevent copying from the text entirely. Or conversely, prevent pasting into the editor/shell.
  2. Prevent copying certain snippets of code, particularly small ones.
  3. Allow all copying, but the first time a student does it, show a pop up suggesting that this is bad for learning and they should try to avoid it.
  4. Accept that students don't want to type code, and make it easier to run code without typing. This could be combined with either 2 (in cases that copying is allowed) or 3. We could provide a button that copies the code to the clipboard, or even a button that immediately runs the code in the shell/editor.

I prefer either 2 or 3. Thoughts? Ideas?

Next course chapters

This issue has been replaced by #92

The biggest thing to do is write the actual course!

This should be an informal, collaborative process. The course doesn't need to be written in the order that it's going to be presented, we can change things as we go, and any amount of brainstorming is useful. Even sharing a little code snippet to demonstrate a concept or a neat exercise is helpful. See below for an example.

If you want to contribute a solid bit of course with actual text, code, and exercises, open a new issue with a proposal just in markdown. Don't jump to implementing it in Python.

Before writing anything, it's a good idea to go through the course to know what's been covered and to get a feel for the style. You don't have to actually read everything or do all the exercises - see the developer mode instructions to skip steps. Reading all the hints on a few exercises would also help.

It can be helpful to read through existing textbooks and such to find inspiration for material. Make sure you have permission to copy their ideas (even if you rephrase it into different words) or that it's permissively licensed. If you're not sure, ask them. I don't want anyone to accuse us of plagiarism.

I'm not sure what exactly the next chapters should be at this stage, but here are some loosely related topics that I want to cover:

  • How to use the birdseye debugger - this will be helpful for understanding and and or correctly. Done
  • Boolean operators and, or, and not - these will be helpful for constructing more useful conditions for if and while. (currently being worked on in #27)
    • Must cover common misuse, e.g. if x == 1 or 2 instead of if x == 1 or x == 2. Birdseye can help here.
  • while. Start with a simple counter (contrast with for i in range), then another example with a proper condition (any ideas for a compelling example?), then while True.
  • Basics of types:
    • Different values have different types
    • These can be revealed with the type() function
    • Types include str, int, float, bool, and list.
    • Different types behave differently, e.g. + and < means different things for each, and each have different methods.
    • Different types are often 'incompatible', e.g. numbers and strings cannot be added, and == is always False.
    • How to convert between types, e.g. str to int and vice versa.
  • input() - goes well with while. Explain that it always returns a string, and must convert to int when needed. Has a volunteer in #61
  • Nested lists

Organisation and naming of pages

Previously you had to start the course at the beginning and go through it linearly. The course was written with that assumption in mind.

#38 changed that and allowed completing pages in any order. This means that users can jump to the middle and see concepts in use that were covered in previous pages they didn't read. Maybe they will know about those concepts from past experience, maybe not. The point is that it's especially important for users to be able to browse through the TOC and see which pages they can skip and which pages they need to read to learn about unfamiliar concepts.

With that in mind, a page should have a title clearly describing the important things it covers, and not cover too many unrelated important concepts.

The course needs to be revised to fix pages violating these principles. For example, the page "Using Variables" goes off-topic at the end. It should either be renamed to something like "Using Variables and print" or better, split off a new page "IntroducingPrint".

Note that the class name of a page is stored in the database to keep track of which page users are on. Therefore you mustn't rename or delete classes. To rename a page, set the title attribute on the class.

Clear messages after going forward a step

At each step, certain code can trigger displaying a message in the bottom left. For example, try typing something other than 1+2 in the first step.

These messages can be dismissed by clicking the X in the corner. They're also supposed to disappear when the user successfully advances a step. This was implemented, but is no longer working.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.