mathspp.com feed https://mathspp.com/blog/tags/binary Stay up-to-date with the articles on mathematics and programming that get published to mathspp.com. en Wed, 23 Jul 2025 16:49:02 +0200 Base conversion in Python https://mathspp.com/blog/base-conversion-in-python https://mathspp.com/blog/base-conversion-in-python Sun, 07 Jan 2024 10:00:00 +0100

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.

Bases change the representation, not the number

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!

Built-in bases for integer literals

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:

  1. binary;
  2. octal; and
  3. 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

Built-in functions for base conversion

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]

String formatting in binary, octal, and hexadecimal

The prefix letters for the integer literals can also be used as...

]]>
binary mathematics modular arithmetic programming python
Problem #058 – identifying light bulbs https://mathspp.com/blog/problems/identifying-light-bulbs https://mathspp.com/blog/problems/identifying-light-bulbs Mon, 28 Mar 2022 23:00:00 +0200

Please help me identify these 100 light bulbs by turning ON and OFF their switches.

Photo by Juan Carlos Becerra on Unsplash.

Problem statement

I have a very peculiar room in my house. It's a simple room that doesn't have much decoration. However, I do have 100 light bulbs hanging from the ceiling because I thought it would look cool. When I installed the 100 light bulbs I wanted maximum freedom, so I also installed 100 independent switches:

  • each switch controls exactly one light bulb; and
  • each light bulb is controlled by exactly one switch.

Of course I was completely silly, so I installed the switches in a room that is far from the room with the light bulbs and I completely forgot which light switch controls which light bulb. How can I identify which switch controls which light bulb in the least amount of trips possible?

For example, I could flip ON a switch and then go verify which light bulb turned ON, and I could do this for the 100 light bulbs... But that would take me 100 trips.

Give it some thought!

If you need any clarification whatsoever, feel free to ask in the comment section below.

This problem was adapted from here and is licensed under CC BY-SA 3.0.

Solvers

Congratulations to the ones that solved this problem correctly and, in particular, to the ones who sent me their correct solutions:

  • David H., Taiwan;
  • Shubham S., India;
  • Dan, USA;
  • Jeena K., India;
  • Frank X., Shenzhen, China;
  • Wolfgang, Germany;
  • Naveen K., India;
  • Pedro G., Portugal;
  • Dylan S., USA;
  • Vladimir L., USA;
  • Sean L., USA;

Know how to solve this? Join the list of solvers by emailing me your solution!

Solution

We can devise a strategy that identifies \(2^n\) light bulbs in \(n\) trips making use of binary.

In short, what we do is number each switch in binary. Suppose the longest binary number has \(k\) digits. Then, we do \(k\) trips and for each trip \(t\) we turn ON the switches whose binary expansions have a \(1\) in the corresponding position. After the \(k\) trips, the times at which each light bulb was on will correspond to the binary expansion of its switch.

As an example, suppose we have 4 light bulbs and 4 switches. We number the four switches in binary:

  1. \(00\)
  2. \(01\)
  3. \(10\)
  4. \(11\)

This means that for the first trip we only turn ON switches 2 and 4, and for the second trip we only turn ON the switches 3 and 4. As two example associations, the light bulb associated with the switch 4 is the light bulb that was turned ON both times and the light bulb associated with the switch 1 is the light bulb that was turned OFF both times.

For 100 light bulbs, the largest binary number will be \(1100011\) (for 99), which means we'll need 7 trips.

Don't forget to subscribe to the newsletter to get bi-weekly problems sent straight to your inbox.

]]>
binary logic mathematics
TIL #017 – symmetrical indexing with bitwise inversion https://mathspp.com/blog/til/017 https://mathspp.com/blog/til/017 Sun, 28 Nov 2021 00:00:00 +0100

Today I learned about the symmetry in indexing from the beginning and end of a list with the bitwise invert operator.

The text “~i” inside a pair of square brackets in front of a highly geometrical building.

Negative indexing

As you might be aware of, Python allows indexing with negative indices:

