How to print two columns with different range using for loops? - python

I need some very basic help with Python. I'm trying to get a better understanding of formatting using a for loop and I want to print out vertical Histogram.
Here is what I've tried:
tot_progress = 2
tot_trailer = 4
tot_retriever = 3
tot_exclude = 4
# Vertical Histogram
print("Progress", " Trailing", " Retriever", " Excluded")
a = '*'
for i,j,k,l in zip(range(0, tot_progress, 1), range(0, tot_trailer, 1), range(0, tot_retriever, 1), range(0, tot_exclude, 1)):
print('{}\t\t\t{}\t\t\t{}\t\t\t{}'.format(a, a, a, a))
The output I got:
Progress Trailing Retriever Excluded
* * * *
* * * *
what I want:
Progress Trailing Retriever Excluded
* * * *
* * * *
* * *
* *

User itertools longest to iterate to maximum and update your loop with conditions and print accordingly
import itertools
for i,j,k,l in itertools.zip_longest(range(0, tot_progress, 1), range(0, tot_trailer, 1), range(0, tot_retriever, 1), range(0, tot_exclude, 1)):
ai="*" if not i == None else " "
aj="*" if not j == None else " "
ak="*" if not k == None else " "
al="*" if not l == None else " "
print('{}\t\t\t{}\t\t\t{}\t\t\t{}'.format(ai, aj, ak, al))

In order to have vertical histograms you can format each row to have the same "length" and then zip, so that you can transpose it properly. Used string formatting layout, see here for details.
Each bar of the histogram will be centered wrt to the label of the column.
col_labels = {'Progress statussss': 2, "Trailing": 8, "Retriever": 3, "Excluded": 4}
SYMBOL = '*'
PADDING = 2 # add extra space between two columns
col_sizes = list(map(len, col_labels))
row_template = [(('{S:^' + f'{size + PADDING}' + '}' + ' ') *v)[:-1].split() + [' ' * (size+PADDING) ]*(size - v) for size, v in zip(col_sizes, col_labels.values())]
# column names
print(''.join(('{:^' + f'{col_sizes[i] + PADDING}' + '}').format(v) for i, v in enumerate(col_labels)))
# bars
for l in (''.join(i) for i in zip(*row_template)):
print(l.format(S=SYMBOL))
Output
Progress statussss Trailing Retriever Excluded
* * * *
* * * *
* * *
* *
*
*
*
*

Related

How to draw right side up triangle recursively with ONE argument

