Dive in with Python puzzles

We're going to dive in headfirst by working on some puzzles in Python. In doing so, we'll get a taste of a lot of the objectives of the workshop. Prepare yourself — it's going to be a firehose! Please ask questions when you get stuck — that's when the learning happens. Afterwards, we'll reflect on and zoom in on elements of the whirlwind tour. (Note: some of these screenshots are outdated, but hopefully still clear enough. If not, please ask.) Follow these steps to get started:

Fork a copy of the repository

Head to the boothresearch/puzzles repository and click the "Fork" button in the top-right corner. You will first have to sign in to GitHub.

Click "Fork"

If you don't already have a GitHub account, you'll have to sign up before you can fork:

  • It's not super-important right now which email address you use, because you can and probably will add multiple email addresses to your GitHub account, eventually. But since we're using GitHub for work, it's probably good to use your work-related email address.

    • If you use a .edu address, you may qualify for the Student Developer Pack, which provides discounts to many services.

  • It's always a good idea to use a password manager, especially for work-related accounts. (Don't use one yet? I invite you to visit Have I Been Pwned and see whether your password has been cracked yet.)

  • For important accounts (e.g. your email, bank, GitHub, etc), it's a good idea to enable two-factor authentication (2FA). I use Authy to generate one-time passwords. Google Authenticator, Bitwarden, and 1Password are all good options for OTPs.

Once you're signed in, you can fork (i.e. make a copy on your own account) the repository (i.e. folder with our code in it):

Create fork

Set up a Codespace

We're going to use a service called Codespaces to edit and run our code. To set it up, click the green " <> Code" button, then the "+" icon in the Codespaces tab:

It will take a minute or two to set up, and then you'll be dropped into an Integrated Development Environment (IDE):

Read the README

There are 25 different puzzles to solve in this project. Let's start with leap. In the left sidebar, find the folder leap/ and within it click the file called README.md .

README.md is written in Markdown, a simple formatting language:

To view the rendered results, find the "Open Preview to the Side" icon in the top-right corner:

Or use the keyboard shortcut to Open Preview in the entire pane (Mac: Shift+Cmd+V, Windows: Ctrl+Cmd+V):

Read more about markdown, and find some tips & tricks, here. And check out this interactive tutorial. Markdown is going to be an essential tool in your belt. As we can see from leap/README.md, our task in this puzzle is to write a function that will check if a given year is a leap year or not. Let's get started.

Enable autosave

From the File menu, ensure that Autosave is enabled. This will save a lot of hassle:

Clear terminal

The pane at the bottom of the IDE is called the "terminal". It is where we will run and see the output of the code we write. You can use Cmd+J (Mac) / Ctrl+J (Windows) to show/hide the terminal.

As you work, it's very helpful to clear the output once in a while, to make it easier to see the output of just your last command. To clear your terminal, use Ctrl+L

Task list

Visit the Issues list on the parent repository. Imagine that I am your PI, and this is the list of tasks that I've defined for this project.

For example, one of the tasks is to figure out the puzzle in the folder leap/

GitHub Issues is a very powerful and common way of documenting what work needs done.

Create a new branch

Whenever we start on a new task, the first thing we should do is create a new branch (i.e. version).

At the terminal prompt ($), type something like:

git checkout -b pick-a-name-for-your-branch