>>> s = "Hello, there!"
>>> s[-1]
'!'

In case this is new to you, you can check out this Pydon't on the subject.

One thing to note is that the index for the nth element is n - 1, but the index for the nth element from the end is -n. This is just “how it works”, but it is kind of a bummer because it is very asymmetrical:

>>> seq = "ABCDCBA"
>>> seq[0], seq[-1]     # 0 and -1
('A', 'A')
>>> seq[1], seq[-2]     # 1 and -2
('B', 'B')
>>> seq[2], seq[-3]     # 2 and -3
('C', 'C')
>>> seq[3], seq[-4]     # 3 and -4
('D', 'D')

By looking at the correspondences above, we can see that the positive index n pairs up with the index -n - 1.

Bitwise invert

Python has a couple of bitwise operations, one of them being bitwise invert ~. Bitwise invert ~n is defined as -(n+1):

>>> n = 38
>>> ~n
-39
>>> -(n+1)
-39
>>> n = -73
>>> ~n
72
>>> -(n+1)
72

Now, maybe you can see where I'm going with this, but -(n+1) simplifies to -n - 1.

Symmetrical indexing with bitwise inversion

If we put these two pieces of knowledge together, we can see how we can use bitwise inversion ~ to index symmetrically from the beginning and end of a sequence, like a string or a list:

>>> seq = "abccba"
>>> seq[1], seq[~1]
('b', 'b')
>>> for i in range(len(seq) // 2):
...     print(seq[i], seq[~i])
...
a a
b b
c c

Doesn't this look beautiful?

I feel like this is one of those things that you really won't use that often, but there will come a time in your life when you'll want to exploit this symmetry! And, you either remember what you just learned about ~, or you'll be writing the uglier version with subtractions:

>>> seq = "abccba"
>>> seq[1], seq[~1]
('b', 'b')
>>> for i in range(len(seq) // 2):
...     print(seq[i], seq[-i - 1])
...
a a
b b
c c

Thanks a lot to Tushar Sadhwani from bringing this to my attention:

That's it for now! Stay tuned and I'll see you around!

]]>
binary mathematics programming python
Problem #029 - hidden key 2 🗝️🗝️ https://mathspp.com/blog/problems/hidden-key-2 https://mathspp.com/blog/problems/hidden-key-2 Sun, 07 Feb 2021 00:00:00 +0100

This problem is a step up from Problem #028 - hidden key. Can you tackle this one?

Two keys.
Original photograph from Aneta Pawlik on Unsplash.

Problem statement

You and your best friend are locked in jail for no reason at all, but you are given the opportunity to escape. You are taken to a room that has four opaque boxes. The key to your cell will be put inside one of the boxes, and then a (regular) coin is placed on top of each box. You may pick a single coin and reverse its face up, and then your friend will enter the room.

When your friend enters the room you are not allowed to talk, and your friend must open a box. If your friend opens the box with the key, you are set free. Otherwise, you are locked for eternity...

What is the strategy that you and your friend should agree upon, so that your friend can always find the key?

Give it some thought...

If you need any clarification whatsoever, feel free to ask in the comment section below.

Solution

The solution I will be sharing is not the original solution I thought of, I decided to share with you the solution that someone [posted][reddit-sol] online when I shared this puzzle on reddit.

What we are going to do is imagine the four boxes are laid out in a two by two square:

The next thing we do is interpret the sides of the coins as zeroes and ones, because it is easier to do maths with binary numbers. So a random configuration of the coins (of the zeroes and ones) and the (hidden) key could be:

The next thing we do is agree that each box can be represented by its coordinates, in the sense that we can identify each box by the row and column it is in. To make things easier for us, we will start counting the rows and columns from zero, so that the top left box is in position \((0, 0)\), the top right box is in position \((0, 1)\), the bottom left box is in position \((1, 0)\) and the bottom right box is in position \((1, 1)\):

In the example image above, the key is currently in box \((1, 0)\).