Write a recursive function called draw_triangle() that outputs lines of *'s 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,
Then the function draw_triangle outputs:
*
***
If the input of the program is 19,
Then the function outputs
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
No space is output before the first asterisk on the last line when the base length is 19.
I was able to code this non-recursively as follows:
def draw_triangle(n):
lines_to_print = int(((n // 2) + 1))
spaces_to_print = 9
asts_to_print = 1
for i in range(lines_to_print):
print(spaces_to_print * ' ', end='')
print(asts_to_print * '*', end='')
print()
spaces_to_print -= 1
asts_to_print += 2
base_length = int(input())
draw_triangle(base_length)
But I cannot, for my life, figure out how to do it recursively, let alone with only one argument. What am I missing about recursion?
The simple trick here is to use the str.center() method.
def draw_triangle(n):
if n == 1:
print('*'.center(19))
else:
draw_triangle(n-2)
print((n*'*').center(19))
Test it:
draw_triangle(19)
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
One method is is to define functions to print the symbole you want to use and the spaces between them:
def print_ecart(ecart):
if (ecart == 0):
return;
print(" ", end = "")
print_ecart(ecart - 1)
def print_etoile(etoile):
if(etoile == 0):
return
print("* ", end = "")
print_etoile(etoile - 1)
def pattern(n, num):
if (n == 0):
return
print_ecart(n - 1)
print_etoile(num - n + 1)
print("");
pattern(n - 1, num)
In this case print_ecrat prints spaces and print_etoile prints the stars:
pattern(10,10)
returns:
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
By printing after the recursion itself happens, you can print smaller lines over the bigger lines:
def draw_triangle(n):
spaces = 9 - n // 2 # Ensures correct spacing for each line
if n == 1:
print(spaces * ' ' + '*')
else:
draw_triangle(n-2)
print(spaces * ' ' + n * '*')
draw_triangle(19)
Well, it is a quite interesting question.
The main obstacle is that you have to preserve initial base length of triangle.
You can't save it via assigning input value to another parameter inside a recursive function because:
only one argument is allowed
assigning will work every function call.
Not sure if the following code is convenient with the conditions of the task but it may be useful to illustrate an idea of recursive functions for you:
base_length = 20
def draw_triangle(base=base_length):
if base % 2 == 0:
base = base - 1
draw_triangle(base)
else:
if base > 0:
# print(base)
# print(int(base/2 - 1))
print(' '*int((base - 2)/2+1) + '*'*(base_length - base) + ' '*int((base - 2)/2))
base = base - 2
draw_triangle(base)
elif base == 0:
return 0
draw_triangle(base=base_length)
Formally there is only one argument in this recursive function, but you have to define base_length paramater outside of the function and the function uses base_length inside.

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)

How to print in the same line print_big('j'), print_big('o'),print_big('j'),print_big('o') in python?

How do I print in the same line print_big('j'), print_big('o'), print_big('j'), print_big('o') to have JOJO.
print(patterns[pattern], end= '')
def print_big(letter):
patterns={0:' *',1:' * ',2:' * *',3:'* *',4:'******',5:'****',6:'* ***',7:' * ',
8:'* *',9:'* ',10:'** *',11:'* * *',12:'* * *',13:'* **',14:'***',
15:'* *',16:'* * * *',17:'* * *',18:'*******',19:' * * ',20:' ****',
21:' *',22:' *****',23:'**** ',24:' ** ',25:' *',26:' *** '}
alphabet={'A':[24,2,4,3,3],'B':[5,3,5,3,5],'C':[20,9,9,9,20],'D':[5,3,3,3,5],'E':[4,9,4,9,4], 'F':[4,9,5,9,9],
'G':[20,9,6,3,20],'H':[3,3,4,3,3],'I':[14,7,7,7,14],'J':[5,1,1,1,0],'K':[3,8,7,8,3],'L':[9,9,9,9,4],
'M':[15,16,17,15],'N':[10,11,12,13],'O':[20,3,3,20],'P':[5,3,5,9,9],'Q':[20,3,12,22,21],'R':[5,3,5,3,3],
'S':[20,9,24,25,23],'T':[18,1,1,1,1,],'U':[3,3,3,4],'V':[15,15,15,19,1],'W':[15,17,16,15],
'X':[15,19,1,19,15],'Y':[15,19,1,1,1],'Z':[4,25,26,7,4,]}
for pattern in alphabet[letter.upper()]:
print(patterns[pattern])
Expected result JOJO actual result
J
O
J
O
Your attempt is broken because you construct every single letter by 4-5 lines. If you wanted to write letters in one line, you would have to print the 1st line of every character, then line break, then the 2nd line, etc.
You are unable to do this atm because your letters are not equally spaced. U and O are only 4 lines high, all others 5. The individual lines vary between 3 (0:' *') and 7 (18:'*******') width. If you mix and match letters this will warp your text.
You need to create a better mapping, ideally with euqally width characters. Then you need to get the 1st line of each characters in your word, print it using end = '', sep = " " then add a line break, then print the second line.
def print_big(word):
# fixes for overall pattern width - all exactly 7 letters wide
# 1234567 1234567 1234567 1234567 1234567 1234567
patterns={0:' * ', 1:' * ', 2:' * * ', 3:'* * ', 4:'****** ', 5:'**** ',
6:'* *** ', 7:' * ', 8:'* * ', 9:'* ',10:'** * ',11:'* * * ',
12:'* * *',13:'* ** ',14:'*** ',15:'* *',16:'* * * *',17:'* * *',
18:'******',19:' * * ',20:' **** ',21:' *',22:' ***** ',23:'**** ',
24:' ** ',25:' * ',26:' *** '}
# fixes for O and U wich had only 4 lines, not 5
alp = {'A':[24,2,4,3,3], 'B':[5,3,5,3,5], 'C':[20,9,9,9,20], 'D':[5,3,3,3,5],
'E':[4,9,4,9,4], 'F':[4,9,5,9,9], 'G':[20,9,6,3,20], 'H':[3,3,4,3,3],
'I':[14,7,7,7,14], 'J':[5,1,1,1,0], 'K':[3,8,7,8,3], 'L':[9,9,9,9,4],
'M':[15,16,17,15], 'N':[10,11,12,13],'O':[20,3,3,3,20], 'P':[5,3,5,9,9],
'Q':[20,3,12,22,21],'R':[5,3,5,3,3], 'S':[20,9,24,25,23],'T':[18,1,1,1,1,],
'U':[3,3,3,3,4], 'V':[15,15,15,19,1], 'W':[15,17,16,15],
'X':[15,19,1,19,15],'Y':[15,19,1,1,1],'Z':[4,25,26,7,4,]}
# generate the needed indexes for all letters line-wise
lines = zip(*[alp[c] for c in word.upper()])
print(list(lines))
for what in lines:
for w in what:
print(patterns[w], end="")
print()
print_big("JOJO")
Output:
# zipped lines, indexes of each tuple are one line for all letters)
[(5, 20, 5, 20), (1, 3, 1, 3), (1, 3, 1, 3), (1, 3, 1, 3), (0, 20, 0, 20)]
**** **** **** ****
* * * * * *
* * * * * *
* * * * * *
* **** * ****
See zip for what it does exactly.
You need to check the other letters if they print nicely and adjust patterns if not.

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]

generate polynomial in python

I am trying to make a function which can print a polynomial of order n of x,y
i.e. poly(x,y,1) will output c[0] + c[1]*x + c[2]*y
i.e. poly(x,y,2) will output c[0] + c[1]*x + c[2]*y + c[3]*x**2 + c[4]*y**2 + c[5]*x*y
Could you give me some ideas? Maybe itertools?
You could try to start from something like
def poly(x,y,n):
counter = 0
for nc in range(n+1):
for i in range(nc+1):
print "c[", counter, "]",
print " * ", x, "**", i,
print " * ", y, "**", nc-i,
print " + ",
counter += 1
For example
poly("x", "y", 2)
will produce
c[ 0 ] * x ** 0 * y ** 0 + c[ 1 ] * x ** 0 * y ** 1 + c[ 2 ] * x ** 1 * y ** 0 + c[ 3 ] * x ** 0 * y ** 2 + c[ 4 ] * x ** 1 * y ** 1 + c[ 5 ] * x ** 2 * y ** 0 +
Build in ifs, if you want to suppress undesired output.
Since you wanted a functional solution with itertools, here's a one-liner:
import itertools as itt
from collections import Counter
n = 3
xy = ("x", "y") # list of variables may be extended indefinitely
poly = '+'.join(itt.starmap(lambda u, t: u+"*"+t if t else u, zip(map(lambda v: "C["+str(v)+"]", itt.count()),map(lambda z: "*".join(z), map(lambda x: tuple(map(lambda y: "**".join(map(str, filter(lambda w: w!=1, y))), x)), map(dict.items, (map(Counter, itt.chain.from_iterable(itt.combinations_with_replacement(xy, i) for i in range(n+1))))))))))
That would give you
C[0]+C[1]*x+C[2]*y+C[3]*x**2+C[4]*y*x+C[5]*y**2+C[6]*x**3+C[7]*y*x**2+C[8]*y**2*x+C[9]*y**3
Note, the order of coefficients is slightly different. This will work not only for any n, but also for any number of variables (x, y, z, etc...)
Just for laughs
Slightly more generalized:
from itertools import product
def make_clause(c, vars, pows):
c = ['c[{}]'.format(c)]
vp = (['', '{}', '({}**{})'][min(p,2)].format(v,p) for v,p in zip(vars,pows))
return '*'.join(c + [s for s in vp if s])
def poly(vars, max_power):
res = (make_clause(c, vars, pows) for c,pows in enumerate(product(*(range(max_power+1) for v in vars))))
return ' + '.join(res)
then poly(['x', 'y'], 2) returns
"c[0] + c[1]*y + c[2]*(y**2) + c[3]*x + c[4]*x*y + c[5]*x*(y**2) + c[6]*(x**2) + c[7]*(x**2)*y + c[8]*(x**2)*(y**2)"

Categories

Resources