Project Euler Python - python

I am working on the Project Euler problems. I am on Problem 1 and for some reason I am getting the wrong answer for it. I don't know if its my math logic that's the problem or if the logic for the code is wrong. Here's the code:
def getSumMult3_5(n):
count = 0
i = 0
i_1 = 0
while i*5 < n:
count += i*5
i += 1
while i_1*3 < n:
count += i_1*3
i_1 += 1
return count
print getSumMult3_5(1000)
It's returning that
count = 266333
but that is not the correct answer. Count should equal 233168. Can anybody help me figure out why it's doing this?
Thanks!

You're double counting numbers that are multiples of both 5 and 3, such as 15.

You are double counting multiples of 15. You can solve this by introducing a third while statement to decrease the count by 1 for each multiple of 15.
I suggest using an if/else statement:
def getSumMult3_5(n):
s = 0
for i in range(1, n+1):
if i%3==0:
s+=i
elif i%5==0:
s+=i
return s
print getSumMult3_5(1000)
This is because that if the number is a multiple of 3, it does not check whether it is a multiple of 5; if it is not a multiple of 3, it checks whether it is a multiple of 5.
I also recommend using s as a variable name because it represents sum, which can't be used as it is a keyword. Count seems to refer to the number of times something occurs.
By only using one variable, and using an if/else statement, execution time will be less and it will be less confusing to read.
Good luck!

Here's my code:
running_sum = 0
for i in range(1,1000):
if i % 3 == 0:
running_sum+=(i)
elif i % 5 == 0:
running_sum+=(i)
print running_sum
You're double-counting numbers like 15 that are multiples of both

Related

Using conditional statements in while loop

I was under the impression that adding the following if statement in my while loop makes python pick only the odd values of i that are smaller than 7 and sums them. However, this is not the case.
Here's my code:
i = 0
sum = 0
while i < 7:
if (i % 2) == 1:
sum += i
i += 1
I expect sum to be 9 but an infinite loop occurs, causing the sum to be infinite.
I can't seem to understand how. Any help is appreciated. Thanks in advance!
You only increment i inside the if, so if the condition is not meant, i stays the same forever
i = 0
sum = 0
while i < 7:
if (i % 2) == 1:
sum += i
i += 1
print(sum)
Output:
9
As you keep conditioning i % 2, but if it doesn't go through, the i never changes, it will always exit the if statement, to solve it:
i = 0
sum = 0
while i < 7:
if (i % 2) == 1:
sum += i
i += 1
print(sum)
You have to unindent by 4 spaces your i += 1 line.
For similar cases it is better to use for loop than while loop. Especially if you have long loops. link
sum = 0
for i in range(7):
if (i % 2) == 1:
sum += i

My Code for Perfect Number

