Printing an arrow head using stars - python

I am trying to print out an arrow head using *s.
So far my code looks like this.
def head(n):
while n > 0:
print n * "*"
n = n - 1
print head(input())
and it works but if for example I enter 11, it prints this:
***********
**********
*********
********
*******
******
*****
****
***
**
*
But I want it to print like this:
*
***
*****
*******
*********
***********
Which has less arrows, but I can't figure out how to do it.

It makes the function a little simpler to think in terms of how many lines do you want:
def head(lines):
for n in range(1,lines*2,2): # count 1,3,5...
print(('*'*n).center(lines*2-1))
Output:
>>> head(5)
*
***
*****
*******
*********
Here's an alternate way to use a variable length format that is a little less obvious:
def head(lines):
for n in range(1,lines*2,2):
print('{:^{}}'.format('*'*n,lines*2-1))

use string formatting:
def head(size):
n=1
while n < size+1:
stars = n * "*"
print '{:^30}'.format(stars)
n += 2
it will center your asterisks on the field 30 chars wide.

def printHead(n):
for l in range(1,n):
print " "*(n-l)+"*"*(1 if l==1 else 2*l-1)
Each row has level-1 spaces. Then if it's the first level one start, otherwise it has 2*level-1.
>>> printHead(6)
*
***
*****
*******
*********

def head(n):
total = 2 * n - 1
s = ''
for i in xrange(1, n + 1):
k = 2 * i - 1
s += ' ' * ((total - k) / 2) + '*' * k + '\n'
return s

The number of stars on a line is equal to 2n - 1 where n is the line number.
I wouldn't call the parameter "n" in this function as it is not clear to me whether it refers to lines or stars.
You can use the center function to surround a string with whitespace, based on a specified width. You want the arrow to be centred around the longest line so you need 2 variables, one to keep track of the current line and another to remember the largest line.
You want to iterate in the opposite direction to what you have demonstrated, as you want the arrow to point up, not down.
I think this should work for you:
def head(total_lines):
for current_line in range(1, total_lines + 1):
print ((2 * current_line - 1) * "*").center(2 * total_lines - 1)

Related

Is it possible to nest all 4 of these nested For loops into one For loop with an extra level?