Now that we have settled all the important details, we can determine our strategy:

  • the parity of the sum of the first row of zeroes and ones will encode the row the key is in; and
  • the parity of the sum of the first column of zeroes and ones will encode the column the key is in.

We are talking about the “parity” of the sum because if the row contains two \(1\)s, then we sum them and get \(2\), which is not a valid row. Likewise for the columns. Hence, if the first row sums to an even number, then the key is in the first row, and if the first row...

]]>
binary combinatorics mathematics
Problem #028 - hidden key 🗝️ https://mathspp.com/blog/problems/hidden-key https://mathspp.com/blog/problems/hidden-key Sun, 24 Jan 2021 00:00:00 +0100

There is a key hidden in one of three boxes and each box has a coin on top of it. Can you use the coins to let your friend know where the key is hiding?

A photograph of a key, by Aneta Pawlik on Unsplash.

Problem statement

You and your best friend are locked in jail for no reason at all, but you are given the opportunity to escape. You are taken to a room that has three opaque boxes. The key to your cell will be put inside one of the boxes, and then a (regular) coin is placed on top of each box. You may pick a single coin and reverse its face up, and then your friend will enter the room.

When your friend enters the room you are not allowed to talk, and your friend must open a box. If your friend opens the box with the key, you are set free. Otherwise, you are locked for eternity...

What is the strategy that you and your friend should agree upon, so that your friend can always find the key?

Give it some thought...

If you need any clarification whatsoever, feel free to ask in the comment section below.

Solution

There are multiple solutions to this problem, but the most simple and elegant one (that I know of) is as follows: flip a coin, so that the box with the key is under a coin whose face up is different from the other two coins.

What is interesting is that this is always possible, regardless of how the coins are originally placed on top of the boxes. I invite you to have a go at demonstrating that the solution I just described actually works, before you keep on reading my solution.

If you number the boxes \(1\) to \(3\), with the box holding the key being box number \(1\), then there's \(8\) different ways the coins could be placed on top of the three boxes. However, we don't care about the exact coin faces facing up! Much like “[Problem #021 - predicting coin tosses][p21]”, we only care about the relationships of the outcomes, which are three and can be identified by the number of boxes whose coin face up is the same as the coin face that is up on top of the box with the key. That was a long sentence, reread it if you must!

For example, if the box with the key has a coin with tails face up, then one of these three must be true:

  1. all coins have tails face up.
  2. two coins have tails face up, one on top of the box with the key and another on top of some other box.
  3. only the coin on top of the box with the key has tails face up.

If we are in situation 1., then we turn the coin on top of the box with the key, so that its face up is now heads (and it is the only coin with heads facing up). If we are in...

]]>
binary combinatorics mathematics
Problem #024 - hats in a line https://mathspp.com/blog/problems/hats-in-a-line https://mathspp.com/blog/problems/hats-in-a-line Sun, 29 Nov 2020 00:00:00 +0100

Some people are standing quiet in a line, each person with a hat that has one of two colours. How many people can guess their colour correctly?

A picture with a couple of people in a line, with different-coloured hats

Problem statement

Some people, let's say \(n\) people, are standing in a line. (Of course they are more than 2m away from each other, social distancing has to be taken seriously by all of us.)

Each person has a hat, like the picture above shows. Each hat is either light or dark, but no one knows the colour of their own hat and people can only look forward and cannot move at all. (Except perhaps to blink and to breath.)

Assuming they got a chance to meet before they got placed in a line and received their hats, what strategy do they have to agree on so that the most people can guess their own hat colour correctly? We can pretend that people who fail to guess their hat colour are sent to prison, and of course we want to keep as many people out of prison as possible. The only thing they know is that the hats will be distributed randomly, they have no idea how many hats of each colour will be distributed.

So your task is to devise the best possible strategy and to find out how many people that strategy saves, on average.

It is important to note that:

  • people cannot communicate with each other once they are in a line;
  • they can try to guess the colours of their hats in any order you see fit;
  • each person gets a single attempt;
  • everyone hears everyone's guess, but only the people behind the person making a guess know if that person got it right. Everyone else has no idea if the guess was correct or not.

