Print "n" results of a function "n" times - python-3.x

I want to print out a sort of pyramid. User inputs an integer value 'i', and that is displayed i-times.
Like if input=5
1
22
333
4444
55555
I have tried this:
input=5
for i in range(input+1):
print("i"*i)
i=i+1
The result of which is
i
ii
iii
iiii
iiiii
The problem is that (as far as I know), only a string can be printed out 'n' times, but if I take out the inverted commas around "i", it becomes (i*i) and gives out squares:
0
1
4
9
16
25
Is there a simple way around this?
Thanks!

Just convert your int loop varaible to str before building the output string by multiplying:
input = 5
for i in range(1, input+1):
print(str(i) * i)

Try this:
a = 5
for i in range(a): # <-- this causes i to go from 0,1,2,3,...,a-1
print("{}".format(i+1)*(i+1)) # < -- this creates a new string in each iteration ; an alternative would be str(i+1)*(i+1)
i=i+1 # <-- this is unnecessary, i already goes from 0 to a-1 and will be re-created in the next iteration of the loop.
This creates a new string in each iteration of the loop.
Note that for i in range(a) will go through the range by itself. There is no need to additionally increment i at the end. In general it is considered bad practise to change indices you loop over.

Related

Horizotal print of a complex string block

Once again I'm asking for you advice. I'm trying to print a complex string block, it should look like this:
32 1 9999 523
+ 8 - 3801 + 9999 - 49
---- ------ ------ -----
40 -3800 19998 474
I wrote the function arrange_printer() for the characters arrangement in the correct format that could be reutilized for printing the list. This is how my code looks by now:
import operator
import sys
def arithmetic_arranger(problems, boolean: bool):
arranged_problems = []
if len(problems) <= 5:
for num in range(len(problems)):
arranged_problems += arrange_printer(problems[num], boolean)
else:
sys.exit("Error: Too many problems")
return print(*arranged_problems, end=' ')
def arrange_printer(oper: str, boolean: bool):
oper = oper.split()
ops = {"+": operator.add, "-": operator.sub}
a = int(oper[0])
b = int(oper[2])
if len(oper[0]) > len(oper[2]):
size = len(oper[0])
elif len(oper[0]) < len(oper[2]):
size = len(oper[2])
else:
size = len(oper[0])
line = '------'
ope = ' %*i\n%s %*i\n%s' % (size,a,oper[1],size,b,'------'[0:size+2])
try:
res = ops[oper[1]](a,b)
except:
sys.exit("Error: Operator must be '+' or '-'.")
if boolean == True:
ope = '%s\n%*i' % (ope,size+2, res)
return ope
arithmetic_arranger(['20 + 300', '1563 - 465 '], True)
#arrange_printer(' 20 + 334 ', True)
Sadly, I'm getting this format:
2 0
+ 3 0 0
- - - - -
3 2 0 1 5 6 3
- 4 6 5
- - - - - -
1 0 9 8
If you try printing the return of arrange_printer() as in the last commented line the format is the desired.
Any suggestion for improving my code or adopt good coding practices are well received, I'm starting to get a feel for programming in Python.
Thank you by your help!
The first problem I see is that you use += to add an item to the arranged_problems list. Strings are iterable. somelist += someiterable iterates over the someiterable, and appends each element to somelist. To append, use somelist.append()
Now once you fix this, it still won't work like you expect it to, because print() works by printing what you give it at the location of the cursor. Once you're on a new line, you can't go back to a previous line, because your cursor is already on the new line. Anything you print after that will go to the new line at the location of the cursor, so you need to arrange multiple problems such that their first lines all print first, then their second lines, and so on. Just fixing append(), you'd get this output:
20
+ 300
-----
320 1563
- 465
------
1098
You get a string with \n denoting the start of the new line from each call to arrange_printer(). You can split this output into lines, and then process each row separately.
For example:
def arithmetic_arranger(problems, boolean:bool):
arranged_problems = []
if len(problems) > 5:
print("Too many problems")
return
for problem in problems:
# Arrange and split into individual lines
lines = arrange_printer(problem, boolean).split('\n')
# Append the list of lines to our main list
arranged_problems.append(lines)
# Now, arranged_problems contains one list for each problem.
# Each list contains individual lines we want to print
# Use zip() to iterate over all the lists inside arranged_problems simultaneously
for problems_lines in zip(*arranged_problems):
# problems_lines is e.g.
# (' 20', ' 1563')
# ('+ 300', '- 465') etc
# Unpack this tuple and print it, separated by spaces.
print(*problems_lines, sep=" ")
Which gives the output:
20 1563
+ 300 - 465
----- ------
320 1098
If you expect each problem to have a different number of lines, then you can use the itertools.zip_longest() function instead of zip()
To collect all my other comments in one place:
return print(...) is pretty useless. print() doesn't return anything. return print(...) will always cause your function to return None.
Instead of iterating over range(len(problems)) and accessing problems[num], just do for problem in problems and then use problem instead of problems[num]
Debugging is an important skill, and the sooner into your programming career you learn it, the better off you will be.
Stepping through your program with a debugger allows you to see how each statement affects your program and is an invaluable debugging tool

