python: Nesting - python

I am trying to write code that will display a shape with an odd width. Once the shape is completed it is placed inside an outer shape. The user will be able to input the characters used for the shape and the number of rows.
I am hoping to produce a shape and, with a for loop, produce an outer shape.
***** .
*** ...
* .....
.*****.
...***...
.....*.....
this is my current code. I only know how to create a shape.
char = (input("Enter first charactrer"))
rows = int(input("enter the number of rows"))
for m in range(rows, 0, -1):
for n in range(0, rows-m):
print(end=" ")
for n in range(0,m):
print(char,end=" ")
print()

There is no need for some of the for-loops:
A useful feature in python is the way you can multiply a char by an int to get a string of that repeated char.
For example, if you do:
'c' * 10
you get:
'cccccccccc'
The reason this will be useful in your case is that you can use it to print the spaces and chars. This will be neater than for-loops as instead of printing a single chars over and over with no line breaks, you can instead print the full number of spaces as a string with one call.
To see what I mean, I wrote your original code using this:
char = input("enter the char ")
rows = int(input("enter the number of inner rows "))
for r in range(rows, 0, -1):
print(' ' * 2 * (rows-r), end='')
print((char+' ') * (2*r+1))
see how much neater it is? Also, you can notice that in the second print of each row for the chars, I used the calculation: 2*r +1. This is what you need to convert this pattern:
3. * * * *
2. * * *
1. * *
0. *
to this one (as you requested):
3. *******
2. *****
1. ***
0. *
you can see that for each row of the second one, the number of chars is 2 * the row +1. So row 3 has 7 chars, row 2 has 5 etc.
If you wanted to, as you have gotten rid of the unnecessary for-loops now, you could put both of the prints in one statement:
print(' ' * 2 * (rows-r) + (char+' ') * (2*r+1))
however, the first may be considered neater and clearer so you might want to stick with the separate statements.
Embedding the inner triangle in an outer one
First off for this, we will need to input two different chars for the inner and outer triangles. This will allow us to differentiate which is which.
I think that the best way to do this would be to keep the print statement which creates the spaces before the triangles as before, but modify how we draw the chars and their pattern.
This is what we want for an input of 4 rows:
0. .
1. ...
2. .....
3. .......
4. .*******.
5. ...*****...
6. .....***.....
7. .......*.......
notice how it would be simplest to split the printing process in half. So for the top half just print a regular triangle, but for the bottom print one regular, one flipped and another regular.
To do this, we want to loop through each of the 8 rows and check when we are half way through. If past halfway, we want the calculations for each smaller triangle to think they are at the top of the triangle, i.e. reset the row count for them so when printing row 4, we calculate as if printing on row 0. To achieve this, once past halfway, we need to modulo the row variable by half of the total rows (the total rows now being not what is entered, but double the entered amount as you can see we have a triangle with 8 rows but an inputted row value of 4). This will give the intended effect of the triangles being half size of the total triangle.
Finally, one last thing to consider is that the center/inner triangle needs to be flipped as we have done before. As our row count is now going from 0 at the top downwards rather than the other way around, we need to change the calculation for that row to be rows - r so it is flipped.
Taking all this into account, the final code may look something like:
innerChar = input("enter the inner char ")
outerChar = input("enter the outer char ")
rows = int(input("enter the number of inner rows "))
for r in range(2 * rows):
#print the white space on the left
print(' ' * 2 * (2 * rows-r), end='')
if r < rows:
#top triangle
print((outerChar+' ') * (2*r + 1))
else:
#working with the row modulo 2
r %= rows
#bottom three triangles
print((outerChar+' ') * (2*r + 1), end='')
print((innerChar+' ') * (2*(rows-r) - 1), end='')
print((outerChar+' ') * (2*r + 1))

