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

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)

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

Why is my code running infinitely?

this is an even odd calculator that runs infinitely without any errors. Does anyone know how to fix this? Is it ok for me to call the method with the input from times?
def calc(time):
i = 1
while i <= time:
num = int(input("Enter your number"))
i + 1
x=0
y=0
if (int(num) % 2 == 0):
even = True
print("even")
elif (int(num) % 2 != 0):
odd = True
print("odd")
if (odd == True):
x += 1
elif (even == True):
y += 1
times = int(input("How many numbers will you be putting in this calc?"))
calc(times)
Just a few things you have wrong, the rest are pretty good, explain are in the comments:
All the variables in [x, y , even , odd] are useless at all, so that's why I erased them.
def calc(time):
i = 1
while i <= time:
num = int(input("Enter your number"))
i+=1 # important thing here, to update the value the symbol is +=, not just +
if (int(num) % 2 == 0):
print("even")
else: # there is no need of elif, if the number is not even, by definition, it is odd
print("odd")
times = int(input("How many numbers will you be putting in this calc?"))
calc(times)
you can try it here, and see how do correctly the job :) -> https://repl.it/Nm70/0
Line number 5 should be i = i+1
I'm assuming you have a formatting issue with stackoverflow and not a formatting issue with your actual code. The lines after your while loop need to be indented which I'm assuming you are doing. The problem you have is that you aren't incrementing i. The first line after your input you have i + 1. That does nothing as you aren't assigning it to anything. You have x += 1 and y += 1 later on in your code which increments and assigns. So basically change your i+1 line to be i += 1 or i = i + 1
Everything that you want in the while loop needs to be indented by one "tab" like so:
while i <= time:
#Code goes here

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)))

Project Euler 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

Division by values in a dictionary (Python)

I am building a prime generator (I know, another one and probably not a very good one at that, but that is for another question.) I am using a dictionary for my collection of primes and ignoring composites by dividing by the previous primes. However it doesn't seem to be iterating properly in the final stage of the function and I get a number of incorrect results. isWhole is a self explanatory call to another function. This is my code where x = the number of primes to be generated:
def prime_generator(x):
count = 2
counter = 2
p = {1: 2}
while len(p) <= x:
if count % 2 == 0:
count += 1
continue
test1 = (math.sqrt(count))
if isWhole(test1) == True:
count += 1
continue
for k, a in p.items():
if count % a == 0:
break
else:
p[ counter ] = count
counter += 1
break
count += 1
return p
Your design intent is not entirely clear, but you may be intending to have the else clause apply to the for loop rather than the if statement. Try un-indenting the entire else clause so that it only runs if the loop terminates without hitting a break.

Categories