Give it some thought...

If you need any clarification whatsoever, feel free to ask in the comment section below.

This problem was posed to me by my friend LeafarCoder.

Solution

Let us say there's \(n\) people standing in the line. We will show that the best strategy always saves \(n - 1\) people and that the \(n^\text{th}\) person is saved with a \(50\%\) probability.

In order to do this, we have to do two things:

  1. Show there is no strategy with a better success rate.
  2. Show there is a strategy with this success rate that works.

In approaching problems of this type, where one has to “find the best strategy possible”, my approach is often one of a wishful thinker. If someone poses a problem like this, usually it's because there is an amazing strategy with a very good success rate. When that is the case, I always try to see if there can be a perfect strategy. More often than not, there is a perfect strategy or one that comes quite close to it.

For this particular problem, it is easy to see there cannot be a truly perfect strategy: the first person that guess their own hat will have no...

]]>
mathematics game theory binary
Twitter proof: size of the set of subsets of a set https://mathspp.com/blog/subsets-of-a-set https://mathspp.com/blog/subsets-of-a-set Thu, 06 Aug 2020 00:00:00 +0200

Let's prove that, if a set has size \(n\), then that same set has exactly \(2^n\) subsets.

|S| = n implies that |P(S)| = 2^n

Do you have an idea for a twitter proof? Let me know in the comments below!

]]>
binary mathematics set theory
The formula that plots itself https://mathspp.com/blog/the-formula-that-plots-itself https://mathspp.com/blog/the-formula-that-plots-itself Wed, 24 Apr 2019 15:32:00 +0200

This post gives you the code to mess around with "Tupper's self-referential formula", a formula that plots itself.

By the end of this blog post, I hope that you know how to make mathematical drawings and why the number

\[ N \approx 4.85845063618971342358209596 \times 10^{543}\]

is so special.

Given a function \(f(x, y)\), how can you use it to make a drawing? Well, we just imagine the whole plane as a white, clean grid, and then we fill with black the squares at the positions \((x,y)\) such that \(f(x,y) > \frac{1}{2}\). In a way, it is as if the function \(f\) is telling us whether to use white or black, i.e., to leave the square empty (\(0\)) or filled in (\(1\)).

(More rigorously, we divide the plane into unit squares and assign each square the coordinates of its lower-left corner.)

If we take, for example, \(f(x, y) = x + y\), then square \((0,0)\) would be white because \(f(0, 0) = 0 < \frac{1}{2}\) but the squares \((0, 1)\) and \((1, 0)\) would be black because \(f(0, 1) = f(1, 0) = 1 > \frac{1}{2}\).

As another example, take \(f\) to be this function:

\[ f(x, y) = \left\lfloor \text{mod}\left(\left\lfloor\frac{y}{17} \right\rfloor 2^{-17\lfloor x \rfloor - \text{mod}(\lfloor y \rfloor, 17)}, 2\right) \right\rfloor\]

where \(\lfloor n \rfloor\) denotes the floor function and \(\text{mod}(a, b)\) denotes the modulo operator. This function looks way more interesting, doesn't it? Yes, it does! And if you look in the right place, this is what is plotted by this function:

A plot showing the Tupper formula written in black in a pixelated font.
The formula, drawn.

What is going on here..? The function I just showed you, called Tupper's self-referential formula, is a formula that plots itself! But you might be suspicious because I said if you look in the right place. What is this place then?

Quite simply, define

\[ N=4858450636189713423582095962494202044581400587983244549483093085061934704708809928450644769865524364849997247024915119110411605739177407856919754326571855442057210445735883681829823754139634338225199452191651284348332905131193199953502413758765239264874613394906870130562295813219481113685339535565290850023875092856892694555974281546386510730049106723058933586052544096664351265349363643957125565695936815184334857605626529915320311182856118951164066401426579727262440270286409619368825536815027849325692956320299303330714849102058741137034502,\]

