One code liner in Python ๐Ÿ

ยท

4 min read

During college, my lecturer gave me a task to find the shortest code to create this string using python:

****
***
**
*
**
***
****

So how you would do that? Here's the code in Python we end up:

for i in range(4, 1, -1):
    print('*' * i)
for i in range(1, 5):
    print('*' * i)

For those who wonder, range(a, b, c) creates an iterator loop from a to b by c. the a is inclusive but b is not. If c is 1, you can omit it since it's the default anyway. Thus range(4, 1, -1) generates [4,3,2] while range(1, 5) generates [1,2,3,4].

And then we take that i to multiply with '*' because python multiplication with string causes that string to be repeated i times, e.g. '*' * 3 generates '***'

This is already short in fact ๐Ÿ˜… that's really awesome about Python, isn't it?

But wait, there's more! We can reduce our python code into one single for loop:

for i in range(1, 8):
  if (i < 4):
    print('*' * (5 - i))
  else:
    print('*' * (i - 3))

What does this code do? It transforms [1,2,3,4,5,6,7] to [4,3,2,1,2,3,4] so then we took these values to get multiplied by *. If it takes a while to grasp why I put these values on, I'll try to explain here:

# i < 4
i = 1 => 5 - 1 = 4
i = 2 => 5 - 2 = 3
i = 3 => 5 - 3 = 2
# else (i >= 4)
i = 4 => 4 - 3 = 1
i = 5 => 5 - 3 = 2
i = 6 => 6 - 3 = 3
i = 7 => 7 - 3 = 4

Okay, but why do we do this? It seems didn't make our code shorter, right?

That's why we need to do some math here. Enter the absolute function:

image.png

How does this absolute function help us? Well, with some fitting on the equation, we get this graph:

image.png

(click the image to see interactive version)

This graph does what we want, transforms [1,2,3,4,5,6,7] to [4,3,2,1,2,3,4] with a single equation. Math is powerful ๐Ÿ’ช.

This is the code now looks like after we implement the equation:

for i in range(1, 8):
  print('*' * (abs(i - 4) + 1))

Luckily python has abs() built-in without importing any modules. This reduces our code lines from 5 to 2 ๐Ÿ’ช.

But does this can get further decreased to 1 line? Yes ๐Ÿ˜ฑ

But before that, we have to put the print() function outside the loop. This can be done with a temporary variable that holds the whole string in a loop:

output = []
for i in range(1, 8):
  output.append('*' * (abs(i - 4) + 1))
print('\n'.join(output))

Now we hold the loop value to a variable named output and use that to print output once. Note that we use '\n'.join(output) which converts the array to string with \n between values. \n simply means a new line, for each string, we add during for loop.

But why this makes our code more verbose? Enter Python's killer feature: List Comprehension.

List Comprehension simply means doing a loop within a single line. Effectively makes a loop became a python expression. What this means for a layman is they allow us to convert this code:

variable = []
for item in list:
  variable.append(expression(item))

to:

variable = [expression(item) for item in list]

Three lines into one! Doesn't that awesome? ๐Ÿ˜Ž

This is our final code after the list comprehension:

print('\n'.join(['*' * (abs(i - 4) + 1) for i in range(1, 8)]))

That's really short, isn't it? Of course, this code is not readable as we are beginning with ๐Ÿ˜… but hey, we do this for fun ๐Ÿ’ช also these pieces of stuff are also useful for machine code optimization (if you're into that).

Anyway, if you're familiar with code golfing, you can get the lowest of all codes within 55 characters in Python by removing unneeded whitespace:

print('\n'.join(['*'*(abs(i-4)+1)for i in range(1,8)]))

Anyone can beat that? ๐Ÿ˜… Hope this useful ๐Ÿ’ช

ย