How to calculate the sum faster - python

Memory limit: 256 MB
Time limit: 1 s
Hello.
We have the following code:
N, M = list(map(int, input().split()))
stones = list(map(int, input().split()))
for __ in range(M):
command, index, num = input().split()
index, num = int(index), int(num)
if command == "S":
print(sum(stones[index:num + 1]))
elif command == "M":
stones[index] = num
Where:
N is the length of list stones
M is number of commands
1 ≤ N, M ≤ 10**5
commands in form {type} {index} {index2 or value} of two types:
'S' to print sum of items in range [index; index2]
'M' to change value of item on index to new 0 ≤ value ≤ 10
This code exceeds the time limit. So, how to optimize it?
Sample Input:
9 10
1 1 2 3 5 0 4 9 4
S 2 4
S 8 8
S 0 8
S 4 5
M 5 9
S 0 8
S 4 5
M 0 7
S 1 8
S 0 5
Sample Output:
10
4
29
5
38
14
37
27

Related

Python. How do i count the number of divisors in nested for loop?

I have a code that generates triangular numbers, calculates the divisors for each triangular number and prints out 3 columns where the first column is the input numbers, the second column is the triangular numbers and the third column is the divisors of each triangular number. How can I count the number of divisors of each triangular number(count the numbers in the third column)?
for num in range(10):
triangle_number = num*(num+1)//2
print(num, end = ' ')
print(triangle_number, end = ' ')
for divisor in range(1, triangle_number+1):
if triangle_number%divisor == 0:
print(divisor, end = ',')
print()
Output looks like this:
0 0
1 1 1,
2 3 1,3,
3 6 1,2,3,6,
4 10 1,2,5,10,
5 15 1,3,5,15,
6 21 1,3,7,21,
7 28 1,2,4,7,14,28,
8 36 1,2,3,4,6,9,12,18,36,
9 45 1,3,5,9,15,45,
You can add a variable inside for loop and increment it when you get the divisor and print a the end.
for num in range(10):
count = 0
triangle_number = num*(num+1)//2
print(num, end = '\t')
print(triangle_number, end = '\t')
for divisor in range(1, triangle_number+1):
if triangle_number%divisor == 0:
print(divisor, end = ',')
count += 1
print("\t", count)
##Output:
##0 0 0
##1 1 1, 1
##2 3 1,3, 2
##3 6 1,2,3,6, 4
##4 10 1,2,5,10, 4
##5 15 1,3,5,15, 4
##6 21 1,3,7,21, 4
##7 28 1,2,4,7,14,28, 6
##8 36 1,2,3,4,6,9,12,18,36, 9
##9 45 1,3,5,9,15,45, 6
##Output order : input number, count of divisors divisors, triangular number
or you can create a list of divisors and measure length before printing.
for num in range(10):
divisors = []
triangle_number = num*(num+1)//2
print(num, end = '\t')
print(triangle_number, end = '\t')
for divisor in range(1, triangle_number+1):
if triangle_number%divisor == 0:
divisors.append(divisor)
print(len(divisors), "\t", ",".join(str(div )for div in divisors))
##Output:
##0 0 0
##1 1 1 1
##2 3 2 1,3
##3 6 4 1,2,3,6
##4 10 4 1,2,5,10
##5 15 4 1,3,5,15
##6 21 4 1,3,7,21
##7 28 6 1,2,4,7,14,28
##8 36 9 1,2,3,4,6,9,12,18,36
##9 45 6 1,3,5,9,15,45
##Output order : input number, triangular number, count of divisors divisors
You might replace your inner for loop using list comprehension and then just get length of that list using len function, that is replace:
for divisor in range(1, triangle_number+1):
if triangle_number%divisor == 0:
print(divisor, end = ',')
with:
divisors = [divisor for divisor in range(1, triangle_number+1) if triangle_number%divisor == 0]
print(*divisors, sep=',', end=' ')
print(len(divisors), end='')
list comprehension is succint way of creating list which might be created via appending inside for loop, * (star operator) does unpacking, if you would have list x = [1, 2, 3] then print(*x) is equivalent of print(1, 2, 3) and so on.

how to \n in certain places in a list