One way to make this easier is to not worry about the spaces at first. Just generate the non-space symbols of each row, and save them into a list. Then at the end, determine the width of the biggest row, and use the str.center method to print each row with the correct amount of space.
def tri(n, chars='*.'):
ic, oc = chars
outer = range(1, 2*n, 2)
# top triangle chars
rows = []
for w in outer:
rows.append(w * oc)
# lower triangles chars
inner = reversed(outer)
for u, v in zip(outer, inner):
a, b = u * oc, v * ic
rows.append(a + b + a)
# Get maximum row size
width = len(rows[-1])
#Print all the rows
for row in rows:
print(row.center(width))
# test
tri(5)
output
.
...
.....
.......
.*******.
...*****...
.....***.....
.......*.......
The characters to use are passed to tri as a two character string, with a default of '*' for the inner char (ic) and '.' for the outer char (oc). But if you want to use other chars you can pass them, like this:
tri(4, '#o')

Related

Python program to give me numbers on the left with their sum on the right while having interchanged symbols in each line up to n (n=6)

Here's the picture of the program/ how it should work, it should display 1*1 then 12$3 < 3 is the sum of 1+2.. we only got to for loop.
I have tried a lot of solutions and this is what i got to at the end, for some reason i can't copy and paste it here without the code deleting whatever i had here..
also the output currently is:
please help and thanks a lot
I would implement this idea this way:
def func(n: int):
for i in range(1, n + 1):
nsum = 0 # Sum of numbers in nested loop.
last = 0 # Last number added to 'nsum'.
string = '' # Final string which is then printed.
for j in range(1, i + 1):
nsum += j # Add to total sum.
string += str(j) # Add to final string.
last = j # Set last number to current.
# Decide if either asterisk (*) or dollar ($) should be included
# in final message, after it append total sum.
string += ('*' if last % 2 else '$') + str(nsum)
print(string)
func(6)

Draw a centered triforce surrounded by hyphens using Python

I want to draw a triangle of asterisks from a given n which is an odd number and at least equal to 3. So far I did the following:
def main():
num = 5
for i in range(num):
if i == 0:
print('-' * num + '*' * (i + 1) + '-' * num)
elif i % 2 == 0:
print('-' * (num-i+1) + '*' * (i + 1) + '-' * (num-i+1))
else:
continue
if __name__ == "__main__":
main()
And got this as the result:
-----*-----
----***----
--*****--
But how do I edit the code so the number of hyphens corresponds to the desirable result:
-----*-----
----***----
---*****---
--*-----*--
-***---***-
*****-*****
There's probably a better way but this seems to work:
def triangle(n):
assert n % 2 != 0 # make sure n is an odd number
hyphens = n
output = []
for stars in range(1, n+1, 2):
h = '-'*hyphens
s = '*'*stars
output.append(h + s + h)
hyphens -= 1
pad = n // 2
mid = n
for stars in range(1, n+1, 2):
fix = '-'*pad
mh = '-'*mid
s = '*'*stars
output.append(fix + s + mh + s + fix)
pad -= 1
mid -= 2
print(*output, sep='\n')
triangle(5)
Output:
-----*-----
----***----
---*****---
--*-----*--
-***---***-
*****-*****
Think about what it is you're iterating over and what you're doing with your loop. Currently you're iterating up to the maximum number of hyphens you want, and you seem to be treating this as the number of asterisks to print, but if you look at the edge of your triforce, the number of hyphens is decreasing by 1 each line, from 5 to 0. To me, this would imply you need to print num-i hyphens each iteration, iterating over line number rather than the max number of hyphens/asterisks (these are close in value, but the distinction is important).
I'd recommend trying to make one large solid triangle first, i.e.
-----*-----
----***----
---*****---
--*******--
-*********-
***********
since this is a simpler problem to solve and is just one modification away from what you're trying to do (this is where the distinction between number of asterisks and line number will be important, as your pattern changes dependent on what line you're on).
I'll help get you started; for any odd n, the number of lines you need to print is going to be (n+1). If you modify your range to be over this value, you should be able to figure out how many hyphens and asterisks to print on each line to make a large triangle, and then you can just modify it to cut out the centre.