So far, I've learned about for loops, if statements, and counting so it would be great to get feedback using only these topics. I was trying to solve the Perfect Number problem where the divisors excluding the number add up to that number. So for 6, The divisors 1,2,3 add up to 6. I've tried looking at other posts, but I wanted to know why my code specifically isn't working. I've tried solving the problem, and I feel that I'm almost there. I just have one issue. This is what I have so far:
#
num = 30
for i in range(1,num+1):
count = 0
for k in range(1,num+1):
if i%k == 0 and i!=k:
count += k
if count == i:
print(k,'Perfect',i)
#
The output on shell gives me this:
3 Perfect 6
8 Perfect 24
14 Perfect 28
#
I know that 24 is not a perfect number. The highest divisor for 24 excluding 24 should be 12, but I'm getting 8. This is why it's showing me that 24 is perfect. Can anyone clarify why I'm not able to get 12?
You have to count all divisors, before you make a conclusion, your code goes up to 8 for 24, then sums up all divisors so far and declares 24 a perfect number, not waiting for other divisors to appear.
Your code should looks like this:
for i in range(1,num+1):
count = 0
for k in range(1,i): # no point searching for numbers greater than i
if i%k == 0 :
count += k
if count == i:
print('Perfect',i)
and produce:
('Perfect', 6)
('Perfect', 28)
Your problem is that you're checking whether count == i in the wrong place. You need to check after the entire count summation is finished, not after each addition to the count sum.
num = 30
for i in range(1,num+1):
count = 0
for k in range(1,num+1):
if i%k == 0 and i != k:
count += k
if count == i:
print(k,'Perfect',i)
Also, if you want slightly more efficient code, you could do the subtraction afterwards instead of checking each value. Also, as lenik suggested, you only need to count to i (since i can't have any divisors larger than itself.) Even more efficiently, one could just use a Sieve of Eratosthenes-like approach, and count to sqrt(i)+1, finding the corresponding factors along the way:
from math import sqrt
num = 30
for i in range(1,num+1):
count = 0
for k in range(1,sqrt(i) + 1):
if i%k == 0:
count += k
factor = count/k
# The conditional is necessary in case i is a perfect square.
if k != factor:
count += factor
if count - i == i:
print(k,'Perfect',i)
12 is not perfect 1 + 2 + 3+ 4 + 6 != 12
second for also have problem in count (change it to i+1)
and critical problem was las check was in for
num = 30
for i in range(1,num+1):
count = 0
last = 0
for k in range(1,i):
if i%k == 0:
count += k
last = k
if count == i:
print(last,'Perfect',i)
result :
3 Perfect 6
14 Perfect 28

palindromes of sums less than 30, help to optimize my code

On my way of studying Python i stacked on the problem:
I have to count all numbers from 0 to 130000 which are palindromes, but they should be palindromes after sum of the number and its reversed version. For example:
i = 93
93 + 39 = 132
132 + 231 = 363
count_of_palindromes should count all i which are palindromes after 1 or more iterations of summing, but less than 50.
I've already written the code but it's too way difficult to run on my PC, Python stops responding :(
Any advices how to optimize my code?
count_of_palindromes = 0
for i in range(0,130000):
trying = 0
if (i == int(str(i)[::-1])) != True:
trying += 1
sum = i + int(str(i)[::-1])
while trying <= 50:
while (sum == int(str(sum)[::-1])) != True:
trying += 1
sum += int(str(sum)[::-1])
if trying > 0 and trying <= 50:
count_of_palindromes += 1
break
print(count_of_palindromes)
Thank you very much!
Let's tidy your code up a bit first for readability. We'll just take some of the syntax heavy string stuff and encapsulate it.
def reverse(n):
return int(str(n)[::-1])
def is_palindrome(n):
return n == reverse(n)
That's better. I think your problem is the second nested while loop. It runs until it finds a palindrome, then checks if it found it in the first fifty tries. You want it to run up to fifty times, then give up. I think the best way would be a second for loop
count_of_palindromes = 0
for i in range(130000):
for tries in range(50):
if(is_palindrome(i)):
counter += 1
break
else:
i = i + reverse(i)
print(count_of_palindromes)
There are some more ways of speeding this up by avoiding string operations and replacing them with math, but that's overkill for this. I was a little unclear on how your problem wants you to treat natural palindromes, so you may need to modify this solution
I had an error in the code, that made the program almost ifinite :)
The correct code (in my opinion is below)
count_of_palindromes = 0
for i in range(12814):
if (i == int(str(i)[::-1])) != True:
trying = 1
sum = i + int(str(i)[::-1])
while trying <= 50:
while (sum == int(str(sum)[::-1])) != True and trying <=50:
trying += 1
sum += int(str(sum)[::-1])
if trying > 0 and trying <= 50:
count_of_palindromes += 1
break
print(count_of_palindromes)
This solution has a lot of conversions so it may not be the best solution but regardless it is a solution. have a look at this post he has a seemingly much better method of reversing integers without conversion
https://stackoverflow.com/a/3806212/1642546
If you combine my code and that posts code. you probably will have a faster solution, but you must benchmark it to see.
token = 0
for x in range(130000):
reversed = str(x)[::-1]
original = str(x)
sum = int(reversed) + int(original)
if str(sum) == str(sum)[::-1]:
token+=1
print(token)

How do I get my num_digit function to give me the correct output and how do I get it to return any integer value in python?

How do I get my num_digit function to return 1 instead of 0 whenever I put in 0 as the parameter in the function?
How do I get the function to return any integer such as negative numbers?
def num_digits(n):
count = 0
while n:
count = count + 1
n = abs(n) / 10
return count
I was working on question number 2 first. Even if I put the abs(n) in the line of code where while is, I still get an infinite loop which I still do not really understand why. I figured if I can get my n value to always be positive and input in say -24, it would convert it to 24 and still count the number of values.
On question 1, I do not know where to start, ive tried:
def num_digits(n):
count = 0
while n:
if n == 0:
count = count + 1
n = n / 10
return count
I forgot to add I have limited tools to use since I am still learning python. I have gotten up to iterations and am studying the while loops and counters. I have not gotten to break yet although I have an idea of what it does.
When in doubt, brute force is always available:
def num_digits(n):
if n == 0:
return 1
if n < 0:
return num_digits(abs(n))
count = 0
while n:
count = count + 1
n = n / 10
return count
Process the exceptional cases first, and then you only have to deal with the regular ones.
If you want to avoid the conditionals, I suggest taking abs(n) only once, at the beginning, and using an infinite loop + break for the 0 case:
def num_digits(n):
n = abs(n)
count = 0
while True:
count = count + 1
n = n / 10
if n == 0:
break
return count
For a more practical solution, you can either count the number of digits in the string (something like len(str(n)) for positive integers) or taking log base 10, which is a mathematical way of counting digits.
def num_digits(n):
if n == 0:
return 0
return math.floor(math.log10(math.abs(n)))

Enumeration to find Nth prime with Python

I have decided it is about time that i should start learning to code. I have some knowledge of HTML and CSS but i want to be able to develop for iOS. I am aware i have a long way to go, but i aim to get there step by step.
I'm working through the MIT Python course on iTunes U and I am stuck on the homework. I understand the concept of enumeration and testing every possible outcome to find the primes, however what i have tried so far has failed me. My closest attempt is the following.
# counting confirmed primes. For loop should do remainder tests on
# all testNumbers, unless caught by the if statements that rule out
# multiples of 2,3,5,7 to speed things up. divisor increments by one
# on those numbers that do not get pulled by qualifying if statements
testNumber = 2
confirmedPrime = 0
while (confirmedPrime < 1001):
for divisor in range(1, testNumber+1):
if (testNumber/2)*2== testNumber:
testNumber += 1
elif (testNumber/3)*3 == testNumber:
testNumber += 1
elif (testNumber/5)*5 == testNumber:
testNumber += 1
elif (testNumber/7)*7 == testNumber:
testNumber += 1
elif(testNumber%divisor == 0):
testNumber += 1
confirmedPrime +=1
print testNumber
This however doesn't return the "7919" i am expecting but. It returns "7507" So somewhere there are some composites slipping through the net.
I have hunted through this site and not managed to solve it so I thought I would ask.
A few bits are off here, so let's go step by step.
You start by setting initial values, which is perfectly reasonable.
testNumber=2
confirmedPrime = 0
Then you go into a while loop, continuing until the value of the variable confirmedPrime is has reached (i.e. is equal to or bigger than) 1001. I suppose your task is to find the 1000th prime, but doing it like this you're actually finding the 1001st, because the while loop continues until confirmedPrime has the value of 1001. Change it to
while(confirmedPrime < 1000):
You immediately go into another loop, and here comes the first problem, even though it isn't what's giving you the wrong answer.
for divisor in range(1, testNumber+1)
if (testNumber/2)*2 == testNumber:
...
Doing the tests for multipliers of 2, 3, 5 and 7 inside the for loop doesn't make any sense, as you only have to to this once for each value of testNumber. So that part of the testing should be moved out of the for loop.
if (testNumber/2)*2 = testNumber: # Why not use modulo here too for consistency?
testNumber += 1
elif ...
...
else:
for divisor in range(...):
The next part is testing for other, larger divisors. You are testing divisors in the range 1 to testNumber+1. I'm not sure why you're doing this, but it's not a good idea, as your modulo test will always return zero when you come to the second last iteration, testing testNumber%testNumber. So you should change it to testNumber-1, in fact you can stop when you have reached the square root of testNumber, but I'll leave it to you to figure out why.
Now comes the biggest problem:
After the for loop is finished, you increment confirmedPrimes by 1 without actually checking if you found a prime or not. So, incrementing confirmedPrimes should only happen if none of the first tests were true and none of the "divisor tests" turned out to be true.
Rewritten using underscores instead of mixedCase (which is bad python mojo), consistent spacing etc:
import math
test_number = 7 # Already know up to 7
confirmed_primes = 4 # Already know about 2, 3, 5 and 7
while confirmed_primes < 1000:
test_number += 1
if test_number % 2 and test_number % 3 and test_number % 5 and test_number % 7:
is_prime = True
for divisor in range(11, int(math.sqrt(test_number))+1):
if test_number % divisor == 0:
is_prime = False
if is_prime:
confirmed_primes += 1
print test_number
I don't understand exactly how your algorithm is supposed to find a prime number.
A number is said to be prime if it's only divisible by 1 or himself.
Another definition is that a number is said to be prime if it's not divisible by any prime number smaller than it.
This can be the base of your algorithm, speeding up the process by a lot.
def nth_prime(n):
prime_list = []
current = 2
count = 0
while(count < n):
is_prime = True
for prime in prime_list:
if current % prime == 0:
is_prime = False
break
if is_prime:
prime_list.append(current)
count += 1
current += 1
return current - 1
print nth_prime(1000) # => 7919

Categories