Can you solve this crossword where all hints are regular expressions?

At EuroPython 2024 I watched a lightning talk about the art of puzzle solving. In it, the speaker showed the regex crossword puzzle that you can see above, that I took from this URL. You are supposed to fill the hexagonal grid with letters so that all of the regular expressions shown match.

If you don't know regular expressions, the puzzle only uses a simple subset of the syntax:

- literal character matches;
- wildcard matches with
`.`

; - alternatives with
`|`

; - the quantifiers
`?`

,`+`

, and`*`

; - character sets with
`[...]`

and negated character sets with`[^...]`

; and - groups with
`()`

and group references with`\1`

,`\2`

, etc.

You can look this up and then you will be able to solve the challenge. You can also use the site regex101 to help you check what each regular expression means.

Give it some thought!

In the spirit of the puzzle hunting community, I will not share my solved grid here. If you need help, feel free to email me and we can talk it over.

P.S. if I understood correctly, in the puzzle hunting community you're not supposed to just fill in the grid. In some way, somehow, you are supposed to be able to extract an English word or phrase from that filled puzzle without any extra information, and then you check that you got it correctly by “checking your answer spoiler-free” in the website where I took the regex crossword from I am still stuck in that step!

]]>With a couple of loops and a bit of maths you can create a rotating spiral.

Following up on the concepts covered in my previous article “Animations from first principles in 5 minutes” and “More animations from first principles in 5 minutes”, in this article we will create the animation you can see above.

We start by modifying the parametrisation of the circle to create a spiral:

```
SIDE = 600
def spiral(percentage):
return (
SIDE // 2
* percentage
* cos(10 * pi * percentage),
SIDE // 2
* percentage
* sin(10 * pi * percentage),
)
```

The `10`

inside `cos`

/`sin`

dictate how many turns the spiral does, all you have to do is divide that number by `2`

, so a `10`

means we do `5`

turns around the centre of the spiral.

You can “easily” put the spiral on the screen:

```
from itertools import product
from math import sin, cos, pi
import pygame
SIDE = 600
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
screen = pygame.display.set_mode((SIDE, SIDE))
screen.fill(WHITE)
def draw_pixel(screen, x, y, colour):
x, y = round(x), round(y)
for dx, dy in product(range(-1, 2), repeat=2):
screen.set_at((x + dx, y + dy), colour)
def spiral(percentage):
return (
SIDE // 2 * percentage * cos(10 * pi * percentage),
SIDE // 2 * percentage * sin(10 * pi * percentage),
)
STEPS = 3000
for step in range(STEPS + 1):
percentage = step / STEPS
x, y = rotating_spiral(percentage, tick / 10)
draw_pixel(screen, x, y, BLACK)
pygame.display.flip()
input()
```

By modifying the function `spiral`

to accept an argument that represents time and by creating an outer loop that emulates ticking of time, we can rotate this spiral:

```
# ...
def spiral(percentage, time):
return (
SIDE // 2 * percentage * cos(10 * pi * percentage + time),
SIDE // 2 * percentage * sin(10 * pi * percentage + time),
)
# ...
STEPS = 3000
for tick in count():
screen.fill(WHITE)
for step in range(STEPS + 1):
percentage = step / STEPS
x, y = rotating_spiral(percentage, tick / 10)
draw_pixel(screen, x, y, BLACK)
pygame.display.flip()
```

To make the spiral expand and contract, we must make it so that the radius has to change as time ticks:

```
def rotating_spiral(percentage, time):
return (
SIDE // 2
+ (1 + sin(time) / 10) # <-- new
* percentage * (SIDE // 3) * cos(10 * pi * percentage + time),
SIDE // 2
+ (1 + sin(time) / 10) # <-- new
* percentage * (SIDE // 3) * sin(10 * pi * percentage + time),
)
```

Finally, to add colour, we create two functions that generate the background and foreground colours for each frame instead of using the constants `WHITE`

/ `BLACK`

:

```
# ...
def bg(time):
return (
40 + int(abs(30 * sin(0.05 * time))),
40 + int(abs(30 * sin(0.05 * time))),
40 + int(abs(30 * sin(0.05...
```

]]>
When will these two clocks synchronise again?

You have two digital clocks. One of them just displays the hours and minutes in the format HH:MM while the other is a stopwatch that displays minutes and seconds in the format MM:SS. The stopwatch wraps around at 59:59, when it goes back to 00:00.