My convention is to start my branch names with the number if the Issue which I am trying to tackle (in this case, it's issue #75). If there is no Issue, then I often start the branch name with rb- (my initials) and then a brief description of the task at hand. Branch names should contain only letters, numbers, and dashes; e.g., 75-rb-leap:

Start working

Let's run leap.py to see what it does at the moment. First, we have to navigate into the leap folder with cd leap (read more about navigating using the command-line here). Then, we can run the program with the python3 command:

python3 leap.py

It looks like it doesn't do much of anything right now. Let's check out the source code in leap/leap.py and replace the pass keyword with some code:

Run interactively

Using print to see what our code is doing is nice, but another technique is to leave the print statement out and run the program interactively with the -i flag. I find that running the program interactively makes it easier to test the function that I'm writing with various inputs.:

Checking your work

Let's keep enhancing:

Nice! Are we done? Is it correct? How would we know?

In this project, we've included a program you can run called pytest. Try it out:

There's a lot of output here, but essentially: the FF.... is telling us that our code isn't quite right yet. The red FF means two tests failed, and the .... means that four tests passed.

The tests themselves live in a file called leap/leap_test.py . Go have a look — there's a lot of stuff in there, but the key lines are the ones that look like this:

self.assertIs(leap_year(2015), False)
self.assertIs(leap_year(1970), False)

Read these assertions to help understand what our function is missing, and then go make each test pass. Run pytest to check your work, until all of the tests are passing:

def leap_year(year):
    if year % 400 == 0:
        return True
    elif year % 100 == 0:
        return False
    elif year % 4 == 0:
        return True
    else:
        return False

Commit your work

Once we're done with our task, we should make a commit (save a snapshot of all of the changes we made). Type the following commands:

git add -A
git commit -m "Complete leap.py"

Push to GitHub

Then, we need to push (send our work back to GitHub.com) our commit, to back it up safely and share it with our team. Do so with the command git push (At first, git push may not work. Copy-paste the helpful guidance it provides to set an upstream, and then it should go through.)

Create a pull request

The next step in our workflow is to make a pull request. This is a place to review our work and get feedback on it from our team.

Visit the URL that was suggested in the terminal after we pushed (you can Cmd+click on it to open it in a new tab) and create a pull request. (Or, visit the page for your fork, and you'll see a yellow banner at the top to create a pull request.)

In the Pull Request description, we try to write as much as needed to help our team provide us with feedback. For now, let's just note down which Issue we were working on by saying "Resolves #75". Now, we wait for feedback on/approval of our work from our team. While we're waiting, let's work on something else!

Start on the next task

Next, let's work on darts. Whenever we start on a new, discrete task:

  • Switch back to the original branch: git checkout main

  • Notice that the work we did in leap.py is gone. That's good, because we want the work we do on darts.py to be independent of the work we did in leap.py, until our team approves it.

  • Get the freshest version of main from GitHub (in case our teammates have shipped any new code): git pull

  • Then, create a new branch as we did before, with git checkout -b

  • Since the next task is darts, which is Issue #77, I am going to name my branch rb-77-darts

Follow all of the same steps that we did before:

  • Read the rendered README to get a sense of the task.

  • Run the program interactively as you build it up so that you can test it manually.

  • Use pytest to test it automatically.

  • Read the assertions in the test file to understand precisely what the function is supposed to do.

  • Once done, make a commit, push to GitHub, and open a pull request.

  • Before starting on the next task, switch back to the main branch, and then check out a new branch.

  • Rinse and repeat.

Chat with an AI assistant

Are you stuck on a syntax error, or want to brainstorm ways to improve a solution? Let's try chatting with an AI assistant.

In the left sidebar, find the Extensions button. Search for "Cody AI" and install it:

A new button will appear in the left sidebar that looks like a winking smiley face. Click on that, and then click each of the three links displayed to sign up for a free account, generate an access token, and add the access token.

Finally, you'll be able to chat with Cody:

What makes Cody particularly powerful is that it has access to the entire repository when answering your questions. This makes it really helpful for understanding the structure of a project that you're new to (more so than, say, ChatGPT, which doesn't have all the context needed to explain the project well). Get more ideas of how to use it here.

Practice the workflow

The puzzles, in very approximate order of difficulty, are:

  • leap

  • darts

  • collatz-conjecture

  • scrabble-score

  • anagram

  • acronym

  • isogram

  • pangram

  • word-count

  • rotational-cipher

  • atbash-cipher

  • isbn-verifier

  • pig-latin

  • roman-numerals

  • run-length-encoding

  • say

  • matrix

  • phone-number

  • luhn

  • matching-brackets

  • poker

  • affine-cipher

  • change

  • bowling

  • book-store

Feel free to jump around, but if you're new to Python, you should probably stay near the top of the list. If you're already a Python expert, you can challenge yourself with some of the later ones.

Practice the git branching/pushing/pull-request workflow while completing as many puzzles as you can.

That was a lot! Jot down things that you encountered that you would like to discuss.

Python references

Last updated

Was this helpful?