0

I am beginning in python programming and I have this exercise that requires me to put text into a box of stars.

Example :

*******
*  I  *
* am  *
* in  *
*  a  *
* box *
*******

I print this :

********
*  I  *
*  am  *
*  in  *
*  a  *
* box! *
********

So far I have this, I feel like I am close to the solution.

phrase = "I am in a box!"

phraseSplit = phrase.split(' ')

longuestString = max(phraseSplit, key=len)

#print(len(longuestString))

def maxStars(longuestString):
    stars = (len(longuestString)+4) * "*"
    print(stars)


maxStars(longuestString)

for i in range(len(phraseSplit)):
    delta = len(longuestString) - len(phraseSplit[i])
    space = int(delta/2 +1)
    
    print("*" + space * " "+ phraseSplit[i] + space  * " " +"*")
    
maxStars(longuestString)

Help me optimize or find other ways that could be more efficient. Thank you

  • 1
    Could the problem be a rounding issue? If you have odd number as longest string that the space at the even numbers should be calculated different than in your solution. So that you should let the even strings at the right or left side inside the space – sheldor May 18 '21 at 13:32
  • Some of the answers to [How can I fill out a Python string with spaces?](https://stackoverflow.com/q/5676646/15497888) might be able to help you more easily orient the words within the internal space of the box. – Henry Ecker May 18 '21 at 13:34
  • The top and bottom of the first example are 7 long. On yours it's 8. – Have a nice day May 18 '21 at 13:37
  • Thank you i will check it out – cocoteminute May 18 '21 at 13:51
  • Your code assumes that the same space is needed before and after the word. What if you adjusted the spacing after the word by comparing the total required spaces with those already allocated to the padding before the word? – JonSG May 18 '21 at 13:56
  • That would make a lot of sense – cocoteminute May 18 '21 at 14:04

2 Answers2

1

Here's how I would do it:

phrase = "I am in a box"
words = phrase.split(' ')
longest = max(words, key=len)
width = len(longest)
pretty = "\n".join(["*"*(width+4),*[f"* {w[::-1].center(width)[::-1]} *" for w in words],"*"*(width+4)])

print(pretty)

*******
*  I  *
* am  *
* in  *
*  a  *
* box *
*******

Now let's break it down!

First we do what you did, splitting the phrase into words and extracting other helpful data:

phrase = "I am in a box"
words = phrase.split(' ')
longest = max(words, key=len)
width = len(longest)

Then comes the real algorithm. Let's make a list of one string per line. Clearly the first and last lines are going to be the length of the longest plus 4 (i.e. (wall + padding)*2).

So at the start and end of the list we put:

"*"*(width+4)

Then we need to fill in the actual meat of the box. We're going to use a list iteration to make as many string as there are lines, and join each line with \n:

[line_contents for w in words]

But we need to actually have line_contents be something for each line. So let's replace that with an f-string.

At the start and end of each line there is the padding (ignoring the extra padding the small words have) and an asterisk. So our f-string is currently f"* {padded_word} *".

To actually make the padded words, we can use str.center(width). This gives the whole f-string as f"* {w.center(width)} *".

Now putting everything together we get:

"\n".join(["*"*(width+4),*[f"* {w.center(width)} *" for w in words],"*"*(width+4)]

NOTE: I used the * operator to unpack the list iteration into the larger list.

If we run the program we get:

*******
*  I  *
*  am *
*  in *
*  a  *
* box *
*******

Looks good! But wait one moment - it seems like str.center is making the off-center words go to the right! This is contrary to your example.

However, there's an easy solution: reverse the word, pad it, then reverse it back. This will make the off-center words go left instead. To reverse any indexable object, you can use slice notation: [start, stop, step] --> [beginning, end, -1] --> [::-1].

Now if we add this into what we have so far, we get what I presented initially.

Lucas Ng
  • 671
  • 4
  • 11
0

I finally found my own answer :

phrase = "Hi I am in a box!"

phraseSplit = phrase.split(' ')

longuestString = max(phraseSplit, key=len)

#print(len(longuestString))

def maxStars(longuestString):
    stars = (len(longuestString)+4) * "*"
    print(stars)


maxStars(longuestString)

for i in range(len(phraseSplit)):
    delta = len(longuestString) - len(phraseSplit[i])
    space = int(delta/2 +1)
    
    if (delta % 2) != 0: 
        
        print("*" + space * " "+ phraseSplit[i] + space  * " " +" *")
    
    else:
        print("*" + space * " "+ phraseSplit[i] + space  * " " +"*")
        
    
maxStars(longuestString)

I am aware there are optimal ways to do this and I need to figure it out.