On a certain day at 00:00, the stopwatch is turned on. When will the clock and the stopwatch have matching displays again? And how often does that happen?

Give it some thought!

The two clocks will have matching displays again at 01:01:01, then again at 02:02:02, 03:03:03, 04:04:04, ..., 23:23:23, so this happens 24 times per day.

To get to this conclusion, we start by realising that the stopwatch can actually be seen as a clock that shows the current time, but without the hours. Thus, the minutes display of the regular clock will always match the minutes display of the stopwatch.

To recap, the two clocks have displays in the format HH:MM and MM:SS and we already know that the MM sections always match. This means that for the two displays to display the same thing, we must have HH = MM = SS, which happens at 00:00:00, 01:01:01, ..., up to 23:23:23.

What if the stopwatch wraps around at 99:59 instead of 59:59?

]]>This article shows how to do base conversions in Python with the built-in int, how to write integer literals in other bases, and how to do base conversions in general.

In this article I'll assume you know what a number base is and how there are multiple number bases. My focus will be on showing you the tools that Python provides to work with multiple number bases, an in particular with the binary, octal, decimal, and hexadecimal, number bases.

Before diving right into the tools that Python gives you to work with different number bases I want to stress that a number base doesn't change the underlying number we're talking about, only its *representation*.

For example, many people around the world have three meals per day: breakfast, lunch, and dinner. It doesn't matter whether I write “three” in English, “três” in Portuguese, “3” in the decimal number base, or “11” in the binary number base. We're always talking about the same number of meals: breakfast, lunch, and dinner.

This is very important!

Python (and most programming languages) let you write integer literals in the decimal number base, and we typically don't even think about it. Python also lets you write integer literals in three other bases:

- binary;
- octal; and
- hexadecimal.

To write an integer literal in any base other than the decimal base, you always start your integer literal with a `0`

followed by the letter that identifies the base.
This is summarised in the table below:

Base | Prefix |
---|---|

binary | `0b` |

octal | `0o` |

hexadecimal | `0x` |

Thus, all four assignments below create the same integer literal:

```
svty_three = 73
svty_three_bin = 0b1001001
svty_three_oct = 0o111
svty_three_hex = 0x49
```

Because the base changes the representation but not the number, printing any of the four variables will print `73`

:

```
print(svty_three) # 73
print(svty_three_bin) # 73
print(svty_three_oct) # 73
print(svty_three_hex) # 73
```

In any of these bases, you can use the underscore `_`

to group digits to make the literals more readable.
For example, in the decimal base you can use the underscore `_`

as the thousands separator:

`huge_number = 17_532_546_253_000_000`

Python contains 3 built-ins that let you convert integers to *string* representations in the three other bases:

Base | Built-in |
---|---|

binary | `bin` |

octal | `oct` |

hexadecimal | `hex` |

Here's example usages of all three:

```
print(bin(73)) # 0b1001001
print(oct(73)) # 0o111
print(hex(73)) # 0x49
```

Notice that these converting functions include the base prefix in the converted representation!

If you want to use these string representations to represent the number in its base, you can discard the prefix and then convert each digit.
The code below uses a list comprehension and the built-in `bin`

to convert an integer to a list of its binary digits:

```
>>> [int(digit) for digit in bin(73)[2:]]
[1, 0, 0, 1, 0, 0, 1]
```

The prefix letters for the integer literals can...

]]>The built-in function max in Python is broken and this article explains why, drawing parallels with other programming and mathematics concepts.

`max`

is brokenDid you ever notice that in Python, you have:

```
sum([]) == 0
all([]) == True
any([]) == False
math.prod([]) == 1
```

Notice that the functions `sum`

, `all`

, `any`

, and `math.prod`

all have one thing in common:
they take a list of things and reduce it into a single result.
In all four cases above, if we pass the function an empty list we get a default value back.

However, `max`

is also a reduce function and `max`

doesn't have a nice default value.
Instead, it throws an error:

`max([]) # ValueError`

But why?
Isn't there a suitable default value for `max`

?

From a mathematical point of view, there is a suitable default value for `max`

, so the fact that the function raises an error instead of returning it is wrong and that is why I claim that `max`

is “broken”.
For `max`

to be mathematically correct, the default value for `max`

should be negative infinity, which you can get with `float("-inf")`

:

`max([]) == float("-inf")`

So, why does Python raise an error instead of being mathematically correct?
I'm guessing Python goes with the “practicality beats purity” approach and prefers to raise an error instead of returning infinity values to users, given that infinity can be quite an exotic thing...
Especially if we consider that `max`

