program to generate palindromic number - python

import math
thevalue = 0
for x in range (100,999):
for y in range (100,999):
mynum=x*y
mynum_str=str(mynum)
for z in range(0,math.floor(len(mynum_str)/2)):
if mynum_str[0+z] != mynum_str[len(mynum_str)-1-z]:
break
else:
if (len(mynum_str)-1-z) -1 == z:
thevalue = mynum
print(thevalue)
gives me 580085 which is not the correct answer(suppose to be over 900000)...
Working on http://projecteuler.net/problem=4 ... on tips on where I went wrong?

You don't need an overcomplicated loop to check for the palindromic nature of the number:
# Using extended slice notation to reverse the string
if str(n) == str(n)[::-1]:
print "Palindrome!"
As for a complete solution, your program is just looking for a palindromic number. There's more than one palindromic number that's the product of 3 digits. You want the biggest of those.
(of course, this isn't the complete solution -- but it'd be no fun if we just gave you the solution to a project Euler challenge ;) )

There is an easier way to check for a palindrome. Just reverse your string and compare it to the original: if(mynum_str == mynum_str[::-1])
The reason you get 580085 is that your program only prints out the last value that it finds. (There are 2470 possible palindromes.) Try either storing them in a list and sorting it, or just keeping the max version:
import math
import string
maxpalindrome = 0
for x in range (100,999):
for y in range (100,999):
mynum=x*y
mynum_str=str(mynum)
if(mynum_str == mynum_str[::-1]):
maxpalindrome = max(string.atoi(mynum_str), maxpalindrome)
print(maxpalindrome)

Related

What’s wrong with my recursion for finding primes? (Python)

I’m trying to create a program that lists all the primes below an inputted number, and I came up with the code:
def primes():
num = 20
numlist = list(range(1,num+1))
i = len(numlist)
for j in numlist[2:]:
ans = divisible(j,i)
if ans:
numlist.remove(j)
print(numlist)
def divisible(m,n):
if m!=n and m%n==0:
return True
elif n == 1:
return False
else:
divisible(m, n-1)
primes()
(I used an in-browser IDE so the num part was a proxy for the input.)
My idea was to create a separate function divisible() that when inputted two ints, m and n, would check if n divides m. I'm not sure if I was right in my recursion, but I wrote divisible(m,n-1) the idea was that it would iterate through all the integers from n downward and it would return True if any n divided m, or False if it reached 1.
In the main code, m iterated through all the numbers in a list, and n is the total number of elements in the same list. I put the print(numlist) inside the if statement as an error check. The problem I’m having is nothing is printing. The code returned literally nothing. Is there something I’ve missed in how recursion works here?
There's a lot wrong here:
You've made a common beginner's recursion error in that you have a recursive function that returns a value, but when you call it recursively, you ignore the returned value. You need to deal with it or pass it along.
It seems like this modulus is backward:
if ... and m%n==0:
Maybe it should be:
if ... and n % m == 0:
You're code doesn't appear to be calculating primes. It's looks like it's calculating relative primes to n.
You start your list of numbers at 1:
numlist = list(range(1,num+1))
But you start testing at index 2:
for j in numlist[2:]:
Which is the number 3 and you never check the divisibility of the number 2.
Even with all these fixes, I don't feel your algorithm will work.
Your divisible function doesn't return anything if it falls into else part. change it as
def divisible(m, n):
if m!=m and m%n==0:
return True
elif n==1 :
return False
else:
return divisible(m,n-1)
This should work

How to find the max value of a set of randomly generated numbers that is divisible by 7?

I know this might be a very easy question but I can't get my head around it. The question asks to generate 357 random numbers between 8 and 254 (inclusive) and print out the largest generated number that is exactly divisible by 7.
I wrote this program:
import random
def main():
for x in range(357):
print (random.randint(8,254)*7),
print
main()
which generates the numbers but I don't know how to get the max number out of it. I would really appreciate any help 🙏
You could use a list comprehension to generate the random numbers and then apply a filter to only keep those that are divisible by 7:
import random
number = max(filter(lambda n: n % 7 == 0, [random.randint(8,254) for _ in range(357)]))
Concise one-liners are great, but here is an alternative approach that somewhat prioritizes readability for OP's reference. Namely, we save the randomly generated numbers in a list and perform sorting:
import random
def seven_max():
nums = [random.randint(8,254) for _ in range(357)]
nums.sort(reverse=True)
for num in nums:
if num % 7 == 0:
return num
return False # No such number
We first create a list of random numbers, defined as nums. Then, we sort the list in reverse order so that larger elements would come first. As we loop through this sorted array, we check if a number is divisible by 7. If it is, we return that number; if no number satisfies this condition, we return False.
You can use max with parameter key.
max((random.randint(8,254) for _ in range(357)),key =lambda x: x if x%7==0 else -1)
(random.randint(8,254) for _ in range(357)) is generator for producing 357 random values between 8 to 254.
key =lambda x: x if x%7==0 else -1 if number is divisible return it else -1. So, you get highest value that is divisible by 7.

How can I optimize my code to print amicable numbers?

