A new programming problem has been trending recently - write a program to print numbers from one to hundred without using any loops or mentioning numbers in the source. Naturally, I was interested in a solution in Python.
I got many brilliant answers on Twitter. But first let me show you how I approached it. I was looking for a general and readable solution than the shortest one. My thought process was – even if we cannot mention numbers we can convert non-numeric types to numbers. So I tried with Booleans and Strings:
zero = int(False)
one = int(True)
hundred = int(f"{one}{zero}{zero}")
def shownum(i):
if i <= hundred:
print(i)
shownum(i + one)
shownum(one)
Starting from scratch, we get 0 and 1 from the False and True values. Then to create 100, the upper limit of the loop, we use the new favourite string interpolation method – f-strings.
Overcoming the limitation of not using loops was quite straightforward - just use Recursion. We have to be careful though, Python does not have Tail Call Optimization (since Guido prefers to have proper tracebacks), so if you keep increasing the upper limit of the loop you will end up in a stack overflow.
Whiz kids on Twitter
To my poser tweet yesterday, there were many wonderful solutions that were way shorter than mine. Here are some of them:
The Long Scream by Abhiram
print([*range(len('a'), len('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))])
— Abhiram R (@abhicantdraw) March 22, 2021
😂
What I like here is the clever use of the * operator to convert the range object into a list tersely. And of course the liberal use of the “a”-s that just screams “I cannot be unseen”.
Short and Succinct by Rohan
list(map(int,range(ord(b"e"))))
— Rohan Verma (@rhnvrm) March 22, 2021
Cleverly taking advantage of Python’s built-in ord
function to get the ASCII code of lower case ‘e’ (it is 101 not 100), we sort of have a code-golf winner. Sort of because it starts count from 0 not 1 as the original question posed. But this is Twitter, a correction soon emerged.
Note that the map and int functions are not really required here, making it even more shorter! In a direct message Rohan shared an improved solution that starts counting from one:
list(filter(lambda x: x,range(ord(b"e"))))
Evolved by Anirudh
list(range(ord('a')-ord('a'), ord('e')))
— Anirudh Menon (@anikmenon) March 23, 2021
With a minor correction, this code fixes the start count to 1. As a nice touch the strings form ‘bae’ which must be the cutest term for a friend.
Can This Get Shorter by Arun
With the benefit of having seen all the ideas, I can finally put forth my shortest solution (with 23 characters):
[*range(True,ord("e"))]
So that’s the end of this code golf for me. That is, until someone else comes up with something shorter!