should return *negative* infinity and `min`

should return infinity, which are different things.

(Right, I forgot to tell you but `min`

is also broken!)

But why “should” the return values be (negative) infinity?
That's because all of these reduction functions (`sum`

, `any`

, `all`

, `math.prod`

, `max`

, and `min`

) should return the identity element for their respective operations.

`sum`

performs addition and 0 is the identity element for addition.`any`

performs the Boolean operation “or” and False is the identity element for “or”.`all`

performs the Boolean operation “and” and True is the identity element for “and”.`math.prod`

performs multiplication and 1 is the identity element for multiplication.

Likewise, the identity element for the `max`

operation is `float("-inf")`

and the identity element for the `min`

operation is `float("inf")`

.

How can you know that `float("-inf")`

is the identity value for the operation `max`

?
Try to come up with a numerical value for `x`

such that `max(float("-inf"), x)`

is *different* from `x`

.
I bet you can't, and that's why `float("-inf")`

is the identity value for the operation `max`

; because `max(float("-inf"), x) == x`

for any number `x`

.

Do you get what I'm saying? Feel free to leave a comment below if you don't!

`max`

To fix `max`

in a mathematical sense you'll need to set its `default`

parameter to `float("-inf")`

.
The version below uses
`functools.partial`

to freeze the parameter `default`

:

```
from functools import partial
pedantic_max = partial(max, default=float("-inf"))
```

]]>
How can an infinite number of mathematicians figure out their own hat colours?

An infinite number of mathematicians are standing in a line. In a couple of minutes, a disruption in the space-time continuum will cause a black or white hat to appear on the head of each mathematician. After that happens, the mathematicians will try to guess their own hat colour (they can't see it) based on the colours of the hats of all other mathematicians.

What's the strategy that the mathematicians must agree on, before hand, so that only a *finite* number of mathematicians guesses wrong?

Give it some thought!

When we look at each matematician's hat we can create a sequence of \(0\)s and \(1\)s. For example, if everyone has a white hat except for the first three mathematicians, then we would have the sequence \((1,1,1,0,0,\cdots)\).

Let us say two sequences are *alike* if they are the same except for a finite number of positions.
As an example, the sequence we get when all mathematicians have a white hat and the previous sequence are *alike* because they differ only in the first three positions: \((\underline{0}, \underline{0}, \underline{0}, 0, 0,\cdots)\).

For any sequence \(S\) we can think of all the other sequences with which \(S\) is *alike*.
Let us call that group of *alike* sequences \([S]\).
What the mathematicians must do is: for every single group \([S]\) they must pick a random sequence from that group and memorise it.

When they are given the hats, they must look at their colleagues and figure out in which group \([S]\) their hat sequence belongs.
Then, they will recall the sequence they all memorized from that group and each mathematician will say that their hat is of the colour corresponding to their position on the memorized sequence.
By definition, only a finite number of mathematicians guesses wrong because the sequence they will recreate and the real sequence are *alike*, i.e. they differ only in a finite number of positions.

This article shows how to use the Python built-in `divmod`

for unit conversions.

`divmod`

for unit conversionsThe built-in `divmod`

is the built-in that tells me that 45813 seconds is the same as 12 hours, 43 minutes, and 33 seconds.
But how?

The built-in `divmod`

gets its name from two arithmetic operations you probably know:

- DIVision; and
- MODulo.

So, the built-in `divmod`

takes two arguments and returns two numbers.
The first one is the division of the arguments and the second one is the module of the arguments.
Sounds simple, right?
That's because it is!

```
>>> x, y = 23, 10
>>> divmod(x, y)
(2, 3)
>>> (x // y, x % y)
(2, 3)
>>> x, y = 453, 19
>>> divmod(x, y)
(23, 16)
>>> (x // y, x % y)
(23, 16)
```

So, when can `divmod`

be useful?
Literally when you want to divide two numbers and also know what's the remainder of that division.

In practice, `divmod`

shows up a lot when converting one small unit to more convenient units.
That's a common use case, at least.

45813 seconds is A LOT of seconds and most people just prefer to use the units of hours and minutes to talk about that many seconds! So, how do we convert 45813 into its corresponding number of hours and minutes?

We can use `divmod`

to divide 45813 by 60, which will convert 45813 seconds to minutes, and also let us know how many seconds couldn't be converted to minutes:

```
>>> divmod(45813, 60)
(763, 33)
```

Then, we take the total number of minutes and repeat the same process to figure out how many hours we have.

```
>>> divmod(763, 60)
(12, 43)
```

If you put everything together, it looks like this:

```
>>> seconds = 45813
>>> minutes, seconds = divmod(seconds, 60)
>>> hours, minutes = divmod(minutes, 60)
>>> hours, minutes, seconds
(12, 43, 33)
```

Is this making sense? Try to convert 261647 seconds into days, hours, minutes, and seconds!

I have another example that you might enjoy. There's this weird game I play sometimes called “meta tic-tac-toe”. (At least, that's what we called it in uni.) It's 9 tic-tac-toe games embedded in a larger tic-tac-toe game.

