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 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)
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:
How does this absolute function help us? Well, with some fitting on the equation, we get this graph:
(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 💪
Top comments (6)
Challenge accepted.
This is what I came up with.
Background
I started
range
at-3
.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:
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 than1
and then-4
to get to-3
)Oh and by the way I used
(
instead of[
for fun but makes no practical difference here. Either way, one is needed otherwiserange
gives a generator (Python 3).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 💪.Since Python 3, print is a function so you can use it anywhere you'd use a function
Rather "What does this code do?"
This is also poor English.
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".
Thank you so much! English is my second language. I'll keep improving my writing skill.
Interesting