avatarLiu Zuo Lin

Summary

The article presents a Python function that generates a hollow triangular pattern of letters using a single line of code.

Abstract

The author of the article discusses a challenging Python problem involving the creation of a hollow triangular pattern with letters from a given string. The solution provided is a compact one-liner function that handles strings of various lengths, including those that cannot form a perfect triangle without the use of asterisks to fill in the gaps. The function calculates the height of the triangle based on the string's length and uses string slicing and concatenation to construct each line of the pattern. The article also breaks down the logic behind the solution, explaining how the pattern is formed line by line, and emphasizes the importance of understanding the underlying principles before attempting to compress the code into a single line. The author concludes by cautioning against writing such dense code in production environments and invites readers to subscribe for more content or support the author through memberships or donations.

Opinions

  • The author believes that understanding complex coding problems is crucial for learning and growth in programming.
  • They suggest that compressing code into one-liners should be done for fun and not for practical, production-level code.
  • The author values reader engagement and encourages support through subscriptions and donations, indicating a desire to continue producing educational content.
  • There is an emphasis on the enjoyment of coding challenges and the satisfaction derived from solving them in creative ways.
  • The article implies that the one-liner solution is an intellectual exercise rather than a best practice for software development.

Solved In 1 Line of Python — Hollow Triangle Of Letters

In my previous article (below), I shared a difficult Python question that I’ve come across when I was just starting out.

In this article, I’ll run through how we can solve this question in one line.

The Question + Some Test Cases

Write a function that takes in a string, and prints the following hollow triangular pattern. If there are insufficient characters to make a perfect triangle, simply use * characters in their place.

string = “abcdefghijkl” (length=12)

Here, this string can form a perfect triangle by itself

   a
  b l
 c   k
defghij

string = “abcdefghijk” (length=11)

Here, there are insufficient letters to form a perfect triangle, so * characters are used to fill it up.

   a
  b *
 c   k
defghij

string = “abcdefghij” (length=10)

   a
  b *
 c   *
defghij

string = “abcdefghi” (length=9)

   a
  b *
 c   *
defghi*

string = “abcdefgh” (length=8)

Here, this string can form a perfect triangle by itself

  a
 b h
cdefg

string = “abcdefghijklmnop” (length=16)

This string too can form a perfect triangle by itself.

    a
   b p
  c   o
 d     n
efghijklm

string = “abcdefghijklmno” (length=15)

    a
   b *
  c   o
 d     n
efghijklm

The Solution In One Line