I'm learning Python from a textbook and one of the exercises (there is no answer key available!) wants you to create 4 patterns of asterisks. This code creates the correct output.
As you can see it is 4 separate code blocks each with nested For Loops. My question is to whether it is possible to put it all into 1 For loop that is nested one level deeper (e.g. For group in range(4) > For row in range(10) > For asterisk in range(etc.)? Or since the output of each code block is different, is this most granular I could go?
Any insight is much appreciated!
for row in range(10):
for asterisk in range(row + 1):
print('*', end='')
print()
print()
for row in range(10):
for asterisk in range(10 - row):
print('*', end='')
print()
print()
for row in range(10):
print(' ' * row, end='')
for asterisk in range(10 - row):
print('*', end='')
print()
print()
for row in range(10):
print(' ' * (9 - row), end='')
for asterisk in range(row + 1):
print('*', end='')
print()
Before trying to push the code into another level of for loops, let's try to make a function that represents the needed logic for each part.
Start with one version of the code, and stub out the parts that change. Add a function header, and stub out the parameters for now.
def triangle(...):
for row in range(10):
...
for asterisk in range(...):
print('*', end='')
print()
Notice that I did not include the print in between the triangles. That has separate logic (we want to do it every time except the first; not because of what kind of triangle we're drawing)
Before we try to figure out how to fill in the blanks, let's try to simplify the code by using what we already know. The existing code uses print(' ' * row, end='') or print(' ' * (9 - row), end='') to print a specific number of spaces (determined by row). The for loop is used to print a specific number of asterisks. Clearly, we can use the * technique instead. So:
def triangle(...):
for row in range(10):
...
print('*' * ..., end='')
print()
And having done that, we see that we have a print that deliberately suppresses the newline at the end, immediately followed by an empty print used only to display a newline. That doesn't make a lot of sense. We could just:
def triangle(...):
for row in range(10):
...
print('*' * ...)
Much better.
Next: is our logic actually conditional? In the original versions of the code, we sometimes had a print for some spaces, and other times not. But we can unify that: "not printing spaces" is the same thing as "printing zero spaces"; so really all we need is a rule that tells us how many spaces to print, and then we can use the same structure every time:
def triangle(...):
for row in range(10):
print(' ' * ..., end='')
print('*' * ...)
In fact, we can combine these prints. We want to print two things one right after the other (i.e. with an empty sep in between), and we want the default newline to be printed after that. So:
def triangle(...):
for row in range(10):
print(' ' * ..., '*' * ..., sep='')
Much better. On to the part where we actually fill in the blanks.
First off, what information do we have to pass in? We need to know two things: whether to right-align the triangle, and whether to print it upside-down or not. So those are our parameters:
def triangle(upside_down, right):
for row in range(10):
print(' ' * ..., '*' * ..., sep='')
What is the rule that tells us how many stars to print?
If the triangle is right-side-up, then we print row + 1 stars. Otherwise we need 10 - row stars. That matches the values that were passed to range in the original code.
def triangle(upside_down, right):
for row in range(10):
stars = 10 - row if upside_down else row + 1
print(' ' * ..., '*' * stars, sep='')
What is the rule that tells us how many spaces to print?
If the triangle is right-aligned, then we should print some spaces. How many? Well, for an upside-down triangle we used the row number directly. For a right-side-up triangle we need 9 - row stars. But we can simplify this, by thinking in terms of the remaining space after we account for the stars. We want a total of 10 stars plus spaces, so we can simply subtract 10 - stars to get the space count.
If the triangle is left-aligned, of course, then we print zero spaces.
def triangle(upside_down, right):
for row in range(10):
stars = 10 - row if upside_down else row + 1
spaces = 10 - stars if right else 0
print(' ' * spaces, '*' * stars, sep='')
Simple. Let's use it:
triangle(False, False)
print()
triangle(True, False)
print()
triangle(True, True)
print()
triangle(False, True)
By extracting the code first, it becomes much clearer how to iterate that code: we just need to change the arguments for the triangle calls, and take care of the intermediate prints. We have a clearly defined function that does one thing and has a reasonable name - in accordance with all the principles that a good programming book tries to teach you.
How do we repeatedly call a function with differing, constant (i.e. pre-calculated) arguments? Simple: we put those arguments in some data structure, and iterate over that. To print after each triangle except the last, our trick is to instead print before each triangle except the first, using some simple flag logic (a variable that tells us what to display - either a newline, or nothing - which changes unconditionally after displaying it).
So, for example:
# This tells us which values we will use to call `triangle` each time.
configurations = ((False, False), (True, False), (True, True), (False, True))
# This tells us what we will display before each `triangle`.
before_triangle = ''
for upside_down, right in configurations:
print(before_triangle, end='')
before_triangle = '\n'
triangle(upside_down, right)
Going over the n×n grid and letting a pattern expression decide whether to print an *:
n = 10
h = n / 2
patterns = [
lambda: i >= j,
lambda: i+j < n,
lambda: j >= i,
lambda: i+j >= n-1,
]
for p in patterns:
for i in range(n):
for j in range(n):
print(' *'[p()], end='')
print()
print()
Output (Try it online!):
*
**
***
****
*****
******
*******
********
*********
**********
**********
*********
********
*******
******
*****
****
***
**
*
**********
*********
********
*******
******
*****
****
***
**
*
*
**
***
****
*****
******
*******
********
*********
**********
Bonus patterns:
lambda: max(i,j) >= h,
lambda: abs(i-h)+abs(j-h) < h,
lambda: (i//2 | j//2) % 2,
Output:
*****
*****
*****
*****
*****
**********
**********
**********
**********
**********
*
***
*****
*******
*********
*******
*****
***
*
** **
** **
**********
**********
** **
** **
**********
**********
** **
** **
Here is one way to factor common logic out of your four for loops, and also to use string multiplication to eliminate the inner loops:
patterns = [
[(1,1), None],
[(-1,10), None],
[(-1,10), (1, 0)],
[(1,1), (-1,9)]
]
begun = False
for (sign, plus), leftPat in patterns:
print('', end = '\n' * begun)
begun = True
leftSign, leftPlus = leftPat if leftPat else (0,0)
for row in range(10):
print(' ' * (row * leftSign + leftPlus), '*' * (row * sign + plus), sep='')
Explanation:
We populate patterns with a list of pairs of tuples (also pairs) that are asterisk params (required) and space params (optional, in other words: can be None)
We iterate over the patterns
For each pattern, we use default values of (0,0) if the space params (leftPat) are None
We then use string multiplication to print the indicated number of spaces followed by the indicated number of asterisks for each row in the pattern
There is additional logic using begun to print blank lines between each pattern
If an extra blank line at the end were acceptable, this could be simplified further to:
for (sign, plus), leftPat in patterns:
leftSign, leftPlus = leftPat if leftPat else (0,0)
for row in range(10):
print(' ' * (row * leftSign + leftPlus), '*' * (row * sign + plus), sep='')
print()

How to Print Pattern Shown?

How do I print pattern in python as shown below:
My code:
for outer_loop in reversed(range(1, 5+1)):
for inner_loop in range(0,outer_loop):
# print(inner_loop*' ')
print('*',end='')
print()
Output:
*****
****
***
**
*
I want to give spaces on left side as shown below,
Expected Output:
*****
****
***
**
*
There is a method rjust on strings:
for n in range(5, 0, -1):
print( (n*"*").rjust(5) )
You don't need reversed(), range() can return a reversed range by using a negative step.
You can multiply a string to duplicate it, instead of using a loop.
Add the spaces by printing 5 - n spaces before n asterisks.
for n in range(5, 0, -1):
print(" " * (5-n) + "*" * n)

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:
*
***
*****
*
***
*****
*
***
*****
*******
*
***
*****
*******
*
***
*****
*******
*********
*
***
*****
*******
*********

Asterisk art in python

I would like to produce this picture in python!
*
**
***
****
*****
******
*******
********
*********
**********
I entered this:
x=1
while x<10:
print '%10s' %'*'*x
x=x+1
Which sadly seems to produce something composed of the right number of dots as the picture above, but each of those dot asterisks are separated by spaced apart from one another, rather than justified right as a whole.
Anybody have a clever mind on how I might achieve what I want?
'%10s' %'*'*x
is being parsed as
('%10s' % '*') * x
because the % and * operators have the same precedence and group left-to-right[docs]. You need to add parentheses, like this:
x = 1
while x < 10:
print '%10s' % ('*' * x)
x = x + 1
If you want to loop through a range of numbers, it's considered more idiomatic to use a for loop than a while loop. Like this:
for x in range(1, 10):
print '%10s' % ('*' * x)
for x in range(0, 10) is equivalent to for(int x = 0; x < 10; x++) in Java or C.
string object has rjust and ljust methods for precisely this thing.
>>> n = 10
>>> for i in xrange(1,n+1):
... print (i*'*').rjust(n)
...
*
**
***
****
*****
******
*******
********
*********
**********
or, alternatively:
>>> for i in reversed(xrange(n)):
... print (i*' ').ljust(n, '*')
...
*
**
***
****
*****
******
*******
********
*********
**********
My second example uses a space character as the printable character, and * as the fill character.
The argument to ljust or rjust is the terminal width. I often use these for separating sections with headings when you have chatty debug printout, e.g. print '--Spam!'.ljust(80, '-').
It's because of the operator precedence, use this one:
x=1
while x<10:
print '%10s' % ('*'*x)
x=x+1
print '\n'.join(' ' * (10 - i) + '*' * i for i in range(10))
To be exact, as your picture ends with 10 asterisks, you need.
for i in range(1, 11):
print "%10s"%('*' *i)

Categories

Resources