Compare commits

...

6 Commits

Author SHA1 Message Date
Peter Norvig
6e45084acb Add files via upload 2026-04-25 09:54:04 -07:00
Peter Norvig
ce990774bc Add files via upload 2026-04-25 09:50:53 -07:00
Peter Norvig
721a7954b4 Remove year highlighting for current year 2026-04-25 09:44:39 -07:00
Peter Norvig
7cebfa6149 Add new puzzles and games to pytudes.py 2026-04-25 09:28:35 -07:00
github-actions[bot]
9b965630ac docs: auto-update README.md via pytudes.py 2026-04-25 16:23:16 +00:00
Peter Norvig
1bc1ce5cb9 Update Sudoku Java puzzle speed from 100k to 200k 2026-04-25 09:23:02 -07:00
3 changed files with 725 additions and 5 deletions

View File

@@ -26,7 +26,9 @@ For each notebook you can hover on the title to see a description, or click the
|Run|Year|New| |Run|Year|New|
|---|---|---| |---|---|---|
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FTruncatablePrimes.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FTruncatablePrimes.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) | <u>2026</u> | <a href="ipynb/TruncatablePrimes.ipynb" title="Prime numbers where you can remove digits and still get primes.">Truncatable Primes</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/clvr.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2Fclvr.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2Fclvr.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/clvr.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/clvr.ipynb) | 2026 | <a href="ipynb/clvr.ipynb" title="Guess famous phrases from letter shapes. Beginner level.">Did you solve it? R y clvr ngh t rd ths sntnc?</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Euler3.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FEuler3.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FEuler3.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Euler3.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Euler3.ipynb) | 2026 | <a href="ipynb/Euler3.ipynb" title="Find the largest prime factor of a number">Project Euler #3: Largest prime factor</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FTruncatablePrimes.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FTruncatablePrimes.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) | 2026 | <a href="ipynb/TruncatablePrimes.ipynb" title="Prime numbers where you can remove digits and still get primes.">Truncatable Primes</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Advent-2025.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FAdvent-2025.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FAdvent-2025.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Advent-2025.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Advent-2025.ipynb) | 2025 | <a href="ipynb/Advent-2025.ipynb" title="Puzzle site with a coding puzzle for 12 days of Christmas, December 2025">Advent of Code 2025</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Advent-2025.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FAdvent-2025.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FAdvent-2025.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Advent-2025.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Advent-2025.ipynb) | 2025 | <a href="ipynb/Advent-2025.ipynb" title="Puzzle site with a coding puzzle for 12 days of Christmas, December 2025">Advent of Code 2025</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Advent-2025-AI.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FAdvent-2025-AI.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FAdvent-2025-AI.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Advent-2025-AI.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Advent-2025-AI.ipynb) | 2025 | <a href="ipynb/Advent-2025-AI.ipynb" title="Using large language coding models to solve AoC puzzles">Advent of Code 2025: AI LLM Edition</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Advent-2025-AI.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FAdvent-2025-AI.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FAdvent-2025-AI.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Advent-2025-AI.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Advent-2025-AI.ipynb) | 2025 | <a href="ipynb/Advent-2025-AI.ipynb" title="Using large language coding models to solve AoC puzzles">Advent of Code 2025: AI LLM Edition</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Advent-2024.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FAdvent-2024.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FAdvent-2024.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Advent-2024.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Advent-2024.ipynb) | 2024 | <a href="ipynb/Advent-2024.ipynb" title="Puzzle site with a coding puzzle each day of Advent, December 2024">Advent of Code 2024</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Advent-2024.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FAdvent-2024.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FAdvent-2024.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Advent-2024.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Advent-2024.ipynb) | 2024 | <a href="ipynb/Advent-2024.ipynb" title="Puzzle site with a coding puzzle each day of Advent, December 2024">Advent of Code 2024</a> |
@@ -97,13 +99,14 @@ For each notebook you can hover on the title to see a description, or click the
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/How%20To%20Count%20Things.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FHow%20To%20Count%20Things.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FHow%20To%20Count%20Things.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/How%20To%20Count%20Things.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/How%20To%20Count%20Things.ipynb) | 2020 | <a href="ipynb/How%20To%20Count%20Things.ipynb" title="Combinatorial math: how to count how many things there are, when there are a lot of them">How to Count Things</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/How%20To%20Count%20Things.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FHow%20To%20Count%20Things.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FHow%20To%20Count%20Things.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/How%20To%20Count%20Things.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/How%20To%20Count%20Things.ipynb) | 2020 | <a href="ipynb/How%20To%20Count%20Things.ipynb" title="Combinatorial math: how to count how many things there are, when there are a lot of them">How to Count Things</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/KenKen.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FKenKen.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FKenKen.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/KenKen.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/KenKen.ipynb) | 2021 | <a href="ipynb/KenKen.ipynb" title="A Sudoku-like puzzle, but with arithmetic.">KenKen (Sudoku-like Puzzle)</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/KenKen.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FKenKen.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FKenKen.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/KenKen.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/KenKen.ipynb) | 2021 | <a href="ipynb/KenKen.ipynb" title="A Sudoku-like puzzle, but with arithmetic.">KenKen (Sudoku-like Puzzle)</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/NumberBracelets.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FNumberBracelets.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FNumberBracelets.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/NumberBracelets.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/NumberBracelets.ipynb) | 2024 | <a href="ipynb/NumberBracelets.ipynb" title="A game involving numbered beads on a circular bracelet.">Number Bracelets Game</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/NumberBracelets.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FNumberBracelets.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FNumberBracelets.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/NumberBracelets.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/NumberBracelets.ipynb) | 2024 | <a href="ipynb/NumberBracelets.ipynb" title="A game involving numbered beads on a circular bracelet.">Number Bracelets Game</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Euler3.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FEuler3.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FEuler3.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Euler3.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Euler3.ipynb) | 2026 | <a href="ipynb/Euler3.ipynb" title="Find the largest prime factor of a number">Project Euler #3: Largest prime factor</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Socks.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSocks.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSocks.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Socks.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Socks.ipynb) | 2019 | <a href="ipynb/Socks.ipynb" title="What is the probability that you will be able to pair up socks as you randomly pull them out of the dryer?">Pairing Socks</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Socks.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSocks.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSocks.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Socks.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Socks.ipynb) | 2019 | <a href="ipynb/Socks.ipynb" title="What is the probability that you will be able to pair up socks as you randomly pull them out of the dryer?">Pairing Socks</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Sicherman%20Dice.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSicherman%20Dice.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSicherman%20Dice.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Sicherman%20Dice.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Sicherman%20Dice.ipynb) | 2018 | <a href="ipynb/Sicherman%20Dice.ipynb" title="Find a pair of dice that is like a regular pair of dice, only different">Sicherman Dice</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Sicherman%20Dice.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSicherman%20Dice.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSicherman%20Dice.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Sicherman%20Dice.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Sicherman%20Dice.ipynb) | 2018 | <a href="ipynb/Sicherman%20Dice.ipynb" title="Find a pair of dice that is like a regular pair of dice, only different">Sicherman Dice</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Golomb-Puzzle.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FGolomb-Puzzle.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FGolomb-Puzzle.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Golomb-Puzzle.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Golomb-Puzzle.ipynb) | 2014 | <a href="ipynb/Golomb-Puzzle.ipynb" title="A Puzzle involving placing rectangles of different sizes inside a square">Sol Golomb's Rectangle Puzzle</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Golomb-Puzzle.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FGolomb-Puzzle.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FGolomb-Puzzle.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Golomb-Puzzle.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Golomb-Puzzle.ipynb) | 2014 | <a href="ipynb/Golomb-Puzzle.ipynb" title="A Puzzle involving placing rectangles of different sizes inside a square">Sol Golomb's Rectangle Puzzle</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Stubborn.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FStubborn.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FStubborn.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Stubborn.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Stubborn.ipynb) | 2024 | <a href="ipynb/Stubborn.ipynb" title="Any number ending in 5 has a square that also ends in 5. What other endings are like this?">Stubborn number endings</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Stubborn.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FStubborn.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FStubborn.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Stubborn.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Stubborn.ipynb) | 2024 | <a href="ipynb/Stubborn.ipynb" title="Any number ending in 5 has a square that also ends in 5. What other endings are like this?">Stubborn number endings</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/StarBattle.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FStarBattle.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FStarBattle.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/StarBattle.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/StarBattle.ipynb) | 2021 | <a href="ipynb/StarBattle.ipynb" title="Fill-in-the-grid puzzle similar to Sudoku">Star Battle (Sudoku-like Puzzle)</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/StarBattle.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FStarBattle.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FStarBattle.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/StarBattle.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/StarBattle.ipynb) | 2021 | <a href="ipynb/StarBattle.ipynb" title="Fill-in-the-grid puzzle similar to Sudoku">Star Battle (Sudoku-like Puzzle)</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Sudoku.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSudoku.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSudoku.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Sudoku.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Sudoku.ipynb) | 2006 | <a href="ipynb/Sudoku.ipynb" title="Classic fill-in-the-grid puzzle">Sudoku</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Sudoku.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSudoku.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSudoku.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Sudoku.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Sudoku.ipynb) | 2006 | <a href="ipynb/Sudoku.ipynb" title="Classic fill-in-the-grid puzzle">Sudoku</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/SudokuJava.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSudokuJava.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSudokuJava.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/SudokuJava.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/SudokuJava.ipynb) | 2021 | <a href="ipynb/SudokuJava.ipynb" title="A version of the Sudoku solver using parallel threads and other optimizations">Sudoku: 100,000 puzzles/second in Java</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/SudokuJava.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSudokuJava.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSudokuJava.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/SudokuJava.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/SudokuJava.ipynb) | 2021 | <a href="ipynb/SudokuJava.ipynb" title="A version of the Sudoku solver using parallel threads and other optimizations">Sudoku: 200,000 puzzles/second in Java</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/SquareSum.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSquareSum.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSquareSum.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/SquareSum.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/SquareSum.ipynb) | 2020 | <a href="ipynb/SquareSum.ipynb" title="Place the numbers from 1 to n in a chain (or a circle) such that adjacent pairs sum to a perfect square">Square Sum Puzzle</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/SquareSum.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSquareSum.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSquareSum.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/SquareSum.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/SquareSum.ipynb) | 2020 | <a href="ipynb/SquareSum.ipynb" title="Place the numbers from 1 to n in a chain (or a circle) such that adjacent pairs sum to a perfect square">Square Sum Puzzle</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Cheryl.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FCheryl.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FCheryl.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Cheryl.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Cheryl.ipynb) | 2020 | <a href="ipynb/Cheryl.ipynb" title="Solving the *Cheryl's Birthday* logic puzzle">When is Cheryl's Birthday?</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Cheryl.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FCheryl.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FCheryl.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Cheryl.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Cheryl.ipynb) | 2020 | <a href="ipynb/Cheryl.ipynb" title="Solving the *Cheryl's Birthday* logic puzzle">When is Cheryl's Birthday?</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Cheryl-and-Eve.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FCheryl-and-Eve.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FCheryl-and-Eve.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Cheryl-and-Eve.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Cheryl-and-Eve.ipynb) | 2015 | <a href="ipynb/Cheryl-and-Eve.ipynb" title="Inventing new puzzles in the Style of Cheryl's Birthday">When Cheryl Met Eve: A Birthday Story</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Cheryl-and-Eve.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FCheryl-and-Eve.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FCheryl-and-Eve.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Cheryl-and-Eve.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Cheryl-and-Eve.ipynb) | 2015 | <a href="ipynb/Cheryl-and-Eve.ipynb" title="Inventing new puzzles in the Style of Cheryl's Birthday">When Cheryl Met Eve: A Birthday Story</a> |
@@ -116,6 +119,7 @@ For each notebook you can hover on the title to see a description, or click the
|---|---|---| |---|---|---|
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Boggle.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FBoggle.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FBoggle.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Boggle.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Boggle.ipynb) | 2020 | <a href="ipynb/Boggle.ipynb" title="Find all the words on a Boggle board; then find a board with a lot of words">Boggle / Inverse Boggle</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Boggle.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FBoggle.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FBoggle.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Boggle.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Boggle.ipynb) | 2020 | <a href="ipynb/Boggle.ipynb" title="Find all the words on a Boggle board; then find a board with a lot of words">Boggle / Inverse Boggle</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/ElementSpelling.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FElementSpelling.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FElementSpelling.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/ElementSpelling.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/ElementSpelling.ipynb) | 2020 | <a href="ipynb/ElementSpelling.ipynb" title="Spelling words using the chemical element symbols, like CoIn">Chemical Element Spelling</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/ElementSpelling.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FElementSpelling.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FElementSpelling.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/ElementSpelling.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/ElementSpelling.ipynb) | 2020 | <a href="ipynb/ElementSpelling.ipynb" title="Spelling words using the chemical element symbols, like CoIn">Chemical Element Spelling</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/clvr.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2Fclvr.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2Fclvr.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/clvr.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/clvr.ipynb) | 2026 | <a href="ipynb/clvr.ipynb" title="Guess famous phrases from letter shapes. Beginner level.">Did you solve it? R y clvr ngh t rd ths sntnc?</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/equilength-numbers.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2Fequilength-numbers.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2Fequilength-numbers.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/equilength-numbers.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/equilength-numbers.ipynb) | 2020 | <a href="ipynb/equilength-numbers.ipynb" title="What number names have the same letter count as the number they name (such as FOUR)?">Equilength Numbers: FOUR = 4</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/equilength-numbers.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2Fequilength-numbers.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2Fequilength-numbers.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/equilength-numbers.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/equilength-numbers.ipynb) | 2020 | <a href="ipynb/equilength-numbers.ipynb" title="What number names have the same letter count as the number they name (such as FOUR)?">Equilength Numbers: FOUR = 4</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Gesture%20Typing.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FGesture%20Typing.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FGesture%20Typing.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Gesture%20Typing.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Gesture%20Typing.ipynb) | 2017 | <a href="ipynb/Gesture%20Typing.ipynb" title="What word has the longest path on a gesture-typing smartphone keyboard?">Gesture Typing</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Gesture%20Typing.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FGesture%20Typing.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FGesture%20Typing.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Gesture%20Typing.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Gesture%20Typing.ipynb) | 2017 | <a href="ipynb/Gesture%20Typing.ipynb" title="What word has the longest path on a gesture-typing smartphone keyboard?">Gesture Typing</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Ghost.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FGhost.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FGhost.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Ghost.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Ghost.ipynb) | 2017 | <a href="ipynb/Ghost.ipynb" title="The word game Ghost (add letters, try to avoid making a word)">Ghost: A Word game</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Ghost.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FGhost.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FGhost.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Ghost.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Ghost.ipynb) | 2017 | <a href="ipynb/Ghost.ipynb" title="The word game Ghost (add letters, try to avoid making a word)">Ghost: A Word game</a> |
@@ -159,7 +163,7 @@ For each notebook you can hover on the title to see a description, or click the
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Differentiation.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FDifferentiation.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FDifferentiation.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Differentiation.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Differentiation.ipynb) | 2017 | <a href="ipynb/Differentiation.ipynb" title="A computer algebra system, including symbolic differentiation">Symbolic Algebra, Simplification, and Differentiation</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Differentiation.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FDifferentiation.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FDifferentiation.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Differentiation.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Differentiation.ipynb) | 2017 | <a href="ipynb/Differentiation.ipynb" title="A computer algebra system, including symbolic differentiation">Symbolic Algebra, Simplification, and Differentiation</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Snobol.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSnobol.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSnobol.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Snobol.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Snobol.ipynb) | 2017 | <a href="ipynb/Snobol.ipynb" title="As a student, did you ever get a bad grade on a programming assignment?">Snobol: Bad Grade, Good Experience</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/Snobol.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FSnobol.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FSnobol.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/Snobol.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/Snobol.ipynb) | 2017 | <a href="ipynb/Snobol.ipynb" title="As a student, did you ever get a bad grade on a programming assignment?">Snobol: Bad Grade, Good Experience</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/TSP.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FTSP.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FTSP.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/TSP.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/TSP.ipynb) | 2018 | <a href="ipynb/TSP.ipynb" title="Another of the classics">Traveling Salesperson Problem</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/TSP.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FTSP.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FTSP.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/TSP.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/TSP.ipynb) | 2018 | <a href="ipynb/TSP.ipynb" title="Another of the classics">Traveling Salesperson Problem</a> |
| [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FTruncatablePrimes.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FTruncatablePrimes.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) | <u>2026</u> | <a href="ipynb/TruncatablePrimes.ipynb" title="Prime numbers where you can remove digits and still get primes.">Truncatable Primes</a> | | [C](https://colab.research.google.com/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [D](https://beta.deepnote.org/launch?template=python_3.6&url=https%3A%2F%2Fgithub.com%2Fnorvig%2Fpytudes%2Fblob%2Fmain%2Fipynb%2FTruncatablePrimes.ipynb) [M](https://mybinder.org/v2/gh/norvig/pytudes/main?filepath=ipynb%2FTruncatablePrimes.ipynb) [N](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) [S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes/blob/main/ipynb/TruncatablePrimes.ipynb) | 2026 | <a href="ipynb/TruncatablePrimes.ipynb" title="Prime numbers where you can remove digits and still get primes.">Truncatable Primes</a> |
# Index of Python Files # Index of Python Files

715
ipynb/clvr.ipynb Normal file
View File

@@ -0,0 +1,715 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9e54c615-5dab-4642-924f-f2840558ff9e",
"metadata": {},
"source": [
"<div align=\"right\" style=\"text-align: right\"><i>Peter Norvig<br>April 2026</i></div>\n",
"\n",
"# Did you solve it? R y clvr ngh t rd ths sntnc?\n",
"\n",
"Alex Bellos's [30 March 2026 column](https://www.theguardian.com/science/2026/mar/30/did-you-solve-it-r-y-clvr-ngh-t-rd-ths-sntnc) asks us to guess famous phrases or sayings, given the shapes of the rectangles that bound the letters, and the clue that vowels are <span style=\"color:green\">**green**</span> and consonants are <span style=\"color:blue\">**blue**</span>. \n",
"\n",
"Here's one of the puzzles:\n",
"\n",
"![](https://i.guim.co.uk/img/media/dd62fe8dfdc6eb9d98815a2e14791ae268aa4d46/0_0_580_75/master/580.jpg?width=310&dpr=2&s=none&crop=none)"
]
},
{
"cell_type": "markdown",
"id": "6a2c1014-5894-4bf0-b4b3-5f1d1561fa2a",
"metadata": {},
"source": [
"I can help solve this problem by using code to constrain what each letter and each word might be.\n",
"\n",
"I'll start by defining different subsets of letters: `v` for the vowels, `c` for the consonants, `a` for the letters whose shape ascends above the norm, etc.:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "628d38c1-0671-49dd-9897-7bd5eff196ee",
"metadata": {},
"outputs": [],
"source": [
"letters = set('abcdefghijklmnopqrstuvwxyz')\n",
"v = set('aeiou') # vowels (green)\n",
"c = letters - v # consonants (blue)\n",
"\n",
"a = set('bdfhijlt') # ascending\n",
"d = set('gjpqy') # descending\n",
"b = letters - a - d # block: neither ascending nor descending\n",
"\n",
"t = set('li') # thin\n",
"w = set('mw') # wide\n",
"n = letters - t - w # normal: neither wide nor thin"
]
},
{
"cell_type": "markdown",
"id": "f51d68da-7569-4bdd-97a2-3c245e143c70",
"metadata": {},
"source": [
"Now I can say that the first letter of the first word above (the green rectangle) is a block-shaped vowel; the intersection of the **b**lock and **v**owel sets, denoted in Python with the `&` operator:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1f17f9ce-0e88-464d-80e6-53a458b3594b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'a', 'e', 'o', 'u'}"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b&v"
]
},
{
"cell_type": "markdown",
"id": "de4886ea-0244-4582-8a43-9fae9daceb9a",
"metadata": {},
"source": [
"The first word has three letters, `b&v` followed by two **a**scending **t**hin **c**onsonants, `a&t&c`:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "df3a9acf-e4df-42eb-8eb0-61fbdda7b598",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'a', 'e', 'o', 'u'}, {'l'}, {'l'}]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[b&v, a&t&c, a&t&c]"
]
},
{
"cell_type": "markdown",
"id": "b3945fa3-587c-4155-b201-ed7aa55510e5",
"metadata": {},
"source": [
"Neat! There is only one **a**scending **t**hin **c**onsonant, `'l'`.\n",
"\n",
"The whole puzzle is as follows (I made the apostrophe be a word of its own):"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "b4b5bb61-08f6-4815-9f46-ff1dd8e5816c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[{'a', 'e', 'o', 'u'}, {'l'}, {'l'}],\n",
" [{'b', 'd', 'f', 'h', 'j', 'l', 't'},\n",
" {'b', 'd', 'f', 'h', 'j', 'l', 't'},\n",
" {'a', 'e', 'o', 'u'}],\n",
" [{'m', 'w'},\n",
" {'a', 'e', 'o', 'u'},\n",
" {'c', 'k', 'm', 'n', 'r', 's', 'v', 'w', 'x', 'z'},\n",
" {'b', 'd', 'f', 'h', 'j', 'l', 't'},\n",
" {'b', 'd', 'f', 'h', 'j', 'l', 't'}],\n",
" [{''}],\n",
" [{'c', 'k', 'm', 'n', 'r', 's', 'v', 'w', 'x', 'z'}],\n",
" [{'a', 'e', 'o', 'u'}],\n",
" [{'c', 'k', 'm', 'n', 'r', 's', 'v', 'w', 'x', 'z'},\n",
" {'b', 'd', 'f', 'h', 'j', 'l', 't'},\n",
" {'a', 'e', 'o', 'u'},\n",
" {'g', 'j', 'p', 'q', 'y'},\n",
" {'a', 'e', 'o', 'u'}]]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"puzzle3 = [[b&v, a&t&c, a&t&c], [a&c, a&c, b&v], [w&c, b&v, b&c, a&c, a&c], [{\"\"}], [b&c], [b&v], [b&c, a&c, b&v, d&c, b&v]]\n",
"puzzle3"
]
},
{
"cell_type": "markdown",
"id": "50586a9e-2a63-4c43-858e-509e783aa99f",
"metadata": {},
"source": [
"## Possible Words\n",
"\n",
"What combinations of letters can each word pattern make? The function `possible_words` goes through the pattern one letter set at a time and builds up all possible ways of adding each possible letter to each possible partial word string:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "664292e4-416c-4408-bc9a-a5df0f2ede08",
"metadata": {},
"outputs": [],
"source": [
"def possible_words(pattern: list[set[str]]) -> set[str]:\n",
" \"\"\"All ways of choosing one letter from each of the possible letters in the word pattern.\"\"\"\n",
" words = {''} # To start there is one possible partial word, with no letters\n",
" for letter_set in pattern:\n",
" # On each turn, add each possible letter to each possible partial word\n",
" words = {word + letter for word in words for letter in letter_set}\n",
" return words"
]
},
{
"cell_type": "markdown",
"id": "c3de036e-7ca3-45f5-99ca-ead670ced8a0",
"metadata": {},
"source": [
"For example,"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "2743ba3a-0474-4f04-91cf-7ea57550b74c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'all', 'ell', 'oll', 'ull'}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"possible_words([b&v, a&t&c, a&t&c])"
]
},
{
"cell_type": "markdown",
"id": "d213da56-3d0b-4344-ab09-6a676b11a1f2",
"metadata": {},
"source": [
"Another example:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0a8cb3da-3d3d-4241-9d22-8b50c16aeb8d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'ban', 'bat', 'bon', 'bot', 'can', 'cat', 'con', 'cot'}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"possible_words([{'b', 'c'}, {'a', 'o'}, {'n', 't'}])"
]
},
{
"cell_type": "markdown",
"id": "799abea2-83a4-4d71-bd04-270ff056249a",
"metadata": {},
"source": [
"Let's trace through how `possible_words` works on this example. It starts with one possible partial word, the empty string:\n",
"\n",
" words = {''}\n",
"\n",
"Then it enterts the `for` loop and looks at the first letter set, `{'b', 'c'}`, and adds each letter to each partial word (just one of them: the empty string) to get a set of two partial words:\n",
"\n",
" words = {'b', 'c'}\n",
"\n",
"It does the same thing with the second letter set, `{'a', 'o'}`, to get a set of four partial words:\n",
"\n",
" words = {'ba', 'bo', 'ca', 'co'}\n",
"\n",
"Finally, it considers the third letter set, `{'n', 't'}`, and gets the final answer, a set of eight words:\n",
"\n",
" words = {'ban', 'bat', 'bon', 'bot', 'can', 'cat', 'con', 'cot'}\n",
"\n",
"## Dictionary Words\n",
"\n",
"What actual dictionary words could a pattern stand for? To answer that I'll need a list of actual dictionary words. Furthermore, when `possible_words(pattern)` returns more than one word, I'll have to pick one. To facilitate that, I will use a word list that includes the frequency of each word so that I can pick the word with the highest frequency. \n",
"\n",
"I'll download the word list file \"[count_big.txt](count_big.txt)\" which has the format: \n",
"\n",
" a 21160\n",
" aah 1\n",
" aaron 5\n",
" ab 2\n",
" aback 3\n",
" abacus 1\n",
" abandon 32\n",
" abandoned 72\n",
" abandoning 27\n",
" abandonment 15\n",
"\n",
"A few things to note about the following command (but you don't need to memorize):\n",
"- The `!` at the start of a line means to do an operating system command, not a Python command.\n",
"- The `[ -e count_big.txt ] ||` part says to skip downloading the file if it already exists.\n",
"- The `curl` command downloads the file\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "4b0b245b-5085-492e-b3c3-902f2d8ae723",
"metadata": {},
"outputs": [],
"source": [
"! [ -e count_big.txt ] || curl -O https://norvig.com/ngrams/count_big.txt"
]
},
{
"cell_type": "markdown",
"id": "65006749-5475-434c-a6bb-aab8c81e6e0b",
"metadata": {},
"source": [
"I'll read the contents of the file into a Python dictionary, which will have the form `{'a': 21160, 'aah': 1, ...}`. "
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "c863b2e8-4e81-4c13-bd62-2aa7be38ad92",
"metadata": {},
"outputs": [],
"source": [
"def make_dictionary(lines) -> dict:\n",
" \"\"\"The lines are strings with a word and a frequency count; make it into a dict.\"\"\"\n",
" counts = {} # Start with an emoty dict\n",
" for line in lines:\n",
" word, count = line.split()\n",
" counts[word] = int(count)\n",
" return counts\n",
"\n",
"dictionary = make_dictionary(open('count_big.txt'))"
]
},
{
"cell_type": "markdown",
"id": "a5939c3b-b99a-4e8d-9cf5-9f4e8eb1533f",
"metadata": {},
"source": [
"Here are some things you can do with the dictionary:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "9edff66d-8668-4408-b636-a2aec0614fcb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"'aback' in dictionary"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "cae82016-a5d1-4fac-9e4d-75029e506f67",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"'the' in dictionary"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "8bf5eb96-7502-4568-bba0-71313f481e99",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"'xyzzy!@#$' in dictionary"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "5cbaf8af-a4eb-4390-b0f2-0bb0e32426ca",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"80030"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dictionary['the'] # get the frequency count"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "d1919007-f2e6-484a-a078-c9dd805a17c2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"80030"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dictionary.get('the', 0) # Get the count, with a default of 0 if word is not in dictionary"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "b137e272-9f34-4ecc-9131-934304a4f5b2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dictionary.get('xyzzy!@#$', 0) # Get the count, with a default of 0 if word is not in dictionary"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "5e10a770-0945-48c7-ad37-826f2e42a2b1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"29136"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(dictionary) # the number of words in the dictionary"
]
},
{
"cell_type": "markdown",
"id": "3662284a-b83e-4122-9896-831fc8580a87",
"metadata": {},
"source": [
"Now I want to take a pattern and figure out the most likely word (which I will guess is the most frequent one):"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "fea1a704-ab79-4204-bd89-506e66c12042",
"metadata": {},
"outputs": [],
"source": [
"def most_likely_word(pattern: list[set[str]]) -> str:\n",
" \"\"\"Out of all the possible words the pattern can make, pick the most frequent one.\"\"\"\n",
" return max(possible_words(pattern), key=frequency)\n",
"\n",
"def frequency(word) -> int: \n",
" \"\"\"The frequency count of the word in the dictionary, or 0 by default.\"\"\"\n",
" return dictionary.get(word, 0) "
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "a7cbb472-ce03-4239-b64f-ee1f8cbe02e3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'all'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"most_likely_word([b&v, a&t&c, a&t&c])"
]
},
{
"cell_type": "markdown",
"id": "d78f5702-9064-4a50-822e-f6ad89a16497",
"metadata": {},
"source": [
"So far, so good!\n",
"\n",
"A puzzle consists of a list of word patterns, and we can generate a best guess at solving the puzzle by finding the `most_likely_word` for each word pattern, and then joining them into a big string."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "b6f70f1d-5f16-4d80-bb95-fc8b01ab57df",
"metadata": {},
"outputs": [],
"source": [
"def solve(puzzle: list[list[set[str]]]) -> str:\n",
" \"\"\"Given a puzzle (a list of word patterns), return a string formed from the most likely matching words.\"\"\"\n",
" return ' '.join(most_likely_word(pattern) for pattern in puzzle)"
]
},
{
"cell_type": "markdown",
"id": "316692e0-244f-4715-bec9-f6e7babcd036",
"metadata": {},
"source": [
"## Puzzle #3\n",
"\n",
"We're ready to see if our program can solve the puzzle:\n",
"\n",
"![](https://i.guim.co.uk/img/media/dd62fe8dfdc6eb9d98815a2e14791ae268aa4d46/0_0_580_75/master/580.jpg?width=310&dpr=2&s=none&crop=none)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "42054f45-a8af-4513-a5d0-f097b2acda02",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'all the world s a stage'"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"solve(puzzle3) "
]
},
{
"cell_type": "markdown",
"id": "8e3b7a2a-259c-463f-b542-5c095c559516",
"metadata": {},
"source": [
"It worked! Let's do another one:\n",
"\n",
"## Puzzle #1\n",
"\n",
"![](https://i.guim.co.uk/img/media/a54abfc70c03cf9bc40e178c4e6186915b97ea1e/0_0_580_75/master/580.jpg?width=310&dpr=2&s=none&crop=none)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "688d1a5c-2770-4dd1-b8db-5d535949f909",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'all s well that ends well'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"solve([[b&v, a&t&c, a&t&c], [{\"\"}], [b&c], [w&c, b&v, t&c, t&c], [a&c, a&c, b&v, a&c], [b&v, b&c, a&c, b&c], [w&c, b&v, t&c, t&c]])"
]
},
{
"cell_type": "markdown",
"id": "47db30ff-a96a-47d7-a4a0-34fe29dad4db",
"metadata": {},
"source": [
"That's correct!\n",
"\n",
"## Puzzle #8\n",
"\n",
" ![](https://i.guim.co.uk/img/media/3eba3f724bda55abf76c8bca57f645cd5a669aef/0_0_580_75/master/580.jpg?width=310&dpr=2&s=none&crop=none)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "599ece2f-88a2-4818-83f9-0d0e478986ab",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'all roads lead to some'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"solve([[v, a&c, a&c], [b&n&c, b&n&v, b&n&v, a&c, b&c], [a&t&c, b&v, b&v, a&c],[a&c, b&v], [c, b&v, w&b&c, b&v]])"
]
},
{
"cell_type": "markdown",
"id": "bfd1dc29-5958-4c51-a124-b39d633ea60f",
"metadata": {},
"source": [
"OK, not quite right, but a good hint.\n",
"\n",
"One more:\n",
"\n",
"## Puzzle #10\n",
"\n",
"\n",
"![](https://i.guim.co.uk/img/media/c358352e9f14f1fb0d0f458f034bb86777efcc83/0_0_464_75/master/464.jpg?width=310&dpr=2&s=none&crop=none)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "68d34678-7688-49c4-94b6-5ba207497866",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'have in blind'"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"solve([[a&c, b&v, b&c, b&v], [a&v, b&c], [a&c, a&t&c, a&v, b&c, a&c]])"
]
},
{
"cell_type": "markdown",
"id": "87eb56d5-9a6b-41f0-8eec-b4c8f63dbdbd",
"metadata": {},
"source": [
"That's not right either, but again it is a good clue to the right answer. (One reason I didn't get this one right is that I didn't consider capital letters, and a Capital \"L\" has a different shape than a lowercase \"l\".)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "747c3d08-c98a-497d-9430-f6a69dbd70cc",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:base] *",
"language": "python",
"name": "conda-base-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -57,13 +57,14 @@ notebooks = {
('How to Count Things', 2020, 'How%20To%20Count%20Things.ipynb', 'Combinatorial math: how to count how many things there are, when there are a lot of them'), ('How to Count Things', 2020, 'How%20To%20Count%20Things.ipynb', 'Combinatorial math: how to count how many things there are, when there are a lot of them'),
('KenKen (Sudoku-like Puzzle)', 2021, 'KenKen.ipynb', 'A Sudoku-like puzzle, but with arithmetic.'), ('KenKen (Sudoku-like Puzzle)', 2021, 'KenKen.ipynb', 'A Sudoku-like puzzle, but with arithmetic.'),
('Number Bracelets Game', 2024, 'NumberBracelets.ipynb', 'A game involving numbered beads on a circular bracelet.'), ('Number Bracelets Game', 2024, 'NumberBracelets.ipynb', 'A game involving numbered beads on a circular bracelet.'),
('Project Euler #3: Largest prime factor', 'Euler3.ipynb', 2026, 'Find the largest prime factor of a number'),
('Pairing Socks', 2019, 'Socks.ipynb', 'What is the probability that you will be able to pair up socks as you randomly pull them out of the dryer?'), ('Pairing Socks', 2019, 'Socks.ipynb', 'What is the probability that you will be able to pair up socks as you randomly pull them out of the dryer?'),
('Sicherman Dice', 2018, 'Sicherman%20Dice.ipynb', 'Find a pair of dice that is like a regular pair of dice, only different'), ('Sicherman Dice', 2018, 'Sicherman%20Dice.ipynb', 'Find a pair of dice that is like a regular pair of dice, only different'),
("Sol Golomb's Rectangle Puzzle", 2014, 'Golomb-Puzzle.ipynb', 'A Puzzle involving placing rectangles of different sizes inside a square'), ("Sol Golomb's Rectangle Puzzle", 2014, 'Golomb-Puzzle.ipynb', 'A Puzzle involving placing rectangles of different sizes inside a square'),
("Stubborn number endings", 2024, 'Stubborn.ipynb', 'Any number ending in 5 has a square that also ends in 5. What other endings are like this?'), ("Stubborn number endings", 2024, 'Stubborn.ipynb', 'Any number ending in 5 has a square that also ends in 5. What other endings are like this?'),
('Star Battle (Sudoku-like Puzzle)', 2021, 'StarBattle.ipynb', 'Fill-in-the-grid puzzle similar to Sudoku'), ('Star Battle (Sudoku-like Puzzle)', 2021, 'StarBattle.ipynb', 'Fill-in-the-grid puzzle similar to Sudoku'),
('Sudoku', 2006, 'Sudoku.ipynb', 'Classic fill-in-the-grid puzzle'), ('Sudoku', 2006, 'Sudoku.ipynb', 'Classic fill-in-the-grid puzzle'),
('Sudoku: 100,000 puzzles/second in Java', 2021, 'SudokuJava.ipynb', 'A version of the Sudoku solver using parallel threads and other optimizations'), ('Sudoku: 200,000 puzzles/second in Java', 2021, 'SudokuJava.ipynb', 'A version of the Sudoku solver using parallel threads and other optimizations'),
('Square Sum Puzzle', 2020, 'SquareSum.ipynb', 'Place the numbers from 1 to n in a chain (or a circle) such that adjacent pairs sum to a perfect square'), ('Square Sum Puzzle', 2020, 'SquareSum.ipynb', 'Place the numbers from 1 to n in a chain (or a circle) such that adjacent pairs sum to a perfect square'),
("When is Cheryl's Birthday?", 2020, 'Cheryl.ipynb', "Solving the *Cheryl's Birthday* logic puzzle"), ("When is Cheryl's Birthday?", 2020, 'Cheryl.ipynb', "Solving the *Cheryl's Birthday* logic puzzle"),
('When Cheryl Met Eve: A Birthday Story', 2015, 'Cheryl-and-Eve.ipynb', "Inventing new puzzles in the Style of Cheryl's Birthday"), ('When Cheryl Met Eve: A Birthday Story', 2015, 'Cheryl-and-Eve.ipynb', "Inventing new puzzles in the Style of Cheryl's Birthday"),
@@ -74,6 +75,7 @@ notebooks = {
'Word Puzzles': [ 'Word Puzzles': [
('Boggle / Inverse Boggle', 2020, 'Boggle.ipynb', 'Find all the words on a Boggle board; then find a board with a lot of words'), ('Boggle / Inverse Boggle', 2020, 'Boggle.ipynb', 'Find all the words on a Boggle board; then find a board with a lot of words'),
('Chemical Element Spelling', 2020, 'ElementSpelling.ipynb', 'Spelling words using the chemical element symbols, like CoIn'), ('Chemical Element Spelling', 2020, 'ElementSpelling.ipynb', 'Spelling words using the chemical element symbols, like CoIn'),
('Did you solve it? R y clvr ngh t rd ths sntnc?', 2026, 'clvr.ipynb', 'Guess famous phrases from letter shapes. Beginner level.'),
('Equilength Numbers: FOUR = 4', 2020, 'equilength-numbers.ipynb', 'What number names have the same letter count as the number they name (such as FOUR)?'), ('Equilength Numbers: FOUR = 4', 2020, 'equilength-numbers.ipynb', 'What number names have the same letter count as the number they name (such as FOUR)?'),
('Gesture Typing', 2017, 'Gesture%20Typing.ipynb', 'What word has the longest path on a gesture-typing smartphone keyboard?'), ('Gesture Typing', 2017, 'Gesture%20Typing.ipynb', 'What word has the longest path on a gesture-typing smartphone keyboard?'),
('Ghost: A Word game', 2017, 'Ghost.ipynb', 'The word game Ghost (add letters, try to avoid making a word)'), ('Ghost: A Word game', 2017, 'Ghost.ipynb', 'The word game Ghost (add letters, try to avoid making a word)'),
@@ -203,7 +205,6 @@ def format_notebook(title, year, url, comment=''):
nb = f'[N](https://nbviewer.jupyter.org/github/norvig/pytudes{urlb})' nb = f'[N](https://nbviewer.jupyter.org/github/norvig/pytudes{urlb})'
sm = f'[S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes{urlb})' sm = f'[S](https://studiolab.sagemaker.aws/import/github/norvig/pytudes{urlb})'
ti = f'<a href="{gh[4:-1]}" title="{comment}">{title}</a>' ti = f'<a href="{gh[4:-1]}" title="{comment}">{title}</a>'
if year == current_year: year = f'<u>{year}</u>'
return f'| {co} {dn} {my} {nb} {sm} | {year} | {ti} |' return f'| {co} {dn} {my} {nb} {sm} | {year} | {ti} |'
def format_pythons() -> str: def format_pythons() -> str: