Euler project Prob 23 Non abundant sums :python2 - python-2.7

I am trying to solve problem 23 in project euler in python2. I am getting the result as 4179935 but the correct answer is 4179871
This is the actual question
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example,
the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of
two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be
written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis
even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
import itertools
def find_non_abundant_sums(num):
non_abundant_number = set()
non_abundant_sums = set()
all_numbers = set(range(1,num+1))
for i in range(1,num+1):
divisor_sum = find_divisor_sum(i)
if(divisor_sum > i):
non_abundant_number.add(i)
for j in itertools.combinations(non_abundant_number,2):
if(j[0]+j[1] < num+1):
non_abundant_sums.add(j[0]+j[1])
print (sorted(non_abundant_sums))
return sum(all_numbers-non_abundant_sums)
def find_divisor_sum(num):
divisors = set()
for i in range(1,num):
if(num%i==0):
divisors.add(i)
return sum(divisors)
print (find_non_abundant_sums(28123))
expected: 4179871
actual: 4179935

Related

Printing sum of non abundant numbers in haskell

This is a Project Euler Problem 23: Non-abundant Sums.
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
Here the sumOfPD function returns the sum of proper divisors.
I wrote the following code which doesn't work.
sumOfPD :: Integral a => a -> a
sumOfPD x = sum([y | y <- [1..x], rem x y == 0]) - x
main = do
print (sum ([x + y | x <- [1..], y <- [1..], x + y < 28124, sumOfPD x <= x, sumOfPD y <= y]))
I'm new to Haskell. Please help me resolve error.
You have two problems. One is largely mathematical and one is largely about Haskell semantics. Both stem from a lack of care and clarity of thought; you should think more carefully and slowly about how to write a program which does less work to get to the answer. I'm not going to write down any solution or correct version (indeed project Euler discourages sharing solutions) as that won't help you and it won't help anyone who comes across this by google.
In your sum in main you're counting some numbers multiple times. For example $1+2+4+5+10=21>20$ so 20 is abundant. Your list includes $32=12+20=20+12$ at least twice. Note [32,32] /= [32]. Also note that this isn't just an issue with counting $x+y$ and $y+x$, there might be some numbers which are the sum of two ambiguous in two (non-trivially) different ways.
Due to the nature of list comprehensions in Haskell, in main, x will only ever take a value of 1 as the values considered are (x,y)=(1,1),(1,2),(1,3),(1,4),... and then each of those values is tested. There is a point after which all values are rejected as x+y>=28124 but you never move on to the next x value. Indeed all values are rejected as 1 is not abundant. Try changing [1..] to [1..n] where n is something you should decide on. Alternatively, change it to a list of abundant numbers up to some limit. Cf takeWhile and filter

Make summing power series more efficient

I am coding in hackerrank and came across this problem:
https://www.hackerrank.com/challenges/power-calculation
My code works for small files and big numbers. As for the big files, it times out. Could someone make it more efficient.
My code:
z = []
def modexp(a, n, m):
bits = []
while n:
bits.append(n%2)
n /= 2
solution = 1
bits.reverse()
for x in bits:
solution = (solution*solution)%m
if x:
solution = (solution*a)%m
return solution
for _ in xrange(int(input())):
while True:
try:
x = raw_input()
sum =0
z = x.split(' ')
power = int(z[1])
limit = int(z[0])
for i in range(0,limit+1):
sum = sum%100 + modexp(i%100,power, pow(10,2))
if sum < 10:
print '%02d' % sum
if sum > 10:
print sum%100
except:
break
Sample data - input:
10
487348 808701
204397 738749
814036 784709
713222 692670
890568 452450
686541 933150
935447 202322
559883 847002
468195 111274
833627 238704
Sample output:
76
13
76
75
24
51
20
54
90
42
One can easily reduce the number of power evaluations by observing that its values mod 100 have a period of 100. Thus
decompose K = M*100+L by computing M=K/100; L=K%100;.
Then
for k=0 to L the power modexp(k%100,N,100) occurs M+1 times,
for k=L+1 to 99 it occurs M times in the sum.
Thus each power sum can be reduced to 99 power computations
One can reduce the effort to compute the powers even more by observing that increasing powers of the same number are periodic in the last two digits. Generally the sequence
1, a % m, a**2 % m, a**3 % m, a**4 % m, ...
becomes periodic after some point that is given by the highest multiplicity of a prime factor. One period length is given by the value of m in Euler's totient function.
The totient value of 100=2²·5² is phi(100)=(2-1)·2·(5-1)·5=40. The offset before the period sets in is at most 2, it follows that for all integers a
a**2 % 100 == a**42 % 100 = a**82 % 100 = ...
a**3 % 100 == a**43 % 100 = a**83 % 100 = ...
and so on.
Which means that for N>41 one can reduce the exponent to N=2+(N-2) % 40. (Indeed one can replace 40 by 20 in that reduction.)
And as a final remark that will not have much impact on running times, only on the complexity of the code:
There is a shorter way to implement modexp, this algorithm is also a standard exercise to identify loop invariants:
def modexp(a, n, m):
solution = 1
apower = a
while n:
if (n%2): solution = (solution*apower) % m
n /= 2
apower = (apower*apower) % m
return solution