def hollow_triangle(s):print(" "*(len(s)//4+min(1,len(s)%4))+s[0] + "\n" + "\n".join([" "*(len(s)//4+min(1,len(s)%4)-i)+s[i]+" "*(i*2-1)+(s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[-i] for i in range(1,len(s)//4+min(1,len(s)%4))]) + "\n" + (s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[len(s)//4+min(1,len(s)%4):1-len(s)//4-min(1,len(s)%4)])

Let’s break this down into human-readable code.

The Logic Behind The Solution

Let’s look for a pattern that describes this pattern

    a          4 spaces + string[0]
   b *         3 spaces + string[1] + 1 spaces + string[-1]
  c   o        2 spaces + string[2] + 3 spaces + string[-2]
 d     n       1 spaces + string[3] + 5 spaces + string[-3]
efghijklm      string[4: -4+1]

Based on this pattern, we can split this function into these steps:

  1. Finding the height of our triangle
  2. Printing the first line
  3. Printing the 2nd line to the 2nd last line using a for loop
  4. Printing the last line

A multi-line solution

def hollow_triangle(s):
    # step 1: finding height of triangle
    height = len(s)//4 + min(1, len(s)%4) + 1
    # step 2: printing the first line
    print(" "*(height-1) + s[0])
    # step 3: printing the 2nd to 2nd last lines
    for i in range(1,height-1):
        print(" "*(height-i-1), end="")
        print(s[i], end="")
        print(" "*(i*2-1), end="")
        print((s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[-i])
    # step 4: printing the last line
    print((s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[height-1:2-height])

Step 1 — Finding the height of the triangle

  • strings of length 5, 6, 7 & 8 → triangle height of 3
  • strings of length 9, 10, 11 & 12 → triangle height of 4
  • strings of length 13, 14, 15 & 16 → triangle height of 5

Let’s say our string has a length which is a multiple of 4, and we increase string length by 1 — triangle height thus increases by 1 in this case. height can thus be expressed as len(s)//4 + min(1, len(s)%4) + 1

Step 2 — Printing the first line

The first line always consists of height-1 space characters followed by the character at index 0 in the string.

Step 3 — Printing 2nd line to 2nd last line

This step runs for height-2 iterations ( height minus the first and last line). Hence, we use the range function arguments range(1, height-1)

   b *         3 spaces + string[1] + 1 spaces + string[-1]
  c   o        2 spaces + string[2] + 3 spaces + string[-2]
 d     n       1 spaces + string[3] + 5 spaces + string[-3]

For each line, we need to concatenate these 4 sections together

  1. The spaces before the left letter → " "*(height-i-1)
  2. The left letter → s[i]
  3. The spaces between the left and right letter → " "*(i*2–1)
  4. The right letter → (s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[-i]

Only strings with lengths that are multiples of 4 can form perfect triangles. For strings with lengths that are non-multiples of 4, we add * behind to make their length a multiple of 4.

In section 4 (the right letter), the expression (s+"*"*(4-len(s)%4) if len(s)%4>0 else s) does exactly this:

  • "abcdefghi" (length 9) becomes "abcdefghi***" (length 12)
  • "abcdefghij" (length 10) becomes "abcdefghi***" (length 12)
  • "abcdefghijk" (length 11) becomes "abcdefghi***" (length 12)
  • "abcdefghijkl" (length 12) remains as it is

Step 4 — Printing the last line

Step 4 uses the same expression (s+"*"*(4-len(s)%4) if len(s)%4>0 else s) to print out the remaining unused characters.

Let’s now attempt to compress all of this stuff into one line.

Compressing this stuff into one line

Let’s first simplify the above code to pseudocode:

def hollow_triangle(s):
    height = # height formula
    print("line 1")
    for i in range(1, height-1):
        print("line 2 to line -2")
    print("last line")

Let’s first compress this function into 3 lines

def hollow_triangle(s):
    height = # height formula
    print(line1 + [line for i in range(1, height-1)] + lastline)

If we write out the actual code, we’ll get something like this:

def hollow_triangle(s):
    height = len(s)//4 + min(1, len(s)%4) + 1
    print(" "*(height-1) + s[0] + "\n" + "\n".join([" "*(height-i-1)+s[i]+" "*(i*2-1)+(s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[-i] for i in range(1,height-1)]) + "\n" + (s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[height-1:2-height])

Notice that our print statement uses height a couple of times. For the sake of writing everything in one line, let’s substitute every height with len(s)//4 + min(1, len(s)%4) + 1. And thus we get our answer:

def hollow_triangle(s):print(" "*(len(s)//4+min(1,len(s)%4))+s[0] + "\n" + "\n".join([" "*(len(s)//4+min(1,len(s)%4)-i)+s[i]+" "*(i*2-1)+(s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[-i] for i in range(1,len(s)//4+min(1,len(s)%4))]) + "\n" + (s+"*"*(4-len(s)%4) if len(s)%4>0 else s)[len(s)//4+min(1,len(s)%4):1-len(s)//4-min(1,len(s)%4)])

Some Final Words

Please don’t write actual production code like this — this article is for fun only, and no sane person writes code like this

Conclusion

I write coding articles (once per 1–2 days) that would have probably helped the younger me speed up my learning curve. Do join my email list to get notified whenever I publish.

If this article provided value and you wish to support me, do consider signing up for a Medium membership — It’s $5 a month, and you get unlimited access to articles on Medium. If you sign up using my link below, I’ll earn a tiny commission at zero additional cost to you.

Sign up using my link here to read unlimited Medium articles

If this article provided immense value for you, do consider buying me a coffee — every small contribution is appreciated greatly!

https://buymeacoffee.com/zlliu

Python
Python3
Python Questions
Python Quiz
Recommended from ReadMedium