How can I create a matrix in which the user inputs both rows and columns and then enters the values for each position in Python?

This should be how the code works:
n = int(input()) #number of rows, for example 3
m = int(input()) #number of columns, for example 5
Then the user is going to enter a value for a row followed by a value for column.
x = int(input()) #This should be the row number, for example row 1
y = float(input()) #This should be the value for each position inside of each x.
Both x and y need to follow certain conditions so I have them apart. In theory it should look something like this:
matrix = [ [0.4], [0.3, 0.2, 0.5], [0.7] ] #Row 1 has 1 float, Row 2 has 3 float and Row 3 only 1
Some floats are going to enter on different rows, like row 1 can have three floats from the input, and another row (row 3) could have 5 floats from the input.
I have tried using the following loop:
for i in range(n): #I have tried multiple ways using len function, append function, etc.
for j in range(m):
But I can't seem to be able to assign each value on the matrix as I have to make sure that the inputs follow certain conditions as the program should read as many different floats as te variable "m" goes.
The reason why I am elaborating the code this way is because I have to calculate an average (in a different function) based on the different values that I get from the float input, making them go through a formula that I already had done before.
From what I understand, this should be roughly what you need:
row_input_count = int(input("please enter the number of rows you want to input: "))
column_count = int(input("please enter the number of columns: "))
matrix = []
for _ in range(row_input_count):
row_index = -1
while row_index < 0:
row_index = int(input(f"please select a row: "))
matrix = matrix + [[0] * column_count] * (row_index + 1 - len(matrix))
values = [0] * (column_count + 1)
while len(values) > column_count:
value_string = input(f"please input up to {column_count} values for row {row_index}: ")
values = [float(x) for x in value_string.split()]
values = values + [0] * (column_count - len(values))
matrix[row_index] = values
print("The resulting matrix: [")
for row in matrix:
print(row)
print("]")
Does this help you understand how the parts you already figured out could work together? I think it should be all relatively easy to read. Python's syntax for repeating elements in a list might be a bit strange to get used to:
>>> ["hi"] * 3
['hi', 'hi', 'hi']

Creating a Diagonal Line in Python/only using Nested Loops

Alright, so I've been staring at my screen for the past few hours trying to solve this problem. I have to create a diagonal line that which could have any character.
Needs to look like something like this:
*
*
*
This is my code that I have right now.
# Draw a Diagonal
row = 1
while row <= size:
# Output a single row
col = 1
while col <= row:
# Output the drawing character
print()
# The next column number
col = col + 1
# Output a newline to end the row
print(end=drawingChar)
# The next row number
row = row + 1
print()
and it doesn't come out close to anything like a diagonal line! Could use some insight, thank you for the help. I have to use nested loops. I saw a couple other questions like this on the search, but they don't work for my assignment.
you can do this with a simple for loop:
>>> for i in range(5):
print(' '*i, end = '*\n')
*
*
*
*
*

Slicing strings of a sentence with a scale