Trying to opening a new line in different points in a generated list.
ive tried to use this to seperate a list but it doesnt work.
for j in range (num,0,-1):
for i in range(0,len(num),j):
blist[i:j]
print(blist)
heres my code
num=int(input('Size: '))
list=[]
blist=[]
for k in range(num,-1,-1):
for i in range(0,num,1):
list.append(i)
num-=1
print(list)
for j in range (num,0,-1):
for i in range(0,len(num),j):
blist[i:j]
print(blist)
heres the expected result
Size: 8
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6
0 1 2 3 4 5
0 1 2 3 4
0 1 2 3
0 1 2
0 1
0
Size: 3
0 1 2
0 1
0
This works:
n = int(input('Size: '))
L = [str(i) for i in range(n)]
for i in range(n):
print(' '.join(L[:n-i]))
Line by line explanation:
L = [str(i) for i in range(n)] Create a list of string digits from 0 up to n-1
for i in range(n): set i from 0 up to n-1
L[:n-i] slices the list L from start up to n-i (not inclusive)
' '.join(L[:n-i]) just glues together all the elements of the resulting slice with a white space ' '
How about this?
num=int(input('Size: '))
list_=[]
for k in range(num,-1,-1):
list_.append([str(i) for i in range(0,num,1)])
num -= 1
result = '\n'.join([' '.join(l) for l in list_])
print(result)
The result takes each list in list_ and joins them by a space, then the next join separates them by newlines.
Below code can work for me.
num=int(input('Size: '))
list_data = list(range(num))
for i in reversed(range(1, num +1 )):
print( list_data[0:i])
You can unpack the output of range as arguments to print instead:
num = int(input('Size: '))
for n in range(num):
print(*range(num - n))
Sample input/output:
Size: 7
0 1 2 3 4 5 6
0 1 2 3 4 5
0 1 2 3 4
0 1 2 3
0 1 2
0 1
0

Pascal's triangle code

