# Euler Problem 35¶

The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.

There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.

How many circular primes are there below one million?

First we get all primes into a look-up table. Then we iterate them and check whether they are circular.

In [1]:

    def get_primes_smaller(number):
        primes = []
        prospects = [n for n in range(2, number)]
        while prospects:
            p = prospects[0]
            prospects = [x for x in prospects if x % p != 0]
            primes.append(p)
            if p * p > number:
                return primes + prospects
        return primes

    ps = get_primes_smaller(1000000)

In [2]:

    def get_combinations(xs):
        if not xs:
            return []
        rs = []
        for i in range(len(xs)):
            yss = get_combinations(xs[:i] + xs[i + 1:])
            if not yss:
                rs.append(xs[i])
            for ys in yss:
                rs.append(xs[i] + ys)
        return rs

    assert(get_combinations("ab") == ["ab", "ba"])

In [3]:

    from itertools import permutations
    prime_set = set(ps)

    def is_circular(p):
        cs = permutations(str(p))
        for c in cs:
            if not int("".join(c)) in prime_set:
                return False
        return True

    assert(is_circular("2") == True)
    assert(is_circular("11") == True)
    assert(is_circular("47") == False)

In [4]:

    s = len([p for p in ps if is_circular(p)])
    print("False solution {}".format(s))

    False solution 22

We did not read the problem properly. Cycles are obviously not the same as permutations. If we change that we should get the solution in no time.

In [5]:

    def cyles(xs):
        if len(xs) <= 1:
            return xs
        return [xs[i:] + xs[:i]  for i in range(len(xs))]

    prime_set = set(ps)

    def is_circular(p):
        cs = cyles(str(p))
        for c in cs:
            if not int("".join(c)) in prime_set:
                return False
        return True

In [6]:

    s = len([p for p in ps if is_circular(p)])
    s

Out[6]:

    55