Printing an ASCII diamond with set width in python - python

Yes, this is a homework task. But just please, if you're going to give me the code please tell me what you've done in detail. I am extremely new to this.
So the task is to print an ASCII diamond depending on what width the user inputs. I can do the first half of the diamond, just not the bottom half, for some reason I just cannot see how to do it.
Here's my code:
wid = int(input("Width: "))
i = 1
while i <= wid:
print(" " * (wid - i) + "* " * i)
i = i + 1
Which will output the following if wid = 5:
Width: 5
*
* *
* * *
* * * *
* * * * *

I tried to explain the code with comments. I hope it helps.
wid = int(input("Width: "))
#no. of lines will be double the width
#each loop prints a line.
for i in range(wid *2):
#first half of the diamond
if i<=wid:
no_of_spaces = wid - i
no_of_stars = i
print(" "*no_of_spaces + "* "*no_of_stars)
#next half of the diamond
else:
no_of_spaces = i - wid
no_of_stars = 2*wid - i
print(" "*no_of_spaces + "* "*no_of_stars)

i=1
j=input("ENTER NO =")
l=0
for i in range(i,j-((j/2)-1),1):
print (' ' * ((j+1)/2-i)+'*' *(i*2-1))
l=(j/2+1)
while (i==l):
i=1
for i in range(i,j,1):
print (' ' *((i*2)-i)+'*' *(j-i*2))
if [i==j-1]:
l=raw_input('<press enter to exit>')

You start with i = 1 and go until i > wid to make the top. To make the bottom of the diamond, you must do the reverse of what you did for the top. The code is easy, but I won't write it unless you want me to.

after your while
i=i-2
while i>0:
print(" "*(wid-i)+"* "*i)
i=i-1;

One method
The simplest way would probably be have two loops; one counting i up to width, another counting i back down to 1.
width = int(input("Width: "))
i = 1
while i < width:
print " " * (width-i) + "* " * i
i += 1
while i > 0:
print " " * (width-i) + "* " * i
i -= 1
This is a bit unattractive because it's a little clumsy, but it's simple.
Another method
Another method is to have have a loop that counts to twice the width, doing one of two things. What it does depends on if i has passed the point of maximum width or not. So it does 'up' and 'down' in the same loop, counting i from 1 up to width*2.
width = int(input("Width: "))
i = 1
while i < width*2:
if i < width:
print " " * (width-i) + "* " * i
else:
print " " * (i-width) + "* " * (2*width-i)
i += 1
This:
print " " * (width-i) + "* " * i
...is your code. Spaces count from width down to 0, *'s from 1 up to width.
And this:
print " " * (i-width) + "* " * (2*width-i)
...is the same thing but inverted. Spaces count from 0 back up to width, and the *'s go back down from width to 1. This comes into play when i exceeds width.
Width: 4
* # first half does this onward
* *
* * *
* * * *
* * * # second half does the rest downward
* *
*
And another
Another alternative, more complex way is to use a for loop on a list that contains numbers counting up and down. For example: [1, 2, 3, 2, 1]
To make this list, this code has to be. I know, it's a bit ugly:
rows = []
for i in range(1, max+1):
rows.append(i)
rows += rows[-2::-1]
Then, you see, we run the for loop off it.
width = int(input("Width: "))
rows = []
for i in range(1, width+1):
rows.append(i)
rows += rows[-2::-1] # takes a reversed list and adds it on to the end: [1, 2, 3, 2, 1]
for i in rows:
print " " * (width-i) + "* " * i
i iterates through each of the numbers in the rows list, which looks something like [1, 2, 3, 2, 1]. Then we just need one printing gizmo.
In python, there's almost always a shorter and less comprehensible way of doing for loops, and in this case, we can get rid of two extra lines by shortening the first for loop:
width = int(input("Width: "))
rows = [ i for i in range(1, width+1)] # Brain-bending way of doing a for loop
rows += rows[-2::-1]
for i in rows:
print " " * (width-i) + "* " * i
And if you're feeling a bit crazy, here's a mere two line version of the whole thing!
width = int(input("Width: "))
print "\n".join([ " "*(width-i) + "* "*i for i in [ i for i in range(1, width+1) ]+[ i for i in range(1, width+1) ][-2::-1] ])
But I don't recommend this style of coding in general.
Sorry, I got a bit carried away at the end... but the best thing I can say to you now is try everything and play around!
Hope that helps. :)

