1

My task is this:

What is the only (double-digit, or above) Prime number that is palindromic in both base-2 (binary), and base-10 (decimal) instances?

Whenever I run this code nothing happens, and it acts like an infinite loop. What am I doing wrong, or how can I improve? Many thanks in advance.

def isPrime(n):
    if type(n) != int or n <= 1:
        return False
    elif n == 2:
        return True
    elif n%2 == 0:
        return False
    else:
        for x in range(2, int(n**0.5)+1):
            if n%x == 0:
                return False
                break
        return True
def isPalindrome(x):
    num = str(x)[::-1]
    if str(x) == num:
        return True
    else:
        return False
while True:
    a = 11
    if isPrime(a) and isPalindrome(a) == True:
        if isPalindrome(bin(a)) == True:
            print a
            break
    else:
        a+=2
        print a

--------- Edit: **SOLVED** ---------

Revised code:

def isPrime(n):
    if n < 2 or n%2 == 0:
        return False
    if n == 2:
        return True
    else:
        for x in range(3, int(n**0.5)+1, 2):
            if n%x == 0:
                return False
        return True
def isPalindrome(x):
    num = str(x)[::-1]
    return str(x) == num
a = 11
while True:
    if isPrime(a) and isPalindrome(a) and isPalindrome(format(a, "b")):
            print a
            break
    a+=2

Thank you to all who contributed answers.

dcgoss
  • 2,147
  • 3
  • 20
  • 31
  • the `break` after `return` is redundant, as return already return the function value and the for finish – Ruben Bermudez Apr 12 '14 at 14:43
  • does it print the value of "a" or is there no output at all? – Sirac Apr 12 '14 at 14:44
  • 2
    Unrelated, from [PEP 8](http://legacy.python.org/dev/peps/pep-0008/): Use `isinstance(obj, int)` to check if `obj` is an Integer and remove `== True`. – Stefan Apr 12 '14 at 14:49
  • *forehead smack* Never even thought about that. Thank you! @RubenBermudez – dcgoss Apr 12 '14 at 15:11
  • I believe it should print "a" after it passes both if statements in the while loop. It also should print "a" even if it doesn't pass, so I can see its progress. @Sirac – dcgoss Apr 12 '14 at 15:12
  • Noted. You learn something every day! @Stefan – dcgoss Apr 12 '14 at 15:14

1 Answers1

7

The output of bin() is never a palindrome, because the characters 0b are prepended to it:

>>> bin(3)
'0b11'
>>> isPalindrome(bin(3))
False

Either slice those two characters of, or use format() to produce a binary representation:

>>> format(3, 'b')
'11'
>>> isPalindrome(format(3, 'b'))
True

Your loop has another problem: it won't increment if you found a palindromic prime that is not a palindromic prime in base 2:

if isPrime(a) and isPalindrome(a) == True:
    if isPalindrome(format(a, 'b')) == True:
        print a
        break
    # no else here
else:
    a+=2
    print a

Just test for all conditions in one test:

if isPrime(a) and isPalindrome(a) and isPalindrome(format(a, 'b')):
    print a
    break
a += 2

There is rarely a need to test for == True in a boolean test.

Next is that you reset a in the loop:

while True:
    a = 11

It doesn't matter what you do to a in the rest of the loop, at the top it goes back to 11. Move that out of the loop:

a = 11
while True:
    if isPrime(a) and isPalindrome(a) and isPalindrome(format(a, 'b')):
        print a
        break
    a += 2

Whenever you write if comparison: return True followed by else: return False, just return the test instead:

def isPalindrome(x):
    num = str(x)[::-1]
    return str(x) == num

because the == comparison operator already returns a boolean value.

Your primality test doesn't need to test for the type of n, really (you only ever pass in integers), but the correct way to test for a type is to use:

isinstance(n, int)

as this allows for subclasses of int too. Even if you do need to limit something to a very specific type and cannot allow for subclasses, you'd use:

type(n) is int

as types are singletons.

Taking advice from isPrime Function for Python Language your isPrime() function would be a little faster if you used:

def isPrime2(n):
    if n < 2: return False
    if n == 2: return True
    for i in range(3, int(n ** 0.5) + 1, 2):   # only odd numbers
        if n % i == 0:
            return False
    return True

instead.

Your loop could be made more efficient by limiting the number of values you look at. If you look at the Palindronic Prime series on the OEIS you'll see that apart from 11, all base-10 palindromic primes have an odd number of digits, so you can skip large swathes of numbers. The following would produce better candidates:

def palindromic_candidates():
    yield 11
    outer = 1
    while True:
        for i in range(10):
            yield int('{}{}{}'.format(outer, i, str(outer)[::-1]))
        outer += 1

Demo:

>>> from itertools import islice
>>> pc = palindromic_candidates()
>>> list(islice(pc, 30))
[11, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383]
>>> list(islice(pc, 100, 130))
[13931, 14041, 14141, 14241, 14341, 14441, 14541, 14641, 14741, 14841, 14941, 15051, 15151, 15251, 15351, 15451, 15551, 15651, 15751, 15851, 15951, 16061, 16161, 16261, 16361, 16461, 16561, 16661, 16761, 16861]

Use this instead of your while True loop, remove the a += 2 line:

for a in palindromic_candidates():
    if isPrime(a) and isPalindrome(format(a, 'b')):
        print a
        break

where you can drop the test for base-10 palindromes as the generator produces only palindromes.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • With the `a=11` inside the while loop, it is always checked if number `11` is prime, palindrome and palindrome in binary. And if it isn't `13` is printing and check again for `11`. `a=11` should be outside the while loop. – Ruben Bermudez Apr 12 '14 at 14:53
  • @MartijnPieters You've used the site longer than me, would a question like this (where there are many, many things to address) be considered off-topic? – anon582847382 Apr 12 '14 at 14:57
  • @AlexThornton: Not really; the OP isn't asking multiple questions here. There is just more than one problem to address that they weren't aware of. – Martijn Pieters Apr 12 '14 at 14:58
  • @MartijnPieters Wow - was unaware I had so many problems! Being the unexperienced 14 year old that I am that should have been expected. Thank you for taking the time to type out such a clear and detailed response, it was very helpful. Will post finished code for the heck of it. – dcgoss Apr 12 '14 at 15:39