Sorry that I ask this here, because this seems really elementary and is most likely asked before. However, I have been searching and trying for hours and I couldn't find anything that helped me out. I want to write a program that asks for an upper bound and returns a table with pairs of numbers (m,n) such that the sum of of divisors of n (excluding n) equals m, and vice versa.
Now I wrote the following
bound = int(input('upper bound = '))
l = len(str(bound))
for x in range(1,l):
print(' ', end='')
print('m', end=' ')
for y in range(1,l):
print(' ', end='')
print('n', end='')
for i in range(1,bound):
for j in range (1, bound):
if j == i:
break
som_i = 0
som_j = 0
for k in range(1,i):
if i % k == 0:
som_i += k
for l in range(1,j):
if j % l == 0:
som_j += l
if som_i == j and som_j == i:
print('{:{prec}d}'.format(j, prec = l).rstrip(''), end="")
print('{:{prec}d}'.format(i, prec = l+2).lstrip(''), end="")
The problem is that I want the pair to be displayed in tabular form side to side and with the right indentation, depending on the length of the number. Whatever I tried (I read so many treads with similar questions already) Python keeps adding a whitespace.
Can anyone help me out on this? I am really new to Python and I cannot figure this out myself. If relevant, I am using version 3.6.
EDIT:
For example, when I run the program I get:
upper bound = 300
m n
220
284
while I would like to get
upper bound = 300
m n
220 284
And similar for larger inputs.
EDIT2 My question is not a duplicate, since i already tried adding
end=""
which did not work.
The first problem is that you're not using end='' after printing the j value, but you apparently already know about that. You also are using it after printing the n header, which you don't want.
Your edited version fixes the missing end='' after the j print, but then adds one after the i print, which, again, you don't want.
I'm not sure you understand what end='' means, so you're just putting it into your code randomly. That isn't going to get you very far. You can read the docs for print, but the short version is: use end='' when you're printing something that isn't supposed to be the end of a line, like that m header and j value, but don't use it when you're printing something that is supposed to be the end of a line, like that n header and i value.
The second problem is that l is just way too big. After for l in range(1,j):, it's going to be the same value as j, which means it's going to be 219, so you're going to print that 220 filled out to 219 characters, and that 284 filled out to 221 characters. So, unless your terminal is more than 446 characters wide, it's going to scroll across multiple lines and look like a mess. I think what you may want here is to use 3 and 5.
Or, maybe, you have some other variable that's supposed to be 3, and you want to use (let's call that variable x) x and x+2 instead of l and l+2. But I don't see any obvious candidates in your code.
So:
# ... unchanged lines
print('n') # no end='' here
# ... more unchanged lines
# using 3 and 5 instead of l and l+2, and adding end=''
print(('{:{prec}d}'.format(j, prec = 3)).rstrip(''), end='')
print(('{:{prec}d}'.format(i, prec = 5)).lstrip(''))
And now, the output is:
upper bound = 300
m n
220 284
Related
This is for a school assignment.
I have been tasked to define a function determining the largest square pyramidal number up to a given integer(argument). For some background, these are square pyramidal numbers:
1 = 1^2
5 = 1^2+2^2
14 = 1^2+2^2+3^2
So for a function and parameter largest_square_pyramidal_num(15), the function should return 14, because that's the largest number within the domain of the argument.
I get the idea. And here's my code:
def largest_square_pyramidal_num(n):
sum = 0
i = 0
while sum < n:
sum += i**2
i += 1
return sum
Logically to me, it seemed nice and rosy until I realised it doesn't stop when it's supposed to. When n = 15, sum = 14, sum < n, so the code adds one more round of i**2, and n is exceeded. I've been cracking my head over how to stop the iteration before the condition sum < n turns false, including an attempt at break and continue:
def largest_square_pyramidal_num(n):
sum = 0
for i in range(n+1):
sum += i**2
if sum >= n:
break
else:
continue
return sum
Only to realise it doesn't make any difference.
Can someone give me any advice? Where is my logical lapse? Greatly appreciated!
You can do the following:
def largest_pyr(x):
pyr=[sum([i**2 for i in range(1,k+1)]) for k in range(int(x**0.5)+1)]
pyr=[i for i in pyr if i<=x]
return pyr[-1]
>>>largest_pyr(15)
14
>>> largest_pyr(150)
140
>>> largest_pyr(1500)
1496
>>> largest_pyr(15000)
14910
>>> largest_pyr(150000)
149226
Let me start by saying that continue in the second code piece is redundant. This instruction is used for scenario when you don't want the code in for loop to continue but rather to start a new iteration (in your case there are not more instructions in the loop body).
For example, let's print every number from 1 to 100, but skip those ending with 0:
for i in range(1, 100 + 1):
if i % 10 != 0:
print(i)
for i in range(1, 100 + 1):
if i % 10 == 0:
# i don't want to continue executing the body of for loop,
# get me to the next iteration
continue
print(i)
The first example is to accept all "good" numbers while the second is rather to exclude the "bad" numbers. IMHO, continue is a good way to get rid of some "unnecessary" elements in the container rather than writing an if (your code inside if becomes extra-indented, which worsens readability for bigger functions).
As for your first piece, let's think about it for a while. You while loop terminates when the piramid number is greater or equal than n. And that is not what you really want (yes, you may end up with a piramid number which is equal to n, but it is not always the case).
What I like to suggest is to generate a pyramid number until in exceedes n and then take a step back by removing an extra term:
def largest_square_pyramidal_num(n):
result = 0
i = 0
while result <= n:
i += 1
result += i**2
result -= i ** 2
return result
2 things to note:
don't use sum as a name for the variable (it might confuse people with built-in sum() function)
I swapped increment and result updating in the loop body (such that i is up-to-date when the while loop terminates)
So the function reads like this: keep adding terms until we take too much and go 1 step back.
Hope that makes some sense.
Cheers :)
I'm attempting to write some code as practice for python. After the user inputs a string and a number that is a factor of the length of the string, the output should be the reverse of the string split up into segments equal to the inputted number. My issue is that the output is cut short, which I believe is a problem caused by the condition of my for loop.
def reverse_and_slice(string, k):
i=0
n=len(string)
j=0
revstring=string[::-1]
finalstring=''
for i in range(n//k):
finalstring+=revstring[j:(i+1)*k] + ' '
j+=(i+1)*k
i+=1
print(finalstring)
I am trying to accomplish this using a for loop. 123456789 should print as 987 654 321. However, it is currently printing as 987 654, without the last three digits. Longer inputs are similarly cut short with only two segments of length k.
Your loop iterate correct amount of times. You can simply check it by printing i in the loop. Problem is with j. In the last iteration, it is equal to 9, so revstring[9:9] is empty. And this is caused by + before =: j+=(i+1)*k You are incrementing j instead of changing value.
def reverse_and_slice(string, k):
i=0
n=len(string)
j=0
revstring=string[::-1]
finalstring=''
for i in range(n//k):
finalstring+=revstring[j:(i+1)*k] + ' '
j = (i+1)*k
i+=1 # this line is also not needed
print(finalstring)
recently I was trying out some past year AIO questions, and I couldn't solve this one.
The problem is as follows:
Safe Cracking
Input File: safein.txt
Output File: safeout.txt
Time Limit: 1 second
Over the centuries many wars have been won, not through a battle of strength but a battle of wits. Your sources have recently informed you that your mother has purchased a pre-release copy of the latest computer game, WheeZork, and is hiding it in the safe at home. To open the safe, one must enter a long sequence of numbers by rotating the circular dial to each number in the correct order.
If the correct sequence of numbers is entered into the safe, the safe opens and you can sneak your Christmas present out early. If you get the sequence wrong the alarm system is activated and you will be grounded for life! Luckily, you know that your mother has written the code down on a sheet of paper in her bedside drawer, which she likes to call the "code sheet".
She often boasts about how clever she is and explains to you that the numbers on the sheet are indeed the code to the safe, however each number in the sequence has been increased by a constant non-negative integer, k, which only she knows. Without this value the sheet is useless, and thus only she can open the safe ... or so she thinks!
In order to determine the correct code, you have spied on your mother when she unlocks the safe and you have managed to remember part of the code that she entered. You are not sure which part of the code this corresponds to, but it is definitely a consecutive sequence of numbers in the code. Armed with this knowledge, you set out to determine the full code to the safe.
Your task is, given the full list of numbers your mother has written down on her code sheet, and the shorter sequence that you know appears in the actual code, determine the entire sequence to unlock the safe.
For example, if the code to the safe was 7, 9, 4, 6, 8, 12, and your mother had incremented all numbers by 4, her code sheet would read 11, 13, 8, 10, 12, 16. This is because 7 + 4 = 11, giving the first number 11. The second number is obtained by adding 9 + 4 = 13. The third number is obtained by adding 4 + 4 = 8, and so forth. You may have caught a glimpse of her entering the numbers 4, 6, 8, in order. With this knowledge, you can determine the entire code.
Input
The first line of the input file will contain two integers, a b, separated by a space. The integer a is the length of the sequence written on your mother's code sheet ( 2 <= a <= 100000). The integer b is the length of the sequence that you know is contained within the code to the safe ( 2 <= b <= 30).
Following this will be a lines, each containing a single integer between 1 and 1000000. These lines are the sequence written on your mother's code sheet, in the order they are entered into the safe.
Following this will be b lines, each containing a single integer, also between 1 and 1000000. These lines describe the glimpse of the actual code to the safe.
You are guaranteed that there will only be one possible solution for any given input scenario.
Output
Your output file should consist of a lines. Each of these lines should contain a single integer, representing the full sequence of numbers required to open the safe.
My code (that passes most test cases) is as follows:
'''program implements a function diff which is returns a list that is the difference of the current elements in the list
to solve the problem, the subset list is reduced until it consists of a single integer
the index of this integer in the original list is then found, before determining the non-negative integer
which was used to encode the numbers'''
def diff(lst):
lst2=[]
for i in range(len(lst)-1):
lst2.append(lst[i+1]-lst[i])
return lst2
infile = open("safein.txt", "r")
outfile = open("safeout.txt", "w")
a, b = map(int, infile.readline().split())
lst, sub = [], []
for i in range(a):
lst.append(int(infile.readline()))
for j in range(b):
sub.append(int(infile.readline()))
temp_sub=sub
temp_lst=lst
k = 0
while len(temp_sub) != 1:
temp_sub=diff(temp_sub)
k+=1
for x in range(k):
temp_lst=diff(temp_lst)
n = temp_lst.index(temp_sub[0])
m = lst[n]-sub[0]
lst=[x-m for x in lst]
for i in lst:
outfile.write(str(i) + "\n")
As this code passes most test cases, with the exception of some cases that give an error (I do not know what error it is), I was wondering if anyone could suggest some corner cases that would lead to this algorithm creating an error. So far all the cases that I have thought of have passed.
EDIT:
as niemmi has pointed out below, there are some side cases which my above algorithm cannot handle. As such, I have rewritten another algorithm to solve it. This algorithm passes most test cases, and there are no errors, except that the execution takes longer than 1s. Could anyone help reduce the time complexity of this solution?
def subset(lst1, lst2):
if lst2[0] in lst1:
idx = lst1.index(lst2[0])
for i in range(len(lst2)):
if lst2[i]==lst1[idx+i]:
continue
else:
return False
else:
return False
return True
infile = open("safein.txt", "r")
outfile = open("safeout.txt", "w")
a, b = map(int, infile.readline().split())
lst, sub = [], []
for x in range(a):
lst.append(int(infile.readline()))
for y in range(b):
sub.append(int(infile.readline()))
if subset(lst, sub):
for i in range(a):
outfile.write(str(int(lst[i])) + "\n")
infile.close()
outfile.close()
exit()
i=1
while True:
temp_sub = [x+i for x in sub]
if subset(lst, temp_sub):
lst = [x-i for x in lst]
for j in range(a):
outfile.write(str(int(lst[j])) + "\n")
infile.close()
outfile.close()
exit()
i+=1
EDIT:
Thanks to niemmi, who provided a solution below that I edited slightly to pass a test case returning an error.
def diff(seq):
return (seq[i - 1] - seq[i] for i in range(1, len(seq)))
with open('safein.txt') as in_file:
a, b = (int(x) for x in in_file.readline().split())
code = [int(in_file.readline()) for _ in range(a)]
plain = [int(in_file.readline()) for _ in range(b)]
code_diff = tuple(diff(code))
plain_diff = tuple(diff(plain))
k = 0
def index(plain_diff, code_diff, plain, code, a, b, k):
for i in range(k, a - b):
for j, x in enumerate(plain_diff, i):
if code_diff[j] != x:
break
else:
k = code[i] - plain[0]
break # found match, break outer loop
return k
k = index(plain_diff, code_diff, plain, code, a, b, k)
with open('safeout.txt', 'w') as out_file:
out_file.write('\n'.join(str(x - k) for x in code))
Thanks!
The above implementation calculates repeatedly the differences of consecutive elements on following lines:
while len(temp_sub) != 1:
temp_sub=diff(temp_sub)
k+=1
When run against the example input after first round temp_sub is [2, 2] and after second and final round it is [0]. Then the implementation proceeds to do the same kind of reduction for temp_lst that contains the incremented code which results to [-7, 7, 0, 2].
Then index is used to find the index with 0 value from temp_lst which is then used to deduce k. This approach obviously won't work if there's another 0 value on temp_lst before the index you're trying to find. We can easily craft an input where this might be the case, for example adding 11 twice at the beginning of the code sheet so the full sheet would be [11, 11, 11, 13, 8, 10, 12, 16].
EDIT Why not just use the initial approach of differences of subsequent numbers to find k? Code below loops over code sheet and for each position checks if plain sequence can start from there i.e. if the number is equal or greater than first number in plain sequence since k was defined to be non-negative integer. Then it loops over next b - 1 numbers both on code sheet and plain sequence to see if differences match or not.
Worst case time complexity is O(ab), if that's not good enough you could utilize KMP for faster matching.
with open('safein.txt') as in_file:
a, b = (int(x) for x in in_file.readline().split())
code = [int(in_file.readline()) for _ in range(a)]
plain = [int(in_file.readline()) for _ in range(b)]
for i in range(a):
k = code[i] - plain[0]
if k < 0:
continue
for j in range(1, b):
if code[i] - code[i + j] != plain[0] - plain[j]:
break
else:
break # found match, break outer loop
with open('safeout.txt', 'w') as out_file:
out_file.write('\n'.join(str(x - k) for x in code))
Here are two problems which I do not know what I am coding wrong:
In physics, for a pendulum with length L and initial angle A, its horizontal displacement X(T) at time T is given by the formula
X(T) = L × cos(A × cos(T × √9.8/L)) - L × cos(A)
Write a program which takes two lines of input; the first line is L and the second line is A. The output should be ten lines, giving the values of X(0), X(1), X(2), ..., X(9). For example, if the first line of input is 53.1 and the second line of input is 0.8, then the first line of output is 0.0 and the second line of output is 53.1*cos(0.8*cos(1*√9.8/53.1)) - 53.1*cos(0.8) ~ 2.6689.
Here is what I have, although the grader shows that I am doing some of the math wrong:
import math
L = float(input())
A = float(input())
for i in range (0, 10):
x = L * math.cos(A * math.cos(i * math.sqrt(9.8/L))-L * math.cos(A))
print(x)
For this program, the first line of input is an integer width. Then, there are some lines of text; the line "END" indicates the end of the text. For each line of text, you need to print out a centered version of it, by adding periods .. to the left and right, so that the total length of each line of text is width. (All input lines will have length at most width.) Centering means that the number of periods added to the left and added to the right should be equal if possible; if needed we allow one more period on the left than the right. For example, for input
Here is what I have, although it isn't correct either:
width = int(input())
hi=input()
while hi != "END":
WordInput=input()
x=len(WordInput)
y=width-x
half=y%2
if half == 0:
a = int(y/2)
print("." * a)
elif half == 1:
b = int(y/2) + 1
c = int(y/2)
print("." * b,WordInput,"." * c)
It may help you debug if your inputs have text prompts, as in width = int(input("enter width: ")), which will give you a better idea of where in the code your input will be stored.
I'm not seeing the problem with #1, but it's been a while since I've taken physics. If your grader says just the math is wrong, double check the equation you're using, and add appropriate parentheses in the code to make sure the correct order of operations is done.
There are several problems with #2. First, your program requests input the wrong number of times. Your loop depends on the variable hi, which you only assign once; once your code enters the loop, nothing will change it to "END" and the loop will never exit. Not only that, but the first word you enter (at the hi prompt) is not considered by code in your loop, so anything other than "END" is simply ignored. You'll want something more like this :
WordInput=input()
while WordInput != "END":
# Do your processing and printing code here
(...)
# Then get some new input at the end of the loop
WordInput=input()
The new value of WordInput will be evaluated when the loop restarts.
Second, look at your if statement. You correctly determine that the length is even (half==0), but in the even case you don't tell the code to actually print the input word, just the periods! In practice, it's good to avoid setting up if/else blocks like this with multiple similar print statements; if you want to go back and change the formatting of one, you have to remember to manually change the others too. As your code gets more complicated this will become a real pain, so it's generally best to condense your print statements as much as you can. Without changing your structure too much here's how I would do it:
if half == 0:
a = int(y/2)
elif half == 1:
a = int(y/2) + 1
b = int(y/2)
print("." * a,WordInput,"." * b)
This way, b is assigned in either case and the same print statement will execute no matter what.
Third, any word that is printed and centered by your code is padded by spaces. This is because when you give print() multiple parameters, by default they are joined by spaces. To override this, you can change the separator parameter to an empty string (or anything else you need);
>>>print("." * 4, "Hey", "." * 4)
.... Hey ....
>>>print("." * 4, "Hey", "." * 4, sep="")
....Hey....
For 1. The parentheses are wrong!
import math
L = float(input())
A = float(input())
for i in range (0, 10):
x = L * math.cos(A * math.cos(i * math.sqrt(9.8/L)))-L * math.cos(A)
print(x)
Here is an example of a for loop inside another for loop.
Example
This code prints a 5×5 square of ones.
Note: when we multiply a number X by ten and add one, we're essentially putting an extra 1 digit at the end of X. For example, (1867*10)+1=18671.
for i in range(0, 5):
X = 0
for j in range(0, 5):
X = (X*10)+1
print(X)
Modify the previous program in two ways. First, instead of a square, make it draw a triangle shaped like this: ◤. Second, instead of always having 5 lines, it should take the desired size as input from input(). For example, if the input is 3, then the output should be
111
11
1
So far the code that I have got is:
X=input()
for i in range(0, 3):
X = 0
for j in range(0, 3):
X = (X*10)+1
print(X)
However this code outputs:
1
11
111
When the expected output should be:
111
11
1
I can't seem to figure out how to change my code that I have so far to get the expected output?
This can solve the problem for you:
def test(X,_range):
x = X
for j in range(0, _range):
print int(str((x*10) +1) + ("1"*(_range-1-j)))
test(0,3)
>>>
111
11
1
>>>
In every loop step the number starts with (X*10)+1
In the next step X has changed and you add the digit 1 to the right side
If want to reverse it, you need to use ("1"*(_range-1-j))
The for iterator changes the X content every step. (he don't use i and j, "For" only for step derivation )
Here's the solution:
n=int(input())
for i in range(0, n):
X = 0
for j in range(0, n-i):
X = (X*10)+1
print(X)
As you said, 10*X + 1 means putting extra 1 at the end of X. You need an inverse operation: how to remove the last digit of a number. Hint: integer division. Google "python integer division" to get to pages such as Python integer division yields float.
So, then all you've to do is construct 111...11 of the right length, and then iteratively print and remove digits one by one.
This block is very confusing, here's what happens:
X=input()
Get value of X from input.
for i in range(0, 3):
X = 0
Now set the value of X to 0 three times (overwriting your input)
for j in range(0, 3):
X = (X*10)+1
print(X)
Now X is being set to 1, then 11 and then 111.
Even if you meant to nest the for loops, this wont behave right. Instead, you want to get the i value to loop backwards, using the slice operator [::-1]. You should then make j's range be zero to i.
You'll also need to compensate by increasing the value of both numbers in i's range (otherwise the last line will be a zero) but this will work:
for i in range(1, 6)[::-1]:
X = 0
for j in range(0, i):
X = (X*10)+1
print(X)
Note that I moved the print out of the j loop, as that wasn't how the original code was (and generated the wrong output), pay attention to whitespace. Using 4 spaces is preferable to just 2 for reasons like this.
If you are doing CS Circles than these other answers probably contain code you still haven't come in contact with, at least I haven't, so I'll try to explain it with the knowledge I've gathered so far (couple weeks doing CS Circles).
You are ignoring the first loop and it is where your answer lies. Notice that if you put the print command outside of the loop body it would just output:
111
That it because your second loop is not in the body of the first, so python just loops the first one 3x and than moves to the second loop. Instead it should be:
for i in range(0, 3):
X = 0
for j in range (0, 3):
X = (X*10)+1
print(X)
Now the program outputs:
111
111
111
But you want one less digit each time print is called again. This is achieved by subtracting the value of "i" (since it neatly goes from 0 to 2) from second loop's range tail value. So now you have :
for i in range(0, 3):
X = 0
for j in range(0, 3-i):
X = (X*10)+1)
print(X)
Finally the output is:
111
11
1
Protip: use the visualizer in CS Circles, it helps you better understand the way code is executed in python, and can provide insight to your problems. Best of luck!
The easiest way is to use the following code;
p = int(input())
for i in range(0,p):
x = 0
for j in range(i,p):
x = (x*10)+1
print(x)