Since some good methods have been addressed, here are some fun little hacky solutions.
Here's one using Python 2.7 string.center just for shits.
import string
width = int(raw_input("Width:"))
for i in range(width):
print string.center(i * " *", width * 2 )
for i in range(width,0,-1):
print string.center(i * " *", width * 2 )
And here's an outrageous one that ouputs using HTML to center.
file = open('file.html','w')
file.write("<div align='center'>")
for i in range(width):
file.write(i * " *")
file.write("<br>")
for i in range(width,0,-1):
file.write(i * " *")
file.write("<br>")
file.write("</div>")
file.close()
import webbrowser
webbrowser.open("file.html")

check it out (for python 2.7x) :
Filled ASCII Diamond :
width = 1
width += int(raw_input('Width : '))
for i in range (1,width):
for j in range (width,i,-1):
print " ",
for j in range (1,i,1):
print " * ",
print
for i in range (width,1,-1):
for j in range (width,i,-1):
print " ",
for j in range (1,i,1):
print " * ",
print
This works!! But not in any Browser window . . .

Related

Printing Pattern Horizontally in Python

So I have to print * in the shape of A which I did.
pattern = ""
for row in range(7):
for col in range(5):
if ((col==0 or col==4) and row!=0) or ((row==0 or row==3) and (col>0 and col<4)):
pattern = pattern + "*"
else:
pattern = pattern + " "
pattern = pattern + "\n"
pattern = pattern + " "
print(pattern, end="")
OUTPUT:
***
* *
* *
*****
* *
* *
* *
But I want to print more A horizontally.
Example: L displayed as star program 3 times looks as below
* * *
* * *
* * * * * * * * *
Please help!
I did not change a lot in your code, but thought that putting it in a function might be useful. As you can see in the last line, you now just have to call it with the number of letters you want to print. Furthermore, I added a for-loop in between yours, in order to get all the required symbols into the according line.
Lastly, I added an if/else staement that checks this is the end of the row and otherwise does not go into the next line.
def multiplePatterns(n):
pattern = ""
for row in range(7):
for i in range(n):
for col in range(5):
if ((col==0 or col==4) and row!=0) or ((row==0 or row==3) and (col>0 and col<4)):
pattern = pattern + "*"
else:
pattern = pattern + " "
if i == n-1:
pattern = pattern + "\n"
else:
pattern += " "
pattern = pattern + " "
return pattern
print(multiplePatterns(2))
The easiest way is to use a library like pyfiglet : https://pypi.org/project/pyfiglet/ .
If you want to do it yourself, python console write per line, you must print your text (ex:"AAA") line per line.
if your final goal is just that, then:
print(" *** *** ***")
print("* * * * * *")
print("* * * * * *")
print("***** ***** *****")
print("* * * * * *")
print("* * * * * *")
print("* * * * * *")
will do the job.
If your goal is to write any text, then its probably better to create some kind of "font" with each letter in a list.

Printing two different squares (made of asterisks) adjacent to each other?

I didn't know how to describe it in the question properly, so I'll try again here.
I have to solve this question where my code should print different types of squares. I have all of that figured out, however, I'm stuck at the printing part.
So, I start by inputting 4 as the size, and it results in different types of squares being made. For example, these two:
first = ""
for j in range(size-1):
first += "*" * size + "\n"
first += "*" * size
two = ""
for j in range(size-1):
if j == 0:
two += "*" * size + "\n"
else:
two += "*" + ((size - 2) * " ") + "*" + "\n"
two += "*" * size
Now, I have to print them like this:
**** ****
**** * *
**** * *
**** ****
separated by a '\t'.
Since these squares are 'stored' in different strings, this is unfamiliar territory for me as the cursor is at the end of the first square. I don't know what to do, help pls.
There are many ways for that, one is here:
>>> v = '\n'.join([i+'\t' + j for i,j in list(zip([i for i in first.split('\n') if i], [ i for i in two.split('\n') if i]))])
>>> print(v)
**** ****
**** * *
**** * *
**** ****
What i did:
Splitted both strings at newline character, then took corresponding parts and joined them by tab in between, then assembled the whole string.
You can change the data structure you use. Let the square will be not a string, but list of strings, where each string is line should be printed.
Then you can for each line write line_first + '\t' + line_two and print it.
This code worked as you expect.
first = []
for j in range(size - 1):
first.append("*" * size)
first.append("*" * size)
two = []
for j in range(size - 1):
if j == 0:
two.append("*" * size)
else:
two.append("*" + ((size - 2) * " ") + "*")
two.append("*" * size)
for f, t in zip(first, two):
print(f + '\t' + t)

Python 3 centered triangle