The board is shown below:

The rules aren't SUPER important now (although it's a pretty fun game). What matters now is that I wanted to implement this game in Python.

To do that, when a user clicks on the board, I need to know what's the purple (outer) cell that is being clicked. I also need to know what's the orange (inner) cell that is being clicked! The question is: how would I compute that?

Suppose the board is a 900 pixel square and everything is evenly spaced.
If I click at position `(423, 158)`

, what are the outer and inner cells I clicked?

We can figure out the outer...

]]>Today I learned that Python and other programming languages have negative zero, -0.0.

`-0.0`

If you open your Python REPL and type `-0`

in, you get `0`

back:

```
>>> 0
0
>>> -0
0
```

That makes sense.
After all, the integer `-0`

is the same as the integer `0`

...

However, `0.0`

and `-0.0`

are also equal but they are displayed differently in your Python REPL:

```
>>> -0.0
-0.0
>>> 0.0
0.0
```

As it turns out, because of the way floats work in computers, `0.0`

and `-0.0`

are two different entities.
Obviously, they compare as equal:

```
>>> 0.0 == -0.0
True
```

But they are different entities.
And *sometimes*, having `-0.0`

and `0.0`

as two distinct things can be helpful.

For example, you can think of `-0.0`

as a very small negative number that you just couldn't represent as a float.
In fact, the code below shows a couple of divisions that should all result in negative numbers, until suddenly we're dealing with such *small* numbers, that we get `-0.0`

:

```
x = -1
for _ in range(20):
x /= pow(10, 20)
print(x)
"""
-1e-20
-1e-40
-1e-60
-1e-80
-1e-100
-1e-120
-1e-140
-1e-160
-1e-180
-1e-200
-1e-220
-1e-240
-1e-260
-1e-280
-1e-300
-1e-320
-0.0
-0.0
-0.0
-0.0
"""
```

In contrast to this, if `x`

starts out as a positive number and you keep dividing it further, you end up at `0.0`

:

```
x = 1
for _ in range(20):
x /= pow(10, 20)
print(x)
"""
# ...
1e-260
1e-280
1e-300
1e-320
0.0
0.0
0.0
0.0
"""
```

Someone on Twitter mentioned that they've seen this used in a chemistry paper.
The appearance of a `-0.0`

indicated that a very small number was rounded to `0`

from a negative number, but in that particular context (of the chemistry paper), that indicated that a specific chemical process had occurred.

Someone else reported using negative zero `-0.0`

to represent the value `None`

in a list that could only contain floats.
So, if for some reason you have a list that is typed as `list[float]`

and you want to be able to represent the value `None`

, you could use `-0.0`

.

If you know of another practical use case for negative zero, comment below and I'll add it to this article!

`0.0`

from `-0.0`

Because `0.0 == -0.0`

, one way I could think of to distinguish negative zero from “regular” zero is by converting it to a string and comparing the signs of the number.

The function `is_negative_zero`

below computes this:

```
def is_negative_zero(number):
return str(number) == "-0.0"
print(is_negative_zero(0.0)) # False
print(is_negative_zero(-0.0)) # True
```

Then, Adam Johnson on Twitter reminded me of the function `math.copysign`

, which copies the sign of the second argument into the first:

```
>>> from math import copysign
>>> copysign(10, 1)
10.0
>>> copysign(10, -1)
-10.0
>>> copysign(10, -1234134.1235143)
-10.0
>>> copysign(10, 0)
10.0
>>> copysign(10, -0.0)
-10.0
```

So you can also use it to identify negative zero:

```
from math import copysign
def is_negative_zero(number):
return...
```

]]>
Create a zooming animation from first principles in Python. In 5 minutes. Kind of.