Find minimum prime numbers which sum to a given value

I want to find the minimum set of prime numbers which would sum to a given value e.g. 9 = 7 + 2 (not 3+3+3).
I have already generated a array of prime numbers using sieve of eratosthens
I am traversing the array in descending order to get the array largest prime number smaller than or equal to given number. This works great if the number is odd.
But fails for even numbers e.g 122 = 113 + 7 + 2 but 122 = 109 +13.
From Golbach's Conjecture we know that any even number can be represented as two sum of two prime numbers. So if a number is even we can directly return 2 as output.
But I am trying to figure out a way other than brute force to find minimum prime numbers.
Although your question didn't say so, I assume you are looking for the set of primes that has the smallest cardinality.
If n is even, then consider the primes p in order, 2, 3, 5, …; eventually n - p will be prime, so n is the sum of two primes. This process typically converges very quickly, with the smaller of the two primes seldom larger than 1000 (and usually much smaller than that).
If n is odd, and n - 2 is prime, then n is the sum of the primes 2 and n - 2.
If n is odd, and n - 2 is not prime, then n - 3 is even and can be written as the sum of two primes, as described above.
Thus you can always find two or three primes that sum to any target n greater than 3.
Try this out!
Not an ideal code but if you want to have a working solution :P
primes = [2,3,5,7]
D = 29
i = -1
sum_ = 0
count = 0
while sum_ != D :
sum_ = sum_ + primes[i]
count += 1
if (sum_ == D) :
break
elif D - sum_ == primes[i-1] :
count += 1
break
elif D - sum_ < ex[i-1] and (D-sum_ not in primes) :
sum_ = sum_ - primes[i]
count = count - 1
i = i - 1
print(count)

finding the digit sum in a arthematic sequence

