DEV Community

Cover image for One code liner in Python 🐍
Wildan Mubarok
Wildan Mubarok

Posted on • Updated on • Originally published at blog.wellosoft.net

One code liner in Python 🐍

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

****
***
**
*
**
***
****
Enter fullscreen mode Exit fullscreen mode

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

for i in range(4, 1, -1):
    print('*' * i)
for i in range(1, 5):
    print('*' * i)
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

to:

variable = [expression(item) for item in list]
Enter fullscreen mode Exit fullscreen mode

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)]))
Enter fullscreen mode Exit fullscreen mode

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)]))
Enter fullscreen mode Exit fullscreen mode

Anyone can beat that? 😅 Hope this useful 💪

Top comments (6)

Collapse
 
michaelcurrin profile image
Michael Currin • Edited

Challenge accepted.

This is what I came up with.

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

# mine
[print("*"*(abs(i)+1)) for i in range(-3, 4)]
****
***
**
*
**
***
****
Enter fullscreen mode Exit fullscreen mode

Background

I started range at -3.

list(range(-3, 4))
# [-3, -2, -1, 0, 1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

And then used abs.

I started with -4, 5 as my inputs but then the pattern was weird and I fixed with -3, 4 and +1.

So now it does this:

[(abs(i) + 1) for i in range(-3, 4)]
# [4, 3, 2, 1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

I also skipped the join to make it even shorter.

But here is my solution with a join. It ends up being a tiny bit shorter than your solution perhaps more readable (it is easier to think about -3 as the start than 1 and then -4 to get to -3)

# yours
print('\n'.join(['*'*(abs(i-4)+1)for i in range(1,8)]))
# mine
print("\n".join(("*"*(abs(i)+1))for i in range(-3,4)))
****
***
**
*
**
***
****
Enter fullscreen mode Exit fullscreen mode

Oh and by the way I used ( instead of [ for fun but makes no practical difference here. Either way, one is needed otherwise range gives a generator (Python 3).

Collapse
 
willnode profile image
Wildan Mubarok

Impressive! I never thought that we can put print() inside a list comprehension. Seems like cheating to me 😂. Thanks for that! I learn something new today 💪.

Collapse
 
michaelcurrin profile image
Michael Currin

Since Python 3, print is a function so you can use it anywhere you'd use a function

Collapse
 
michaelcurrin profile image
Michael Currin • Edited

What is code does?

Rather "What does this code do?"

This is also poor English.

Here's a typical code in Python

More like a "piece of code" or "snippet of code".

Because "code" describes a collective, not an individual. We wouldn't say "here is a water", "here is a spaghetti", "here is an information". But rather, "here is a cup/drop of water", "a piece/strand of a spaghetti" or "a piece of information".

Similarly, one shouldn't say "I wrote some codes", but "I wrote some code".

Collapse
 
willnode profile image
Wildan Mubarok

Thank you so much! English is my second language. I'll keep improving my writing skill.

Collapse
 
inr1137m profile image
Iyyanar M

Interesting