I have tried this following code and it takes a lot of time when I set lower = 0 and upper = 10000
def sumPdivisors(n):
'''This function returns the sum of proper divisors of a number'''
lst = []
for i in range(1,n//2+1):
if n%i == 0:
lst.append(i)
return(sum(lst))
lower = int(input("Enter the lower value of range: "))
upper = int(input("Enter the upper value of range: "))
lst = []
for i in range(lower, upper+1):
if i == 0:
continue
else:
for j in range(i, upper):
if i!=j and sumPdivisors(i) == j and sumPdivisors(j) == i:
lst.append((i,j))
break
print(lst)
There are two things that you could do here.
Memoization
There's already a great explanation of what memoization is elsewhere on this site [link], but here's how it's relevant to your problem:
sumPdivisors is called very frequently in the for-loop at the bottom of your code snippet. For really large inputs n, it will take a long time to run.
sumPdivisors is called with the same input n multiple times.
You can speed things up by saving the result of calling sumPdivisors on different inputs somehow, like in a dictionary that maps integers to the resulting output when you call sumPdivisors with that corresponding integer. This is kind of what memoization is. You're precomputing the possible outputs of sumPdivisors and storing them for later. Read the link for a more in-depth explanation.
Don't add the numbers in sumPdivisors to a list
You can just add these numbers as you iterate instead of appending them to a list, then summing them. This change won't have as great of an impact as adding memoization to your code.

How to compare words in two lists according to same order in python?(I have def a function)

Recently, I def a function which can compare two words in each wordlist. However, I also found some problems here.
def printcorrectletters():
x=0
for letters in correctanswer:
for letters2 in userinput:
if letters == letters2:
x = x+1
break
return x
In this function, if the correctanswer='HUNTING', and I input 'GHUNTIN', it will show 6 letters are correct. However, I want it compare words' letters 1 by 1. So, it should march 0. For example, 'H' will match first letter of userinput.. and so on.
I also think another function which can solve it by using 'zip'. However, our TA ask me to finish it without things like 'zip'.
If the strings are different lengths, you want to compare each letter of the shorter string:
shortest_length = min(len(correctanswer), len(userinput))
min just gives you the minimum of two or more values. You could code it yourself as:
def min(a, b):
return a if a < b else b
You can index a character in a string, using [index]:
>>> 'Guanfong'[3]
n
So you can loop over all the letter indices:
correct = 0
for index in range(shortest_length):
if correctanswer[index] == userinput[index]:
correct += 1
If you did use zip and sum:
correct = sum(1 for (correct_char, user_char) in zip(correctanswer, userinput)
if correct_char == user_char)
Python provides great facilities for simplifying ideas and for communicating with the computer and programmers (including yourself, tomorrow).
Without zip you can use enumerate() to loop over elements of correctanswer , and get index and element at the same time. Example -
def printcorrectletters():
x=0
for i, letter in enumerate(correctanswer):
if i < len(userinput) and letter == userinput[i]:
x = x+1
return x
Or if even enumerate() is not allowed, simply use range() loop till len(correctanswer) and get elements from each index.

How to tell if item in list contains certain characters

I have a script that creates a list of numbers, and i want to remove all numbers from the list that are not whole numbers (i.e have anything other than zero after the decimal point) however python creates lists where even whole numbers get .0 put on the end, and as a result i cant tell them apart from numbers with anything else. I can't use the int() function as it would apply to all of them and make them all integers, and then i'd lose the ones that originally were.
Here is my code:
z = 300
mylist = []
while(z > 1):
z = z - 1
x = 600851475143 / z
mylist.append(x)
print(mylist)
[y for y in mylist if y #insert rule to tell if it contains .0 here]
the first bit just divides 600851475143 by every number between 300 and 1 in turn. I then need to filter this list to get only the ones that are whole numbers. I have a filter in place, but where the comment is i need a rule that will tell if the particular value in the list has .0
Any way this can be achieved?
You're performing an integer division, so your results will all be integers anyway.
Even if you'd divide by float(z) instead, you'd run the risk of getting rounding errors, so checking for .0 wouldn't be a good idea anyway.
Maybe what you want is
if 600851475143 % z == 0:
mylist.append(600851475143/z)
It's called the "modulo operator", cf. http://docs.python.org/reference/expressions.html#binary-arithmetic-operations
EDIT: Ralph is right, I didn't put the division result into the list. Now it looks ugly, due to the repetition of the division ... :) gnibbler's answer is probably preferable, or Ralph's.
You can use divmod() and only put the result of an "even divide" in to
your list:
z = 300
mylist = []
while(z > 1):
z = z - 1
x,y = divmod(600851475143, z)
if y==0:
mylist.append(x)
print(mylist)
You can use int() - just not the way you were thinking of perhaps
z = 300
mylist = []
while(z > 1):
z = z - 1
x = 600851475143 / z
mylist.append(x)
print(mylist)
[y for y in mylist if y==int(y)]
Use regular expressions to match what you need. In your case, it should be check for ".0" at the end of the string, thus re.search("\.0$", y). Please be aware that you should use re.search, because re.match checks only for match at the beginning of the string.
Edit: sorry, I was disappointed with
however python creates lists where
even whole numbers get .0
and thought that you are making it list of strings. jellybean gave you the answer.
jellybean's answer is quite good, so I'd summarise:
magic_num = 600851475143
filtered_list = [magic_num/i for i in range(300,0,-1) if magic_num%i == 0]
(the division operator should be integer //, but the code coloriser interprets it as a comment, so I've left the single slash)

Categories