Difference resulting from position of print in loops

First question here.
I am picking up Python and have a question that may be quite basic.
I am trying to create this pattern with a nested loop:
x
x
x
xxx
With the code:
numbers = [1,1,1,3]
for count_x in numbers:
output = ""
for count in range(count_x):
output +=x
print(output)
My question is - why does my output change when I move the position of print(output).
The code above works but when I align print(output) with the for count_x in numbers:, I only get "xxx", when I align print(output) to output +=x, I get the following:
x
x
x
x
xx
xxx
which is very odd because there are only 4 items in the list and it shows me 6 lines of output.
Could someone please help? Really puzzled. Thank yall very much.
There's a difference between these two bits of code (fixing the x/"x" problem along the way - your code won't actually work as is unless you have a variable x):
# First:
numbers = [1,1,1,3]
for count_x in numbers:
output = ""
for count in range(count_x):
output += "x"
print(output)
# Second:
numbers = [1,1,1,3]
for count_x in numbers:
output = ""
for count in range(count_x):
output += "x"
print(output)
In the second, the print is done inside the loop that creates the string, meaning you print it out multiple times while building it. That's where your final three lines come from: *, ** and ***. This doesn't matter for all the previous lines since there's no functional difference. Printing a one character string at the end or after adding each of the one characters has the same effect.
In the first, you only print the string after fully constructing it.
You can see this effect by using a slightly modified version that outputs different things for each outer loop:
numbers = [1,1,1,3]
x = 1
for count_x in numbers:
output = ""
for count in range(count_x):
output += str(x)
print(output)
x += 1
This shows that the final three lines are part of a single string construction (comments added):
1 \
2 >- | Each is one outer/inner loop.
3 /
4 \ | A single outer loop, printing
44 >- | string under construction for
444 / | each inner loop.
In any case, there are better ways to do what you want, such as:
numbers = [1,1,1,3]
for count_x in numbers:
print('x' * count_x)
You could probably also do it on one line with a list comprehension but that's probably overkill.

for loop with changed iterator