So I need to create 3 functions for this assignment.
The first should do the following
numCol(): When dealing with plain text (and data written in plain text), it can be helpful to have a “scale” that indicates the columns in which characters appear. We create a scale using two lines (or “rows”). In the second row, we print 1234567890 repeatedly. In the first row (i.e., the line above the second row), we write the “tens” digits above the zeros in the second row as shown in the listing below. This function takes one argument, an integer, and prints a scale the length of your quote. It doesn't return anything.
The second should
docQuote(): Takes three arguments: 1) the quote as a string, 2) the slice start value, and 3) the slice end value. It returns the doctored string.
The third should
main(): Takes no arguments and returns nothing. Prompts user for original quote and number
of slices needed. Then in a for-loop, calls numCol() in such a way that the scale is the length of the quote, prompts the user for the start and end slice values (recall that the end value isn’t included in the slice), and then calls docQuote(). Finally, it prints the final doctored quote.
If the program is correct its output should look as follows:
1. Enter quote: Money is the root of all evil.
2. Enter the number of slices needed: 2
3. 1 2
4. 012345678901234567890123456789
5. Money is the root of all evil.
6. Start and end for slicing separated by a comma: 8, 20
7. 1
8. 012345678901234567
9. Money is all evil.
10. Start and end for slicing separated by a comma: 12, 17
11. -> Money is all.
What I have so far: (Will update if I figure something out)
def numCol(x):
col=[]
for i in range(1,(round(n)//10)+1):
col.append(str(i))
print(" "," ".join(col),end="")
def docQuote(x,y,z):
return
def main():
x=input("Enter quote: ")
y=int(input("Enter the number of slices needed: "))
numCol(len(x)-1)
print(x)
main()
Ok: you have to define a function called numCol which takes one integer argument:
def numCol(n):
then you have to print a line consisting of n characters, where every tenth character is an incrementing integer and every other character is a space.
chars = []
for i in range(1, n+1):
if i % 10:
chars.append(" ")
else:
chars.append(str((i % 100) // 10))
print(''.join(chars))
and finally a row consisting of 'n' chars, being 1234567890 repeating:
chars = []
for i in range(1, n+1):
chars.append(str(i % 10))
print(''.join(chars))
which then runs as
>>> numCol(65)
1 2 3 4 5 6
12345678901234567890123456789012345678901234567890123456789012345
Edit:
In response to #AdamSmith:
Let's see some actual numbers:
from textwrap import dedent
from timeit import Timer
test_statements = [
(
"n = 65",
"""
# as a for-loop
chars = []
for i in xrange(1, n+1):
if i % 10:
chars.append(" ")
else:
chars.append(str((i % 100) // 10))
"""
),
(
"n = 65",
"""
# as a list comprehension
chars = [" " if i%10 else str((i%100)//10) for i in xrange(1,n+1)]
"""
),
(
"n = 65",
"""
# extra cost of list-to-string
chars = [" " if i%10 else str((i%100)//10) for i in xrange(1,n+1)]
s = ''.join(chars)
"""
),
(
"n = 65",
"""
# vs cost of generator-to-string
chars = (" " if i%10 else str((i%100)//10) for i in xrange(1,n+1))
s = ''.join(chars)
"""
),
(
"s = ' 1 2 3 4 5 6 '",
"""
# cost of actually displaying string
print(s)
"""
)
]
for setup,run in test_statements:
res = Timer(dedent(run), setup)
times = res.repeat() # 3 * 1000000 runs
print("{:7.1f}".format(min(times)) # time of one loop in microseconds
on my system (i5-760, Win7 x64, Python 2.7.5 64bit) this gives
15.1 # for-loop -> list of chars
10.7 # list comprehension -> list of chars
11.4 # list comprehension -> string
13.6 # generator expression -> string
132.1 # print the string
Conclusions:
a list comprehension is 29% faster than a for-loop at building a list of characters
a generator expression is 19.6% slower than a list comprehension at building a list of characters and joining to a string
it's pretty much irrelevant, because actually printing the output takes 9 times longer than generating it with any of these methods - by the time you print the string out, using a list comprehension (fastest) is just 2.9% faster than the for-loop (slowest).
#user3482104
If you really want to avoid if ... else, you can do
if stmt:
do_a()
if not stmt: # same effect as 'else:'
do_b()
but be aware that this has to evaluate stmt twice where else only evaluates it once.
Also, because both loops are iterating over the same range (same start/end values), you can combine the loops:
def numCol(n):
firstline = []
secondline = []
for i in range(1, n+1):
i %= 100
tens, ones = i // 10, i % 10
if ones: # ones != 0
firstline.append(" ")
if not ones: # ones == 0 # <= 'else:'
firstline.append(str(tens))
secondline.append(str(ones))
print(''.join(firstline))
print(''.join(secondline))

Categories

Resources