I have a very simple question. I will be provided with the first term of Arithmetic Progression and the common difference. I am required to give sum of digits of all numbers in between the range of L and R.Here the sum means the sum <10 that means for a number say 157, the sum of digits is 1+5+7=13 which is further 1+3=4. The range is the index of the elements. L means the Lth number of that series and L starts from 1.Here L and R can be of range 1 to 10^18. How can i find the sum of these digits for such a large range. I know the digit sum of a number n can be calculated as (n-1)%9+1. But i can't iterate over 10^18 numbers.
Example: let say First term of Arithmetic Progression is 14 and common difference 7.Then the sum of digits of all numbers between 2 and 4 will be sum of (2+1)=3 and (2+8)=(1+0)=1 and (3+5)=8 which is equal to 12
for pattern finding
current=first;
ll arr[10]={0};
while(1)// search for the pattern
{
ll dsum=(current-1)%9+1;// calculating digit sum
if(arr[dsum]!=0)
break;
arr[dsum]=ptr;// saving the value in the array by using hashing
ptr++;
current+=c_diff;
}
for sum
for(ll i=1;i<ptr;i++)
{
sum[i]=sum[i-1]+new_arr[i];
}
Since all of your numbers will be (ultimately) reduced to a single digit, you must be having repetition after certain number of terms, and, that is maximum of 9. (because 10 digits, but 0 not possible to repeat).
So, lets start with an example. Say, a=14, d=7, l=2, r=50. I've changed the value of r from your example.
So, trying to find repetition:
Our repetition array is q (say). Then, 1st term of q is 5 (since 14 = 5).
Now, next term is 21 (= 3). Since 3 is not equal to 5, we continue.
We find all terms till we get 5 again. So, q will be like this in this example:
q[] = {5,3,1,8,6,4,2,9,7} ... and then we have 5 again, so stop.
So, our repetitive pattern has 9 members. Now, find a cumulative sum array with this, which will be like:
sum[] = {5,8,9,17,23,27,29,38,45}
Now, since r=50, find sum of r terms, which will be:
(floor)(50/9) * 45 + sum[50%9]
= 5 * 45 + 23
= 248
Now, similarly, find sum of l-1 terms, (since you have to find sum in range l..r inclusive.
Sum of 1st (2-1) = 1 terms will be:
(floor)(1/9) * 45 + sum[1 % 9]
= 0 + 5
= 5
So, the answer is, 248 - 5 = 243.
well you can solve this problem by taking two arrays of elements 9 and finding the lth term element.
from the lth term find the digit sum of lth element and save it in two array respectively .
w1=a+(l-1)*d
for(i=1,j=w1;i<=9;j+=d,i++){ if(j%9==0){array1[i]=9 ;array2[i]=9;}else{array1[i]=j%9;array2[i]=j%9;}
}
now q = r-l+1
w= q/9 and e=q%9
array1[i]=array1[i]*w // in loop from i= 1 to 9
in array2[i]=0 //new loop from i=e+1 to 9
now digitsum += array1[i]+array2[i] // from a a loop i=1 to 9 and digitsum is the sum of all digit of sequence
this digit sum is solution.

How to count co-prime to n in a range [1,x] where x can be different from n?

I want to count co-primes of n in a range [1,x]. I have tried using euler phi function but it gives for [1,n].Can anyone suggest a modification to euler phi or any other approach to do this?
I have used phi(n) = n* product of (1-(1/p)) where p is a prime factor of n.
You can use Inclusion-Exclusion Principle
Find the unique prime factors of N (they cannot be more than 10-12, Considering N and X <=10^10).
Now you can find the number of numbers <=x and divisible by 'y' just by dividing. Try all combination of factors of n for y (you will get only 2^10 (1024) in worst case).
Use Inclusion Exclusion now to find the co-primes of n less than x.
The idea is that if a number is not co-prime to n, then it will have
at least one prime factor common with n.
For our example here lets consider X=35 and N=30
First find the unique prime factor of the number. (their number must not be greater than 10-12). Unique Prime factor of N ={2,3,5}.
Find the product of each factor PAIR. {2x3, 2x5, 3x5 or 6, 10, 15}.
Find the product of each factor TRIPLET: { 2x3x5 or 30}.
Repeat until all factors are multiplied together: {N=30 and no more steps are required}.
Find the sum of X divided by each factor from STEP 1: {X=35: (35/2)+(35/3)+(35/5) = (17+11+7)=35}
Find the sum of X divided by each number from STEP 2: {X=35: 35/65+3+2=10}
Find the sum of X divided by each number from STEP 3: {X=35: 1}
Repeat until all results from step 4 are absorbed: {x=35 no more steps are required}
Number of co-primes to N in the range [1..X] = X - step5 + step6 - step7 etc. {N=30, X=35 is given by 35 - 35 + 10 - 1 = 9}.
For N=30, X=60 you will have:
60 - (60/2 + 60/3 + 60/5) + (60/6 + 60/10+ 60/15) - (60/30) = 60 -
(30+20+12) + (10+6+4) - 2 = 60 -62 + 20 - 2 = 16.
Suppose X = 10. N = 6 = 2 * 3.
We have the numbers {1, 2, 3, ..., 10}.
Remove all multiples of 2. You get: {1, 3, 5, 7, 9}.
Remove all multiples of 3. You get: {1, 5, 7}.
How do we count this efficiently? Try answering this question: How many numbers are there in [1, X] that are divisible by p? It's Floor(X/p), right? i.e., p, 2p, ..., kp, where kp <= X. So, from X, we can subtract Floor(X/p),
and you will get the number of numbers that are relatively prime to p in [1, X].
In this example, there are 10 numbers. Number of numbers divisible by 2 is 10/2, which is 5. So, 10-5 = 5 numbers are relatively prime to 2. Similary, there are 10/3=3 numbers which are multiples of 3. So, can we say that there are 5-3=2 numbers that are relatively prime to 2 and 3? No. Because you have double counted! Why? 6 has been included in the count for p = 2 and 3. So we have to account for this by adding multiples of 2 and 3. There is only one multiple of 2 and 3 in [1, 10], which is 6. So, add 1. Which means, the answer is 10 - 5 - 3 + 1 = 3, which is right.
The generalisation of this is the inclusion and exclusion principle. For every n, we are just finding its prime factors, which I know for sure will be less than 10 or so. This is done using the Sieve of Eratosthenes, followed by a prime factorisation. (since X < 10^9, the maximum number of prime factors a number will have is less. Try finding out the product of the first 10 primes. It will be: 6469693230, which is about ~ 64*10^9.(i consider max limit as 10^10. this can be easily extended to big numbers like 10^18.)
i hope this helps !!