without Loops to Sum Range of odd numbers - python

is there any way to sum odd numbers from 1 to n but without any loops and if there isn't a way how can i create this by fast algorithm to do this task in less than n loops.

You can take advantage of the summation in an Arithmetic Series to sum the first n odd numbers (not the odd numbers from 0 to n)
a = 1 # from 1
n = 9999 # to n
d = 2 # and skip every even number
n = int((n - a) / d + 1) # locate the number of term for n
sum = int((n / 2) * (2 * a + (n - 1) * d))
Time complexity: O(1), no loop
reference: Summing an Arithmetic Series
edit: to fit case for even n, e.g. 10000
if n % 2 == 0:
n = n - 1 # to eliminate the case 10000 and find range 1-9999

Try this -
sum(range(1, n+1, 2))

You can try the one below, which loop through from 1 to n, stepping 2
sum(range(1,n,2))

Related

how to use for-loop to sum first n integer fractions

How to create a program that uses a for-loop to sum the first n
integer fractions 1/2 + 2/3 + 3/4 + .... (n-1) / n + n / (n + 1). (n> 0 is a positive
integer and the last number in the sum is n / (n + 1)
I have tried many times but nothing seems to work.
You can try it.
def sum_fraction(n):
# Initialize the sum variable
sum = 0
# For loop : start from 1 ( n greater than zero ) : end with n
for i in range(1, n):
# Sum current term with all previous term (term by term)
sum += i / (i + 1)
return sum
n = 5
res = sum_fraction(n)
n = int(input("Enter the nth term"))
fsum = 0
#Recommended to not use 'sum' itself
#as it can cause problems with python's built in function which also has the same name
for i in range(1, n+1):
fsum += i/(i+1)
print(fsum)
I guess this should solve your problem
If u want to know more about range function,see this
https://www.w3schools.com/python/ref_func_range.asp
Note that the range function only returns till the stop value and not including the stop value.The stop value in your case is the variable n.That is why we have to use n+1 in the range function

Probability that n is achieved by multiplying two random integers from two given ranges

So here is the challenge: I am given four numbers: a,b,c,d. Then the number n is given which describes how many numbers to check will be. Then these numbers are inputted and the goal is to find which probability that number will be gotten if multiply two random numbers one from the range a to b and one from c to d range. Finally, I need to output that probability in 'p/q' format. I figured out the solution and it works but the problem is when working with bigger numbers it uses too much time. I also have another solution where I first create a list with all possible combinations but in that case it uses too much memory.
from math import gcd
a,b,c,d = (map(int,input().split(" ")))
combs_quantity = (b-a+1)*(d-c+1)
def findProb(z):
repeats = 0
nec_mulps = [z//x for x in range(a,b+1) if z%x == 0]
for n in nec_mulps:
if n in range(c,d+1):
repeats+=1
probGCD = gcd(repeats,combs_quantity)
return str(repeats//probGCD) + "/" + str(combs_quantity//probGCD)
probability = []
n = int(input())
for i in range(n):
probability.append(findProb(int(input())))
for p in probability:
print(p)
Get all divisors of n
For every divisor Z that belongs to range a..b check whether complementary divisor n//Z lies in range c..d
#MBo said above that complexity is sqrt(z). You can to calculcate repeats as:
divisors = []
i = 1
while i * i <= z:
if z % i == 0:
divisors.append(i)
if i * i < z:
divisors.append(z // i)
i += 1
repeats = 0
for divisor in divisors:
if a <= divisor <= b and c <= z // divisor <= d:
repeats += 1

Project Euler Problem 12, How can I optimize my code so it finds the answer faster?

I have been writing in python for only few months now, so please don't be too harsh on me. But I've wrote this code and I don't know how I can make it faster.
n = 2
ListOfTriangles = []
ListOfDivisors = []
term = 0
for x in range(1,100001):
x = (n*(n-1))/2
ListOfTriangles.append(int(x))
n += 1
for y in range(1,100001):
Tri = ListOfTriangles[term]
for i in range(1,Tri+1):
if(Tri%i==0):
ListOfDivisors.append(i)
if len(ListOfDivisors) >= 500:
print("---------------------------------------------------")
print(len(ListOfDivisors))
print(ListOfDivisors)
print(ListOfTriangles[term])
print("---------------------------------------------------")
break
print(ListOfTriangles[term]," - ",len(ListOfDivisors)," - ",(term/100000)*(10**2),"%")
ListOfDivisors = []
term += 1
Basically what I have done if you can't tell by this mess, is that i created a list with Triangular Numbers and then put this list through loop that list all factors for each number found in the list and then stop when it finds number that meats the requirement of number having over 500 factors.
One idea applicable to this problem is as follows:
The n'th triangular number t[n] is given by n * (n + 1) / 2. Note that the only common divisor of n and n + 1 is 1. Let divs[n] denote the number of divisors of n. Then,
for even n, we have divs[t[n]] = divs[n//2] * divs[n+1] - 1
for odd n, we have divs[t[n]] = divs[n] * divs[(n+1)/2] - 1
We can precompute the number of divisors for each number from 1 to n in O(n^2) time (this can be improved asymptotically), and use the formula above to compute the number of divisors for the corresponding triangular number. With numpy, we have:
import numpy as np
# pick a number of elements for divisor computation
n = 20_000
# store number of divisors of n; O(n^2), can be optimized asymptotically
divs = np.zeros(n+1, dtype=int)
for i in range(1,n+2):
# i divides every number in the sequence i, 2i, 3i... (up to n)
divs[i:n+2:i] += 1
# store number of divisors of n'th triangular number
divs_tri = np.zeros(n, dtype=int)
# treat evens and odds separately
evens = np.arange(0, n, 2) # e.g. [0, 2, 4...]
odds = np.arange(1, n, 2) # e.g. [1, 3, 5...]
# with even k, k/2 and k+1 are coprime; -1 accounts for 1 being a factor of both
divs_tri[evens] = divs[evens//2] * divs[evens+1] - 1
# with odd k, k and (k+1)/2 are coprime; -1 accounts for 1 being a factor of both
divs_tri[odds] = divs[odds] * divs[(odds+1)//2] - 1
# index of first triangular number with at least 500 divisors
k = (divs_tri >= 500).argmax()
# compute the value of k'th triangular number
ans = k * (k + 1) // 2

Efficient algorithm to find the count of numbers that are divisible by a number without a remainder in a range

Let's say I have two numbers: 6 and 11 and I am trying to find how many numbers between this range are divisible by 2 (3, in this case).
I have this simple code right now:
def get_count(a, b, m):
count = 0
for i in range(a, b + 1):
if i % m == 0:
count += 1
return count
Its order of growth is linear, O(N), I believe.
I was wondering if there is a faster algorithm with a constant O(1) performance, or a mathematical formula.
I don't expect a direct answer. The name of such an algorithm would be awesome.
Thank you.
((b - b%m) - a)//m+1 seems to work for me. I doubt it has a name. Another formula that seems to work is (b//m) - ((a-1)//m).
Sample python3 program:
def get_count(a, b, m):
return (((b - (b % m)) - a) // m) + 1
for i in range(5, 8):
for j in range(10, 13):
print(get_count(i, j, 2), end=" ")
print()
You are counting even numbers. Let's write o for odd, E for even.
If the sequence has an even count of numbers, it is either oEoE...oE or EoEo...Eo, i.e. one half of numbers is always even. If there is odd count of numbers, you can check the first number (or last one) separately and the rest is the known case discussed first.
def count_even(start, end):
# assert start <= end
len = end - start
len2, r = divmod(len, 2)
if r and start % 2 == 0:
len2 += 1
return len2
To find the count of all numbers between 0 and n that are divisible by two. you can use the bitwise operation called right shift;
c = a >> 1;
10 >> 1 is equivalent to floor(10/2)
You can subtract the two resultant numbers and get numbers between any range.
This will work in O(1). Hope this helps.

How to calculate no. of palindroms in a large number interval?

I want to calculate how many numbers are palindrome in large interval data say 10^15
My simple code (python) snippet is:
def count_palindromes(start, end):
count = 0
for i in range(start, end + 1):
if str(i) == str(i)[::-1]:
count += 1
return count
start = 1000 #some initial number
end = 10000000000000 #some other large number
if __name__ == "__main__":
print count_palindromes(start, end)
Its a simple program which checks each number one by one. Its vary time consuming and takes a lot of computer resources.
Is there any other method/technique by which we can count Palindrome numbers? Any Algorithm to use for this?
I want to minimize time taken in producing the output.
When you want to count the numbers having some given property between two limits, it is often useful to solve the somewhat simpler problem
How many numbers with the given property are there between 0 and n?
Keeping one limit fixed can make the problem significantly simpler to tackle. When the simpler problem is solved, you can get the solution to the original problem with a simple subtraction:
countBetween(a,b) = countTo(b) - countTo(a)
or countTo(b ± 1) - countTo(a ± 1), depending on whether the limit is included in countTo and which limits shall be included in countBetween.
If negative limits can occur (not for palindromes, I presume), countTo(n) should be <= 0 for negative n (one can regard the function as an integral with respect to the counting measure).
So let us determine
palindromes_below(n) = #{ k : 0 <= k < n, k is a palindrome }
We get more uniform formulae for the first part if we pretend that 0 is not a palindrome, so for the first part, we do that.
Part 1: How many palindromes with a given number d of digits are there?
The first digit cannot be 0, otherwise it's unrestricted, hence there are 9 possible choices (b-1 for palindromes in an arbitrary base b).
The last digit is equal to the first by the fact that it shall be a palindrome.
The second digit - if d >= 3 - can be chosen arbitrarily and independently from the first. That also determines the penultimate digit.
If d >= 5, one can also freely choose the third digit, and so on.
A moment's thought shows that for d = 2*k + 1 or d = 2*k + 2, there are k digits that can be chosen without restriction, and one digit (the first) that is subject to the restriction that it be non-zero. So there are
9 * 10**k
d-digit palindromes then ((b-1) * b**k for base b).
That's a nice and simple formula. From that, using the formula for a geometric sum, we can easily obtain the number of palindromes smaller than 10n (that is, with at most n digits):
if n is even, the number is
n/2-1 n/2-1
2 * ∑ 9*10**k = 18 * ∑ 10**k = 18 * (10**(n/2) - 1) / (10 - 1) = 2 * (10**(n/2) - 1)
k=0 k=0
if n is odd, the number is
2 * (10**((n-1)/2) - 1) + 9 * 10**((n-1)/2) = 11 * (10**((n-1)/2) - 2
(for general base b, the numbers are 2 * (b**(n/2) - 1) resp. (b+1) * b**((n-1)/2) - 2).
That's not quite as uniform anymore, but still simple enough:
def palindromes_up_to_n_digits(n):
if n < 1:
return 0
if n % 2 == 0:
return 2*10**(n//2) - 2
else:
return 11*10**(n//2) - 2
(remember, we don't count 0 yet).
Now for the remaining part. Given n > 0 with k digits, the palindromes < n are either
palindromes with fewer than k digits, there are palindromes_up_to_n_digits(k-1) of them, or
palindromes with exactly k digits that are smaller than n.
So it remains to count the latter.
Part 2:
Letm = (k-1)//2 and
d[1] d[2] ... d[m] d[m+1] ... d[k]
the decimal representation of n (the whole thing works with the same principle for other bases, but I don't explicitly mention that in the following), so
k
n = ∑ d[j]*10**(k-j)
j=1
For each 1 <= c[1] < d[1], we can choose the m digits c[2], ..., c[m+1] freely to obtain a palindrome
p = c[1] c[2] ... c[m+1] {c[m+1]} c[m] ... c[2] c[1]
(the digit c[m+1] appears once for odd k and twice for even k). Now,
c[1]*(10**(k-1) + 1) <= p < (c[1] + 1)*10**(k-1) <= d[1]*10**(k-1) <= n,
so all these 10**m palindromes (for a given choice of c[1]!) are smaller than n.
Thus there are (d[1] - 1) * 10**m k-digit palindromes whose first digit is smaller than the first digit of n.
Now let us consider the k-digit palindromes with first digit d[1] that are smaller than n.
If k == 2, there is one if d[1] < d[2] and none otherwise. If k >= 3, for each 0 <= c[2] < d[2], we can freely choose the m-1 digits c[3] ... c[m+1] to obtain a palindrome
p = d[1] c[2] c[3] ... c[m] c[m+1] {c[m+1]} c[m] ... c[3] c[2] d[1]
We see p < n:
d[1]*(10**(k-1) + 1) + c[2]*(10**(k-2) + 10)
<= p < d[1]*(10**(k-1) + 1) + (c[2] + 1)*(10**(k-2) + 10)
<= d[1]*(10**(k-1) + 1) + d[2]*(10**(k-2) + 10) <= n
(assuming k > 3, for k == 3 replace 10**(k-2) + 10 with 10).
So that makes d[2]*10**(m-1) k-digit palindromes with first digit d[1] and second digit smaller than d[2].
Continuing, for 1 <= r <= m, there are
d[m+1]*10**(m-r)
k-digit palindromes whose first r digits are d[1] ... d[r] and whose r+1st digit is smaller than d[r+1].
Summing up, there are
(d[1]-1])*10**m + d[2]*10**(m-1) + ... + d[m]*10 + d[m+1]
k-digit palindromes that have one of the first m+1 digits smaller than the corresponding digit of n and all preceding digits equal to the corresponding digit of n. Obviously, these are all smaller than n.
There is one k-digit palindrome p whose first m+1 digits are d[1] .. d[m+1], we must count that too if p < n.
So, wrapping up, and now incorporating 0 too, we get
def palindromes_below(n):
if n < 1:
return 0
if n < 10:
return n # 0, 1, ..., n-1
# General case
dec = str(n)
digits = len(dec)
count = palindromes_up_to_n_digits(digits-1) + 1 # + 1 for 0
half_length = (digits-1) // 2
front_part = dec[0:half_length + 1]
count += int(front_part) - 10**half_length
i, j = half_length, half_length+1
if digits % 2 == 1:
i -= 1
while i >= 0 and dec[i] == dec[j]:
i -= 1
j += 1
if i >= 0 and dec[i] < dec[j]:
count += 1
return count
Since the limits are both to be included in the count for the given problem (unless the OP misunderstood), we then have
def count_palindromes(start, end):
return palindromes_below(end+1) - palindromes_below(start)
for a fast solution:
>>> bench(10**100,10**101-1)
900000000000000000000000000000000000000000000000000 palindromes between
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
and
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
in 0.000186920166016 seconds
Actually, it's a problem for Google Codejam (which I'm pretty sure you're not supposed to get outside help on) but alas, I'll throw in my 2 cents.
The idea I came up with (but failed to implement) for the large problem was to precompile (generated at runtime, not hardcoded into the source) a list of all palindromic numbers less than 10^15 (there's not very many, it takes like ~60 seconds) then find out how many of those numbers lie between the bounds of each input.
EDIT: This won't work on the 10^100 problem, like you said, that would be a mathematical solution (although there is a pattern if you look, so you'd just need an algorithm to generate all numbers with that pattern)
I presume this is for something like Project Euler... my rough idea would be to generate all numbers up to half the length of your limit (like, if you're going to 99999, go up to 99). Then reverse them, append them to the unreversed one, and potentially add a digit in the middle (for the numbers with odd lengths). You'll might have to do some filtering for duplicates, or weird ones (like if you had a zero at the beginning of the number or sommat) but that should be a lot faster than what you were doing.

Categories

Resources