1

i'm working on this challenge, wherein based on a number given it will show the asterisk (*) increment per odd number. Basically the result should be if I run the function below and set the n_floor to 5 it should show the result below. My code somehow iterates per number of floor and increments the * per odd number but the result fails but this is because the spacing of the asterisk between those quotes are wrong. Any idea/tip how to fix this?

a. Correct Result

['    *    ', '   ***   ', '  *****  ', ' ******* ', '*********']

b. REsult from my script below:

['*', '***', '*****', '*******', '*********']
def tower_builder(n_floor):
    a = '*'
    b = 1
    c= 0
    result = []
    num=range(1, n_floor+1)

    # * to increment by odd number
    for x in num:
        c = a
        result.append(c)
        a += str('**')
    return result
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 1
    use `str.center` – wjandrea Oct 31 '19 at 17:01
  • 2
    Possible duplicate of [Python: String Formatter Align center](https://stackoverflow.com/questions/44781484/python-string-formatter-align-center) – wjandrea Oct 31 '19 at 17:02
  • @wjandrea string formatting won't work as the amount of spaces on either side needs to vary according to n_floor. – andyhasit Oct 31 '19 at 17:21
  • 1
    @andyhasit Then just calculate the width: `width = 2 * n_floor - 1` ... `a.center(width)` – wjandrea Oct 31 '19 at 17:24
  • 2
    @wjandrea actually you are right. I didn't think you could specify the numbers in a format string as variables but you can `line = '{stars:^{size}}'.format(size=size, stars=stars)`. I added a full answer below too. – andyhasit Oct 31 '19 at 17:38
  • 1
    @andyhasit Neat! I didn't know you could do that either! Still, `line = stars.center(size)` is simpler :p – wjandrea Oct 31 '19 at 17:40

3 Answers3

5

Here's a better way which calculates the width you need:

def tower_builder(n_floor):
    result = []
    width = (n_floor * 2) - 1
    for x in range(1, 2 * n_floor, 2):
        stars = x * '*'
        line = stars.center(width)
        result.append(line)
    return result


assert tower_builder(1) == ['*']
assert tower_builder(2) == [' * ', '***']
assert tower_builder(3) == ['  *  ', ' *** ', '*****']
assert tower_builder(4) == ['   *   ', '  ***  ', ' ***** ', '*******']
assert tower_builder(5) == ['    *    ', '   ***   ', '  *****  ', ' ******* ', '*********']
andyhasit
  • 14,137
  • 7
  • 49
  • 51
2

Here is a one-liner function:

def tower_builder(n):
    return [('*' * i).center(n * 2 - 1) for i in range(1, 2 * n + 1, 2)]

Because each row of the tower is formed of an odd number of *, we need to loop oddly, Thus we set the loop max to the 2 * n with step of 2 to ensure that we are looping through odds.

Then we use center function to give the tower the final Pyramidal shape.

  • 2
    Welcome to Stackoverflow. Please explain your answer how it solves, so others can understand easily. – octobus Dec 13 '19 at 14:07
1

Like the comments say, you will want to use str.center. For a concrete example, it would also point out that every "floor" has an odd number of characters, so you can actually simplify your function a bit.

def tower_builder(n_floor):
    window = '☐'
    total_width = 20  # this may get bigger if you have a very tall building

    floor_strings = []
    for floor_idx in range(n_floor):
        # because widths are always odd
        width = 2 * floor_idx + 1
        # construct this floor
        floor_string = (window*width).center(total_width)
        # add it to the list
        floor_strings.append(floor_string)

    # join them all together with newlines
    return '\n'.join(floor_strings)

print(tower_builder(5))                                                                        
         ☐          
        ☐☐☐         
       ☐☐☐☐☐        
      ☐☐☐☐☐☐☐       
     ☐☐☐☐☐☐☐☐☐      

As a side note, you can actually calculate what total_width must be by starting with the widest floor (or calculating it, which isn't terribly hard) and using that as total_width.

Andrew F
  • 2,690
  • 1
  • 14
  • 25