I can't make the iterator shorter while I'm running on it.
I want to write a function which gets a string and deletes repeating sequences in it.
for example:
if a have the string aaaaabbbbbbbcccccccDDDDDDaaaaa
I should get in return abcDa.
I tried to run over the string with a for loop and every time I see a new letter I will save the letter in a variable which adds up to be the fixed string.
def string_sequence_fixing(string):
c = ''
for char in my_str:
if c != char:
c = char
else:
my_str = my_str.replace(c, '', my_str.count(c) - 1)
return my_str
The problem I want to avoid is too many iterations.
When I see a new character I want to delete all the other sequences of it,
but the second line from the end does not update the "condition" in the for a loop.
Short Answer: loops don't work that way.
Longer answer:
Here is some simple pseudo code, for your perusal:
j=99
print "J is " j
for j=0;20;5
print j \t
end
print "Now J is " j
The output may surprise you.
run
J is 99
0 5 10 15 20
Now J is 99
The reason is: the variable j in the loop is NOT the as the j variable outside the loop.
I like to use the term "stack" (some languages claim they don't use a stack. In those cases I call it a "not-stack stack). The stack simple means a temporary storage space in memory.
The initial variable "j" goes into the "program data space". The loop variable "j" goes into the "stack data space."
Using a variable doesn't 'really' mean you are using a variable, it's just a mnemonic to a memory space. Let's have another look at that sample code:
pointer-to-program-space-variable-named-j = 99 (poke into memory location 1:4500)
pointer-to-stack-space-variable-named-j = 0 (poke into memory location 87:300)
print pointer-to-stack-space-variable-named-j followed by tab
increment pointer-to-stack-space-variable-named-j by 5
repeat until pointer-to-stack-space-variable-named-j = 20
print pointer-to-program-space-variable-named-j
With this knowledge, let's look at your code to see what is going on:
def string_sequence_fixing(string):
c = ''
for char in *STACK*.my_str:
if c != char:
c = char
else:
my_str = my_str.replace(c, '', *PROGRAM*.my_str.count(c) - 1)
return my_str
See how they are different variables? NEVER assume that a loop variable and a program variable are the same. You need to redo you algorithm to accomplish what you want to do.
Also, see the link provided by #David Cullen.
You can use groupby() from itertools. Code is like:
data = 'aaabbbcccDDDDDEfggghiij'
from itertools import groupby
dataN = ''
for d in groupby(data):
dataN += d[0]
print(dataN)
output:
abcDEfghij

IndexError: string index out of range ... why in this small piece of code?

s='saamaarrr'
for i in range(0, len(s)-1):
while(s[i]==s[i+1]):
i+=1
print(s[i])
IndexError: string index out of range
I am new to python. I know the reasons for this error. But i don't know why it is occurring here. i've read other answers to this question also
Range objects include the left bound and exclude the right bound
If the string is 9 characters long, as it is in your case, the range sequence would be:
0 1 2 3 4 5 6 7 8
Let's take a look at what happens when the variable i in the for loop reaches 8.
In your while loop, you're checking if s[8] is equal to s[9]. Since indexing in Python starts from 0, as in many other programming languages, the last letter of your string s would have an index 8, which means that index 9 is out of range of the string. This causes an error.
To fix it, make your for loop like this:
for i in range(0, len(s)-2):
This way the range sequence will be 0 1 2 3 4 5 6 7, so it won't cause an error.
Also, you don't have to specify the left bound as 0, it is a default value, so this also works:
for i in range(len(s)-2):
while(s[i] == s[i+1])
That's causing problems because when i = len(s)-1, s[i+1] will be out of range!
You don't need nest a while loop inside of your for loop. Adjust the range statement in your FOR and try an if statement instead...
for i in range(0, len(s)-2):
If s[i]==s[i+1]:
print(s[i])
The problem is that you want to access the value of s[i+1] before testing the actual value of i+1. I also suggest that you don't use the same variable (i) in both your for and while loops.
Here is the result :
s='saamaarrr'
for i in range(0, len(s)-1):
j = i + 1
while (j < len(s)) and (s[i]==s[j]):
print(s[j])
j+=1
And here is the output :
a
a
r
r
r
Don't know what you want to achieve, though...
Hope it'll be helpful !

Recognize relevant string information by checking the first characters

I have a table with 2 columns. In column 1, I have a string information, in column 2, I have a logical index
%% Tables and their use
T={'A2P3';'A2P3';'A2P3';'A2P3 with (extra1)';'A2P3 with (extra1) and (extra 2)';'A2P3 with (extra1)';'B2P3';'B2P3';'B2P3';'B2P3 with (extra 1)';'A2P3'};
a={1 1 0 1 1 0 1 1 0 1 1 }
T(:,2)=num2cell(1);
T(3,2)=num2cell(0);
T(6,2)=num2cell(0);
T(9,2)=num2cell(0);
T=table(T(:,1),T(:,2));
class(T.Var1);
class(T.Var2);
T.Var1=categorical(T.Var1)
T.Var2=cell2mat(T.Var2)
class(T.Var1);
class(T.Var2);
if T.Var1=='A2P3' & T.Var2==1
disp 'go on'
else
disp 'change something'
end
UPDATES:
I will update this section as soon as I know how to copy my workspace into a code format
** still don't know how to do that but here it goes
*** why working with tables is a double edged sword (but still cool): I have to be very aware of the class inside the table to refer to it in an if else construct, here I had to convert two columns to categorical and to double from cell to make it work...
Here is what my data looks like:
I want to have this:
if T.Var1=='A2P3*************************' & T.Var2==1
disp 'go on'
else
disp 'change something'
end
I manage to tell matlab to do as i wish, but the whole point of this post is: how do i tell matlab to ignore what comes after A2P3 in the string, where the string length is variable? because otherwise it would be very tiring to look up every single piece of string information left on A2P3 (and on B2P3 etc) just to say thay.
How do I do that?
Assuming you are working with T (cell array) as listed in your code, you may use this code to detect the successful matches -
%%// Slightly different than yours
T={'A2P3';'NotA2P3';'A2P3';'A2P3 with (extra1)';'A2P3 with (extra1) and (extra 2)';'A2P3 with (extra1)';'B2P3';'B2P3';'NotA2P3';'B2P3 with (extra 1)';'A2P3'};
a={1 1 0 1 1 0 1 1 0 1 1 }
T(:,2)=num2cell(1);
T(3,2)=num2cell(0);
T(6,2)=num2cell(0);
T(9,2)=num2cell(0);
%%// Get the comparison results
col1_comps = ismember(char(T(:,1)),'A2P3') | ismember(char(T(:,1)),'B2P3');
comparisons = ismember(col1_comps(:,1:4),[1 1 1 1],'rows').*cell2mat(T(:,2))
One quick solution would be to make a function that takes 2 strings and checks whether the first one starts with the second one.
Later Edit:
The function will look like this:
for i = 0, i < second string's length, i = i + 1
if the first string's character at index i doesn't equal the second string's character at index i
return false
after the for, return true
This assuming the second character's lenght is always smaller the first's. Otherwise, return the function with the arguments swapped.

Resources