This is a follow-up to my recent article called “Animations from first principles (in 5 minutes)”. In that article, we created a simple animation with Python and pygame.

In *this* article, we will create a different type of animation, where we will draw a recursive triangular structure that can be zoomed in indefinitely.
We'll be using Python and `pygame`

, so make sure you install it in your preferred way, and make sure it was installed properly:

```
>>> import pygame
pygame 2.5.1 (SDL 2.28.2, Python 3.11.4)
Hello from the pygame community. https://www.pygame.org/contribute.html
```

The code in this article was written with Python 3.11 and `pygame`

2.5.1.
However, it should run well on older versions of Python/`pygame`

because we're only using fundamental features that have been around for a while and that are unlikely to go anywhere.

I have no idea if you can go through this in 5 minutes. You'll likely need more time if these ideas are new to you and you're typing the code yourself. However, I did present most of this material in 5 minutes in a lightning talk at PyCon Portugal.

For this demo, I'll cheat a bit and I will add a little bit of boilerplate for free.
This is a class `Point`

that I'm using to represent 2D points.
The idea is to make it easier to add and subtract points, and to multiply and divide points by numbers.

The class `Point`

looks like this:

```
class Point:
def __init__(self, x, y):
self.values = (x, y)
def __add__(self, other):
x, y = self.values
x_, y_ = other.values
return Point(x + x_, y + y_)
def __sub__(self, other):
x, y = self.values
x_, y_ = other.values
return Point(x - x_, y - y_)
def __mul__(self, other):
return Point(self.values[0] * other, self.values[1] * other)
__rmul__ = __mul__
def __truediv__(self, other):
return Point(self.values[0] / other, self.values[1] / other)
@property
def length(self):
return self.values[0] ** 2 + self.values[1] ** 2
```

It uses arithmetic dunder methods and a property, but it is just so I can do operations like `Point(1, 2) + Point(3, 4)`

or `3 * Point(1, 0)`

.

With this out of the way, let us start!

Just like last time, we'll start by making sure we can get a black screen in front of us:

```
import pygame
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
screen = pygame.display.set_mode((400, 400))
screen.fill(BLACK)
while True:
pygame.display.flip()
```

The code above fills a 400 by 400 screen with black and then it refreshes it forever. If you run this program, you'll see a black screen:

To close this window, you'll need to interrupt *the Python shell where*...

Create animations from first principles and morph between different figures with Python. In 5 minutes. Kind of.

Let me guide you through creating your first animation.
We'll be using Python and `pygame`

, so make sure you install it in your preferred way, and make sure it was installed properly:

```
>>> import pygame
pygame 2.5.1 (SDL 2.28.2, Python 3.11.4)
Hello from the pygame community. https://www.pygame.org/contribute.html
```

The code in this article was written with Python 3.11 and `pygame`

2.5.1.
However, it should run well on older versions of Python/`pygame`

because we're only using fundamental features that have been around for a while and that are unlikely to go anywhere.

I have no idea if you can go through this in 5 minutes. You surely can't if these ideas are new to you and you're typing the code yourself. However, I did present most of this material in 5 minutes in a lightning talk at PyCon Portugal.

The first thing we need is a canvas to draw on, so we'll import `pygame`

, create a small canvas, and fill it with black.
Since we'll be drawing in white, we can also set that up already:

```
import pygame
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
WIDTH = 400
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(BLACK)
while True:
pygame.display.flip()
```

The code above fills a 400 by 400 screen with black and then it refreshes it forever. If you run this program, you'll see a black screen:

To close this, you'll need to interrupt *the Python shell where you ran your program*.

We'll start by animating the drawing of a circle, so we need to be able to draw a circle.
In order to do this, we'll write a function `circle`

that accepts a single argument `progress`

that is a float between 0 and 1:

```
def circle(progress):
...
```

This function `circle`

will return a point – a tuple with two floats – that will represent a position on the screen that belongs to the circle...
But what position?

Think of yourself drawing a circle.
As the pen moves around the piece of paper, you can think of the "progress" you've made in drawing the circle.
If you have put the pen down on the paper, you've drawn 0% of the circle, so the progress is `0`

.

After you've drawn half a circle, you've drawn 50% of the circle, so that's `progress=0.5`

.
And as soon as you finish the circle, when your pen has gone around the paper and it touches the line you started drawing, at that time, your progress is `1`

.

So, the function `circle`

is supposed to return the position your pen was in when your drawing was at a...