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.

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.)
As of September 2024, Apple has added an official password manager app (finally).
Google has a web Password Manager.
Bitwarden is another good option and has a free tier.
I use 1Password (paid), but I probably would have used one of the above had they existed sooner.
A really handy feature of password managers is that you can use them across your devices; e.g. autofilling passwords on iOS.
Bottomline: use a password manager to generate strong, unique passwords for every service you use.
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):

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 ondarts.py
to be independent of the work we did inleap.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
DataCamp's Introduction to Python
DataCamp's Intermediate Python for Data Science
Last updated
Was this helpful?