Given a odd positive integer h, greater than or equal to 5, create a bowtie pattern with h rows and 2h columns.
input: 5
output:
* *
*** ***
**********
*** ***
* *
or
input: 7
output:
* *
*** ***
***** *****
**************
***** *****
*** ***
* *
I created code that only works for one given value of h but I'm not sure how to make it functional for any value of h. I also tried taking advantage of the symmetry so I made only half of the bowtie.
h = input()
n = int(h)
x = "*"
space = " "
print(x)
print(-(-n // 2)*x)
print(n*x)
print(-(-n // 2)*x)
print(x)
You can build up the top half by left and right justifying the * repeated as many times as necessary (we use range with a step for this as the first row will have 1 *, the next 2 more, the next 2 more again up until we reach N) padded left and right with width n, eg:
n = int(input())
top = [('*' * i).ljust(n) + ('*' * i).rjust(n) for i in range(1, n, 2)]
This gives you a top (for n=5) of:
['* *', '*** ***']
Then, we print the top, the middle (which is always * repeated N*2 times) and then top in reverse order for the bottom separated by newlines, eg:
print(*top, '*' * n * 2, *reversed(top), sep='\n')
Gives you (n=5):
* *
*** ***
**********
*** ***
* *
Or for (n=11):
* *
*** ***
***** *****
******* *******
********* *********
**********************
********* *********
******* *******
***** *****
*** ***
* *
Symmetry tells you that the left and the right have the same number of *. It also tells you that the middle row is all stars (n * 2), and that each row the same distance above and below the middle row has the same size. Further, as you move away from the center, you lose 4 stars total, 2 from each side.
The two secrets to coding this concise are to 1) number the rows symmetrical, not from 1 to n, but from -n//2 to n//2; and 2) to think of the rows as a number of spaces drawn on a background of *s, rather than a number of *s surrounding spaces.
Once you figure out how many spaces are in each row (call it f(i), based on the value of i in for i in range(-n//2, n//2+1): ..., you can draw that row with (" "*f(i)).center(2*n, "*").
it will work for any odd number
h = input()
n = int(h)
i = 1
if(n%2)!=0 and n > 4:
halfmark= n//2
str=""
while i <= n:
if(i<=halfmark):
blank = ' '* (4*(halfmark +1-i))
elif i > (halfmark+1):
blank = ' '*(4*(i-(halfmark+1)))
else:
blank = ''
star = '*'*((2*n-len(blank))//2)
str = star+blank+star
print(str)
i +=1
Related
LAB: Drawing a right side up triangle
Write a recursive function called draw_triangle() that outputs lines of * to form a right side up isosceles triangle. Function draw_triangle() has one parameter, an integer representing the base length of the triangle. Assume the base length is always odd and less than 20. Output 9 spaces before the first * on the first line for correct formatting.
Hint: The number of * increases by 2 for every line drawn.
Ex: If the input of the program is:
3
the function draw_triangle() outputs:
*
***
Ex: If the input of the program is:
19
the function draw_triangle() outputs:
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
Note: No space is output before the first * on the last line when the base length is 19.
I have been able to figure out the recursion part but I cant figure out getting the right white space to the left of the triangle
If I understand your problem correctly, you see that the "top" of the triangle, always has one * in it. Then if the base of the triangle is n, the "top" row should have n - 1 spaces in it.
Continuing the pattern you can see that with every row under the top, you add 2 *'s. Then any given row will have n - 2r - 1 spaces if r is the row (starting from the top, r = 0).
Here's the cool part, since you know n is odd (given in question) and 2r is definitely even, then n - 2r - 1 is always going to be even. Call half this number the "whitespace amount" and print out that amount of spaces for each row (and remember, the row r starts from 0).
Here's some pseudo code
def print_triangle(width, row):
if 2 * row + 1 == width: # if you are in the last row
for i < 2 * row + 1:
print("*") # print the *
return # break out of recursion
else:
for i < (width - 2 * row - 1) / 2:
print(" ") # print whitespace
for i < 2 * row + 1:
print("*") # print the *
return print_triangle(width, row + 1) # recursive call
of course there are many more ways to do this, some of which will have more concise code, but hopefully this pseudo code helps you understand the logic behind the program.
You can't just have a single variable for recursion:
This code would help you:
def draw_triangle(n,i):
if(n<=0):
return
print(" "*(n//2),end="")
print("*"*i)
draw_triangle(n-2,i+2)
draw_triangle(19,1)
Output:
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
Hope this helps you. Here i=1 since you need to print 1 star at the begining.
For your weird request to have 9 space for all input :))
def draw_triangle(n,i=1,s=9):
if(i>n):
return
print(" "*s+"*"*i)
draw_triangle(n,i+2,s-1)
draw_triangle(3)
Here i represents how many stars in first line and s represent space in first line.
Output:
*
***
I do need to create two recursive functions in Python. the first function should create a pyramid with a given parameter n. for example pyramid(3) should have the following output
*
***
*****
I came up with the following function:
def pyramid(n, i=0):
if n == 0:
return 0
else:
print(" "*(n-1) +"*"*(2*i+1)+ " "*(n-1))
return pyramid(n-1, i+1)
Now I do need to create a second recursive function pyramid_seq with 2 parameters n,k what prints a sequence of pyramids in with height of n. for example pyramid_seq(3,4) should have the following output:
* * * *
*** *** *** ***
********************
Add another parameter to your function (notice the changes in the recursive call) that determines how many times you should print every line. This will create the desired effect.
def pyramid(n, k, i=0):
if n == 0:
return 0
else:
print(k*(" "*(n-1) +"*"*(2*i+1)+ " "*(n-1)))
return pyramid(n-1, k, i+1)
Output for pyramid(4, 6):
* * * * * *
*** *** *** *** *** ***
***** ***** ***** ***** ***** *****
******************************************
If you want to properly leverage the power of recursion, your function should return their result as data and the printing part should be separate. This will allow you to reuse a previously defined function to produces new results from it:
def pyramid(h):
if h==1: return ["*"]
return [" "+p+" " for p in pyramid(h-1)]+["*"*(2*h-1)]
The function returns an array of lines (strings) that you can print or reuse for something else:
print(*pyramid(5),sep="\n")
*
***
*****
*******
*********
Because you now have a function that generates a pyramid as a list of lines, you can reuse it to concatenate its result to form a series of pyramids without reinventing the wheel:
def pyramids(h,w):
return [p*w for p in pyramid(h)]
print(*pyramids(4,6),sep="\n")
* * * * * *
*** *** *** *** *** ***
***** ***** ***** ***** ***** *****
******************************************
If your second function also needs to be recursive, you can still reuse the first one to build it:
def pyramids(h,w):
if w == 1: return pyramid(h)
return [ ps+p for ps,p in zip(pyramids(h,w-1),pyramid(h)) ]
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
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) == [' * ', ' *** ', ' ***** ', ' ******* ', '*********']
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.
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.
I made a program that allows the user to type in the height of a diamond and it will print one out in asterisks using loops. My code now looks like this:
diamond = int(input("Height": )
for i in range(diamond-1):
print((diamond-i) * " " + (2*i+1) * "*")
for i in range(diamond-1, -1, -1):
print((diamond - i) * " " + (2 * i + 1) * "*")
And the diamond will look perfect like this (diamond == 6):
*
***
*****
*******
*********
***********
*********
*******
*****
***
*
Now if I make some changes and instead write the backwards loop like this:
for i in reversed(range(diamond-1)):
print((diamond - i) * " " + (2 * i + 1) * "*")
It will print out the diamond like this:
*
***
*****
*******
*********
*********
*******
*****
***
*
So my question is: what is the difference between the first backwards loop and the second one I wrote? Why do they turn out so different?
Because they are different ranges:
>>> diamond = 6
>>> range(diamond-1, -1, -1)
[5, 4, 3, 2, 1, 0]
>>> list(reversed(range(diamond-1)))
[4, 3, 2, 1, 0]
range includes the start point, but excludes the end point.
You may have noticed my last query on a similar task.
I am trying to replicate this structure:
********************
********* *********
******** ********
******* *******
****** ******
***** *****
**** ****
*** ***
** **
* *
** **
*** ***
**** ****
***** *****
****** ******
******* *******
******** ********
********* *********
********************
If you think of it as composed of 4 triangles - I am able to produce each of the corners individually, then to put them under one another.
I do not know how I would go about putting them together in a larger construct though.
Would I attempt this, or would I approach the problem by tackling it as if were a single construct and work on it line by line as I did with the individual triangle parts? I just assumed that the triangles into a bigger thing might be a shortcut.
This worked for me
w = 20
lines = []
for y in xrange(w / 2, 0, -1):
lines.append("".join(("*" * y, " " * (w - (y * 2)), "*" * y))
lines += reversed(lines[:-1])
for l in lines:
print l
You could shrink it down more if you wanted to as well:
lines = ["".join(("*" * y, " " * (w - (y * 2)), "*" * y)) for y in xrange(w / 2, 0, -1)]
print "\n".join(lines + lines[-2::-1])
Output w = 20:
********************
********* *********
******** ********
******* *******
****** ******
***** *****
**** ****
*** ***
** **
* *
** **
*** ***
**** ****
***** *****
****** ******
******* *******
******** ********
********* *********
********************
print '\n'.join('*' * (20 - i) + ' ' * (i * 2) + '*' * (20 - i) for i in range(0, 20))
print '\n'.join('*' * i + ' ' * (40 - i * 2) + '*' * i for i in range(0, 20))
http://codepad.org/Z46ldEOG
I would treat it as a different problem. If you imagine an origin at the centre of the figure, then you only want to print a * where the "Manhattan distance" to that cell is greater than half the length of the edge. For example, you could do the following:
import sys
r = 5
for y in range(-r,r+1):
for x in range(-r,r+1):
c = ' ' if (abs(x) + abs(y)) < r else '*'
sys.stdout.write(c)
print
... which produces this:
***********
***** *****
**** ****
*** ***
** **
* *
** **
*** ***
**** ****
***** *****
***********
How about:
W = 10
for i in range(10):
this_str = "*"*(W-i)+" "*i
print this_str+this_str[::-1]
for i in range(9,-1,-1):
this_str = "*"*(W-i)+" "*i
print this_str+this_str[::-1]
Peer pressure at work. Here's a shorter version to keep up with all my compatriots:
W=10
lines = ["*"*(W-i)+" "*2*i+"*"*(W-i) for i in range(W)]
print "\n".join(lines + lines[-2::-1])
If your instructor was looking for simple loops, this may help (even though its probably too late, and it only really works with even "w" value's)
w = 20
for a in range (0,w/2):
print((w/2-a)*"*"+2*a*" "+(w/2-a)*"*")
for a in range (2,w/2+1):
print(a*"*"+(w-2*a)*" "+a*"*")
Or if you wanted to take out the variable "w" all together:
for a in range (0,10):
print((10-a)*"*"+2*a*" "+(10-a)*"*")
for a in range (2,11):
print(a*"*"+(20-2*a)*" "+a*"*")