The purpose of this code is to find the smallest semiprime \$s = a b\$ satisfying a bunch of conditions stated in the Math.SE question What is the smallest "prime" semiprime?. The conditions are:
- \$a\$, \$b\$ are prime numbers,
- the reversal of \$s = a b\$ is a prime number,
- both concatenations of \$a\$ and \$b\$ are prime numbers,
- all six concatenations of \$a\$, \$b\$, \$s\$ are prime numbers.
The code assumes that there is at least one solution \$s \le 140000000000\$ (this is known from an earlier search) and finds the smallest solution. The code uses the simplification \$a \equiv b \equiv 5 \pmod{6}\$, \$11 \le a < b\$, which is derived in this Math.SE answer. The library sympy is used for primality testing; search took several hours, and I'm interested how can this code be optimised; any other feedback is welcome too.
import sympy
M = 140000000000 # current upper bound on s = a * b
a_choices = [ 11, ] # growing sorted list of primes
b = 17
while 11 * b <= M: # b increases, M doesn't increase
repr_b = str(b)
# try all prime a such that 11 <= a < b and a * b <= M
for a in a_choices:
if a * b > M:
break
repr_a = str(a)
# both concatenations of a, b must be prime numbers
repr_ab = repr_a + repr_b
repr_ba = repr_b + repr_a
if sympy.isprime(int(repr_ab)) and sympy.isprime(int(repr_ba)):
s = a * b
repr_s = str(s)
# the reversal of s = a * b must be a prime number
if sympy.isprime(int(''.join(reversed(repr_s)))):
# all concatenations of a, b, s must be prime numbers
if ( sympy.isprime(int(repr_s + repr_ab)) and
sympy.isprime(int(repr_s + repr_ba)) and
sympy.isprime(int(repr_ab + repr_s)) and
sympy.isprime(int(repr_ba + repr_s)) and
sympy.isprime(int(repr_a + repr_s + repr_b)) and
sympy.isprime(int(repr_b + repr_s + repr_a)) ):
# output a result and update the upper bound
M = s
print('found {} = {} * {}'.format(s, a, b))
# find the next prime b = 5 (mod 6), and (if needed) append the previous prime b to a_choices
b_old = b
b += 6
while not sympy.isprime(b):
b += 6
if b_old * b <= M:
a_choices.append(b_old)
# report the smallest solution
print('smallest solution: {} = {}'.format(
M, ' * '.join(map(str, sympy.factorint(M, multiple = True)))))
The output was:
found 137800963117 = 42299 * 3257783
smallest solution: 137800963117 = 42299 * 3257783
The answer by toolic suggests it would be helpful to add a comment explaining the line b = 17. I do not edit the above code to not invalidate answers; the loop on \$b\$ begins with 17 since 17 is the next prime \$\equiv 5\pmod 6\$ after 11.