(a 544-digit-long number). Then, the image I showed you is the rectangular area with the lower-left corner \((0, N)\) and the upper-right corner \((105, N + 16)\) (so it is a \(106 \times 17\) rectangle). Quite impressive, right? Self-references are always fun!

But that is not all... If you look hard enough, you can find literally anything inside that \(106\times17\) rectangle! For example, taking

\[ N=677269797063266389145771001639366162904443300634759368354244105189144417475687924080590138582401925400953401198762670070868017028632609067495842127259345485889052110555312844858658969250766978033911456684637024394115209279287448522343527514061700072005928325124098808483476326307953390156875355289624192978628506335125351370018499785193486797521350328711540234844414805471938182060305235921541912512179523099720166772353828125144439537587189530425493554812515912471900753848603802337280,\]

you can find the name of this site "mathspp" and a winking face ";)":

The text "mathspp ;)" drawn in black in a pixelated font.
mathspp ;)

Now the really important question is... How does one find such values for \(N\)? Well, you can watch this Numberphile YouTube video, or I can tell you all about it...

You start with a \(106\times17\) grid and you colour it (with black/white) the way you want. Then you will construct a bit sequence: you start on the top-right corner, and write down a \(1\) if that square is black, \(0\) if that square is white. Then you go down one square, and repeat. You do this column by column, top to bottom, right to left. When you finish, you convert your bit sequence...

]]>
binary mathematics modular arithmetic programming pygame python recursion visualisation
Problem #005 - number me right https://mathspp.com/blog/problems/number-me-right https://mathspp.com/blog/problems/number-me-right Tue, 23 Jan 2018 00:00:00 +0100

This problem is a really interesting problem I solved two times. The first time I solved it I failed to prove exactly how it works... then some years later I remembered the problem statement and was able to solve it properly. Let's see how you do!

Problem statement

Take a chessboard and extend it indefinitely upwards and to the right. In the bottom leftmost corner you put a \(0\). For every other cell, you insert the smallest non-negative integer that hasn't been used neither in the same row, to the left of the cell, nor in the same column, below it. So, for example, the first row will have the numbers \(0, 1, 2, 3, \cdots\). What is the number that appears in the \(1997\)th row, \(2018\)th column?

Give it some thought... my best advice would be for you to create a grid in your piece of paper and start filling it out as stated by the rules. Can you find a pattern?

If you need any clarification whatsoever, feel free to ask in the comment section below.

Solution

The key here is to understand the way in which the board is filled. When I first solved the problem I started by filling a board on my own, to get a feel for the rules imposed. Doing so should make clear that, for example,

  • the number in the diagonal is always a \(0\);
  • the board is symmetric along the diagonal, i.e. the number in column \(j\) and row \(i\) is the same number as in row \(j\) and column \(i\).

The interested reader is left with trying to get a feel for the pattern involved in filling the board. We skip right to the full solution.

Claim: the number in the \(i+1\)th row and \(j+1\)th column is \(i \hat{} j\), where \(\hat{}\) is the bitwise [XOR] operation.

The bitwise XOR takes two bit representations and for each pair of corresponding bits returns \(1\) if one and only one of the bits was \(1\). Otherwise the result is \(0\). For example, \(1100_2 \hat{} 1010_2 = 0110_2\).

Notice how this aligns with the two observations made:

  • the diagonal only has zeros; in the diagonal the row and the column have the same number and \(n \hat{} n = 0\);
  • being in row \(i\) and column \(j\) is the same as being in column \(i\) and row \(j\); \(i \hat{} j = j \hat{} i\).

From now on we will renumber the rows and columns so that they start at \(0\) and we will let \(c(i,j)\) be the value in the \(i\)th row, \(j\)th column. Let \(P(n)\) be the statement "the bottom left square of the table with side \(2^n\) has, in every row, every single number from \(0\) to \(2^n -1\) and

\[ \forall i,j \leq 2^n-1: c(i,j) = i \hat{} j\ .\]

This final part means that the value of a specific cell is...

]]>
binary induction mathematics