I am having trouble getting this python code to work right. it is a code to display pascal's triangle using binomials. I do not know what is wrong. The code looks like this
from math import factorial
def binomial (n,k):
if k==0:
return 1
else:
return int((factorial(n)//factorial(k))*factorial(n-k))
def pascals_triangle(rows):
rows=20
for n in range (0,rows):
for k in range (0,n+1):
print(binomial(n,k))
print '\n'
This is what it keeps printing
1
1 1
1
2
1
1
12
3
1
1
144
24
4
1
1
2880
360
40
5
1
1
86400
8640
720
60
6
1
1
3628800
302400
20160
1260
and on and on. any help would be welcomed.!!
from math import factorial
def binomial (n,k):
if k==0:
return 1
else:
return int((factorial(n)//factorial(k))*factorial(n-k))
def pascals_triangle(rows):
for n in range (rows):
l = [binomial(n, k) for k in range (0,n+1)]
print l
pascals_triangle(5)
output:
[1]
[1, 1]
[1, 2, 1]
[1, 12, 3, 1]
[1, 144, 24, 4, 1]
there are many wrong things.
The first one is the way you compute the values : if building a pascal triangle, you want to use the previous line to compute the current one, and not use the binomial computation (which is expensive due to the number of multiplications).
then by default, print appends a "\n"
Correct implementation:
def print_line(x):
print (" ".join(map(str,x)))
def pascals_triangle(rows):
cur_line=[1,1]
for x in range (2,rows):
new_line=[1]
for n in range (0,len(cur_line)-1):
new_line.append(cur_line[n]+cur_line[n+1])
new_line.append(1)
print_line (new_line)
cur_line=new_line
this provides the following output
$ python pascal.py
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
Your binomial function had a small bracketing mistake in it, which was giving you incorrect output:
from math import factorial
def binomial(n, k):
if k==0:
return 1
else:
return int((factorial(n)/(factorial(k)*factorial(n-k))))
def pascals_triangle(rows, max_width):
for n in range (0,rows):
indent = (rows - n - 1) * max_width
print(' ' * indent, end='')
for k in range(0, n+1):
print("{:^{w}}".format(binomial(n, k), w = max_width*2), end='')
print()
pascals_triangle(7, 2)
With the addition of a padding parameter, the output can be made to look like this:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1

Error with len() function or something else?

So I've been trying to get my program to loop through this pke equation with only the e changing 15 times into a list. I thought I had it solved but in my print statement instead of len just printing a single number for each exponent it's lopping through and printing a number for every unique number it has. I'm having trouble with seeing where I'm going wrong. My program is this:
def greatest_common_divisor(a_int, b_int):
if a_int > b_int:
dividend = a_int
divisor = b_int
else: # b >= a
dividend = b_int
divisor = a_int
remainder = dividend % divisor
quotient = dividend // divisor
while remainder != 0:
dividend = divisor
divisor = remainder
remainder = dividend % divisor
quotient = dividend // divisor
return divisor # which is the gcd
p =5
q = 7
n = p*q
header = ["p","q","n","e","diminished","gcd","unique remainders","max remainders"]
print(header)
for e in range(12,27):
unique_remainders_list = []
for x in range(1,(n+1)):
y = x**e % n
diminished = (p - 1)*(q - 1)
gcd = greatest_common_divisor(e, diminished)
max_uni_val = n-1
if not (y in unique_remainders_list):
unique_remainders_list.append(y)
print("{:>2} {:>4} {:>6} {:>4} {:>10} {:>9} {:>10} {:>16}".\
format(p,q,n,e,diminished,gcd,len(unique_remainders_list),max_uni_val, end = ' '))
Example of print:
['p', 'q', 'n', 'e', 'diminished', 'gcd', 'unique remainders', 'max remainders']
5 7 35 12 24 12 1 34
5 7 35 12 24 12 2 34
5 7 35 12 24 12 3 34
5 7 35 12 24 12 4 34
5 7 35 13 24 1 1 34
5 7 35 13 24 1 2 34
5 7 35 13 24 1 3 34
5 7 35 13 24 1 4 34
5 7 35 13 24 1 5 34
5 7 35 13 24 1 6 34
5 7 35 13 24 1 7 34
5 7 35 13 24 1 8 34
So I think I'm having trouble with the range of e in the end, I'm just not sure where.
Figured it out, needed to move my print statement over. I hate when I miss such small things, but thanks for the help hagubear.
for e in range(12,27):
unique_remainders_list = []
for x in range(1,(n+1)):
y = x**e % n
diminished = (p - 1)*(q - 1)
gcd = greatest_common_divisor(e, diminished)
max_uni_val = n-1
if not (y in unique_remainders_list):
unique_remainders_list.append(y)
print("{:>2} {:>4} {:>6} {:>4} {:>10} {:>9} {:>10} {:>16}".\
format(p,q,n,e,diminished,gcd,len(unique_remainders_list),max_uni_val, end = ' '))

Count number of 0s from [1,2,....num]

We are given a large number 'num', which can have upto 10^4 digits ,( num<= 10^(10000) ) , we need to find the count of number of zeroes in the decimal representation starting from 1 upto 'num'.
eg:
countZeros('9') = 0
countZeros('100') = 11
countZeros('219') = 41
The only way i could think of is to do brute force,which obviously is too slow for large inputs.
I found the following python code in this link ,which does the required in O(L),L being length of 'num'.
def CountZeros(num):
Z = 0
N = 0
F = 0
for j in xrange(len(num)):
F = 10*F + N - Z*(9-int(num[j]))
if num[j] == '0':
Z += 1
N = 10*N + int(num[j])
return F
I can't understand the logic behind it..Any kind of help will be appreciated.
from 0 - 9 : 0 zeros
from 10 - 99: 9 zeros ( 10, 20, ... 90)
--100-199 explained-----------------------
100, 101, ..., 109 : 11 zeros (two in 100)
110, 120, ..., 199: 9 zeros (this is just the same as 10-99) This is important
Total: 20
------------------------------------------
100 - 999: 20 * 9 = 180
total up to 999 is: 180 + 9: 189
CountZeros('999') -> 189
Continu this pattern and you might start to see the overall pattern and eventually the algorithm.
Does the following help you're understanding:
>>> for i in range(10, 100, 10):
... print(CountZeros(str(i)))
...
1
2
3
4
5
6
7
8
9
>>>
What about this:
>>> CountZeros("30")
j Z N F
0 0 0 0
j Z N F
0 0 3 0
j Z N F
1 0 3 0
j Z N F
1 1 30 3
3

Categories