I'm trying to hone my Python 3 (specifically, nested loops) with the good old triangle exercises (which only takes an odd input for now). However, I have come across a problem I can't warp my head around with.
user_input = 7
x = 1
temp = user_input
spaces = " "
stars = ""
y = temp - 2
t = 0
while x < temp:
while y > t:
stars = "*" * x
spaces = spaces * y
print(spaces + stars)
spaces= " "
y -= 1
x += 2
I have a user_input (which is 7 for now so I don't have to give an input each time I run).
A variable x and t used for the while loop
Another temporary variable that holds my user_input (in case I decrement it as not to 'damage' the original variable).
A variable spaces and another variable stars (which should be self explanatory as I'm trying to draw a triangle based on asterisks).
I have a variable y which is equal to temp - 2
Expected output of 7 should be like this:
*
***
*****
*******
The reason I have made y equal to temp - 2 is because the first row has spaces equal to user_input - 2.
So let's say our input was 7, first row's amount of spaces is 5.
If our input is 9, first row's amount of spaces is 7
The first while loop will loop from 1 to 7 (1, 3 , 5, 7) which is why I made x equal to 1.
The second while loop should loop from input - 2 until 0.
Weird thing is, that if my user_input is equal to 5, it outputs just how I expected it to be.
*
***
*****
But once I enter something like 7, it builds a triangle from 1 to 9 (1, 3, 5, 7, 9)
*
***
*****
*******
*********
But I expect it to end right before the last row, it should output as many asterisks as my input.
Is my thought process wrong? If so, where did I end up wrong?
I hope I have clarified everything as much as possible.
Thanks a bunch.
Seems overly complicated. Why not just:
input = 7
i = 1
while i <= input:
spaces = ' ' * ((input-i) // 2)
stars = '*' * i
print(spaces + stars)
i += 2
*
***
*****
*******
Or even simpler, using str.center:
while i <= input:
print(('*' * i).center(input))
i += 2
Let's clarify a bit your code a bit :
t is useless since it holds only 0 and never changes, use 0 instead
user_input is never used except to make temp = user_input, use user_input instead of temp. As for decrementing it, it doesn't happen, and anyway you never return it to the user so it would be ok.
that's kind of a typo so it's ok, but avoid letting your debugging prints like print(x,y) when you show some code on Stack Overflow, it's harder for us to understand the whole code.
If you change back spaces = " " at the end of the while, just use spaces = " " * y.
You do nothing between the two while so you can "merge" them with an and on conditions.
So now we have :
user_input = 9
x = 1
y = user_input - 2
while x < user_input and y > 0:
stars = "*" * x
spaces = " " * y
print(spaces + stars)
y -= 1
x += 2
As you can see, you have two stopping conditions on your while when only one would be clearer. The reason behind your code works with 7 and not more is because 7 is the limit between when one condition stops loop and when the other does.
I would suggest to change your code to :
user_input = 3
x = 0
while x < user_input//2:
stars = "*" * (x * 2 + 1)
spaces = " " * (user_input//2 - x)
print(spaces + stars)
x += 1
There is a bug in your code. Here is the rectified code.
user_input = 7
x = 1
temp = user_input
spaces = " "
stars = ""
y = temp - 2
t = 0
while x <= temp:
stars = "*" * x
spaces = spaces * y
print(spaces + stars)
spaces= " "
y -= 1
x += 2
It is not necessary to check y>0 since your first while loop is enough to meet the requirement. Because of that extra while loop you are getting ambiguous values of (x,y).
The lazy solution using the builtin center() and the format mini language:
user_input = [5,7,9]
def getStars(num):
return ('*' * i for i in range(1,num+1,2))
def sol1(num):
for s in getStars(num):
print(s.center(num))
def sol2(num):
stars = getStars(num)
for s in stars:
print( ("{:^"+str(num)+"}").format(s))
for s in user_input:
sol1(s)
sol2(s)
Output:
*
***
*****
*
***
*****
*
***
*****
*******
*
***
*****
*******
*
***
*****
*******
*********
*
***
*****
*******
*********

W by H grid tiles?

Imagine that we have a w by h grid, where the tiles are numbered starting at 1 in the top left corner. w (for width) and h (for height) have been stored in a function. You have access to these stored values, as long as you call them w and h. Write a program to return: The column number of a tile number given by the user. Start counting columns at column 1.
import subprocess
def template(w, h, t):
#w and h are memory locations that already contain values
tile = t
sum = ((t - 1) // w) + 1
#END OF YOUR CODE
failed = 0
width = 1
while width <= 3:
height = 1
while height <= 3:
tile = 1
while tile <= width * height:
result = template(width, height, tile)
col = (tile - 1) % width + 1
if (result == col):
print "On a " + str(width) + " by " + str(height) +" board, with tile " + str(tile) +", col is " + str(col) + ", you got it RIGHT!"
else:
print "On a " + str(width) + " by " +:str(height)%+" board, with tile " + str(tile)%+", col is " + str(col) + ", you got: " + str(result)
failed = 1
tile += 1
height += 1
width += 1
if (failed == 0):
print "Your code is CORRECT!"
print "Please check your code, at least one test case did not pass."
I am almost there I think, but this formula isn't quite right and I'm out of ideas.
See below pseudo code, this approach should work for you,
# divide t by h, the tile should reside in the next row
tileRow = (t/h)+1
# get the reminder of the division, that's the column number
tileColumn = t%h
see the sample code I tried below
>>> w = 5
>>> h = 10
>>> t =36
>>> tileRow = (t/h)+1
>>> tileRow
4 # the tile is in the 4th row
>>> tileColumn = t%h
>>> tileColumn
6 # the tile is in the 6th column
>>>
You may also have to check if the tile number is within in range, in the above example its w x h (50)
Please comment if you need anymore clarification. If this resolves your problem you may accept and vote the answer
To create the grid, use a list comprehension.
grid=[list(range(x,x+w))for x in range(1,w*h,w)]
To find the column number of t, find the remainder of t divided by w:
t%w
So the function would be:
def template(w,h,t):
grid=[list(range(x,x+w))for x in range(1,w*h,w)]
return t%w
Example:
template(6,5,22)
Output:
4

Printing X-type pattern in Python 2.7

I'm trying to print this pattern in Python:
*............*
.**........**
..***....***
...********
...********
..***....***
.**........**
*............*
And came up with this code that does the job:
for row in range(1,5):
print "." * (row -1) + row * "*" + (16 - row * 4) * "." + row * "*"
for row in range (0,4):
print("." * (3-row)+ "*" *(4 -row) + row * 4 * "." +"*" *(4 -row))
My question: is it possible to do this without using two loops? BTW, this is not for homework, I'm just playing around with some exercises from "Think Like a Programmer" by V. Anton Spraul and implementing the solutions in Python rather than C++.
Thanks in advance.
Without changing anything else, you can just do the loop over two ranges:
for row in range(1,5)+range(4,0,-1):
print "." * (row -1) + row * "*" + (16 - row * 4) * "." + row * "*"
Since you can add lists together:
In [8]: range(1,5)
Out[8]: [1, 2, 3, 4]
In [9]: range(4,0,-1)
Out[9]: [4, 3, 2, 1]
In [10]: range(1,5) + range(4,0,-1)
Out[10]: [1, 2, 3, 4, 4, 3, 2, 1]
By the way, you can get rid of the leading dots using spaces:
for row in range(1,5)+range(4,0,-1):
print " " * (row -1) + row * "*" + (16 - row * 4) * "." + row * "*"
*............*
**........**
***....***
********
********
***....***
**........**
*............*
A more elegant thing to do might be to build a list of strings:
X = []
for row in range(1,5):
X.append(" " * (row -1) + row * "*" + (16 - row * 4) * "." + row * "*")
Now, add the bottom half by just duplicating the top half in reverse:
X = X + list(reversed(X))
But when we print it we see a list:
print X
#['*............*', ' **........**', ' ***....***', ' ********', ' ********', ' ***....***', ' **........**', '*............*']
So we can join them together with newlines:
print '\n'.join(X)
*............*
**........**
***....***
********
********
***....***
**........**
*............*
here's an answer with one while loop
def star(size=14): ##size for the star in your post
asterisk=1;
space=0;
def func(x):
x+=1
return x
def decrement(x):
x-=1
return x
while (asterisk > 0):
line=''
line+=' '*space
if((size-(2*space)-(2*asterisk))<=0):
line+='*'*(size-(2*space))
else:
line+='*'*asterisk
line+=' '*(size-(2*space)-(2*asterisk))
line+='*'*asterisk
print ''.join(line)
if((size-(2*space)-(2*asterisk))<=0):
func=decrement ### switch to decreasing number of asterisks after we cross the middle of the star
print ''.join(line)
space=func(space);
asterisk=func(asterisk);
for i in range(20): ##whee
star(i)
I liked askewchan's elegant approach which noticed the symmetry between the top and bottom. There is also left-right symmetry. Here's an attempt to take advantage of that (it does have two loops though):
stars = [" "*(row-1) + "*"*row + " "*(8-row*2) for row in range(1,5)]
for line in stars + list(reversed(stars)):
print line + line[::-1]

Categories

Resources