Palindromic Primes without 11
Python 2, 76 73 72 70 69 68 bytes
n=input();c=k=m=11
while n:m*=k/c;k+=c;n-=`k`==`k`[::~m%k-c]
print k
Thanks to @WheatWizard for golfing off 3 bytes!
Thanks to @ØrjanJohansen for golfing off 1 byte!
Thanks to @xnor and @ØrjanJohansen for paving the way to 68 bytes!
Input is 0-indexed. Try it online! or verify the first 31 test cases.
Background
Recall that Wilson's theorem states that for all integers p > 1,
meaning that (p - 1)! + 1 is evenly divisible by p if and only if p is prime.
If p > 1 is not prime, it is composite; let q be the smallest prime divisor of p. Clearly, q ≤ p/q. There are two cases:
If q = p/q, we have that p = q².
If q = 2, (p - 1)! = 3! = 6, so (p - 1)! is congruent to 2 modulo p.
If p/q = q > 2, so 2q < p. This way, q and 2q are both among 1, …, p - 1, whose product is the factorial of p - 1, so 2p = 2q² = q · 2q divides (p - 1)! evenly.
If q < p/q, q and p/q are both among 1, …, p - 1, so p = q · p/q divides (p - 1)! evenly.
Summing up,
for all integers p > 1.
Now, for all integer congruences and all integers a, b, and c, the following holds.
When a = -1, b = 11, and c = -1, we follow that
and, since 21 and -23 are congruent modulo 44 and -1 and 11p-1 are congruent modulo 11p, we arrive at the following conclusion.
For all possible values of p, the outcome (11, 21, or 11p - 1) will fall in the range 0, …, 11p - 1, so these values match those that will be returned by Python's %
operator.
How it works
We initialize c, k, and m to 11 after the saving the input in n. c will be constant for the remainder of the program. Since there are three occurrences of c on the following line and assigning c costs only two bytes, this saves a byte. k can be thought of 11p using the meaning of p from the previous paragraph; initially, k = 11 = 11 · 1!. m takes the place of 11 · (p - 1)!; initially, m = 11 = 11 · 0!. k and m will satisfy the relationship m = 11 · (k/11)! at all times.
n represents the number of “Stephen's palindromes” we have to find. Since k = 11 initially, we can output k verbatim without further computation. However, when n is positive, we enter the while loop. The loop begins by multiplying m by k/c = p, then adding 11 to k, thus incrementing p. If k is a member of the sequence, we subtract 1 from n and start over. Once n reaches 0, we found the sequence member at the desired index and break out of the loop, then print the last value of k.
The expression
`k`==`k`[::~m%k-c]
performs the actual test, and it's result (True / 1 for sequence members, 0 / False otherwise) is subtracted from n. As seen before, ~m % k = (-m - 1) % k = (-11 · (p - 1)! - 1) % 11p equals 10 if p is prime, 21 if p = 4, and 11p - 1 > 43 if p > 4 is composite. Thus, after subtracting c = 11, we're left with -1 for prime p and a positive integer larger than 9 otherwise.
For prime p, `k`[::-1]
gives us the string representation of k with reversed digit order, so comparing it to `k`
checks whether k is a palindrome. If it is, all conditions are fulfilled and k is a sequence member. However, if p is not prime, the large range step and the fact that k will always have more than one digit mean that `k`[::-1]
cannot have the same number of digits as `k`
, let alone be equal to it.
Jelly, 18 13 bytes
ṬÆẸש11ŒḂµ#ṛ®
For some reason, this is much slower than my initial revision, despite doing exactly the same.
Try it online!
N = 127
dennis-home:~$ time jelly eun 'ṬÆẸש11ŒḂµ#ṛ®' <<< 127
997799
real 1m43.745s
user 1m43.676s
sys 0m0.113s
How it works
ṬÆẸש11ŒḂµ#ṛ® Main link. No arguments.
µ Combine all links to the left into a chain.
# Read an integer n from STDIN and call the chain monadically, with
argument k = 0, 1, 2, ... until n values of k result in a truthy
output. Return the array of all matching values of k.
Ṭ Untruth; yield [0, 0, 0, ..., 1] (k-1 zeroes followed by a 1) or
[] if k = 0.
ÆẸ Unexponents; consider the resulting array as exponents of the
sequence of primes and yield the corresponding integer. For k = 0,
this yields 1. For k > 0, it yields the k-th prime.
ש11 Multiply the result by 11 and copy the product to the register.
ŒḂ Test if the product is a palindrome.
ṛ® Replace the resulting array with the integer in the register.
Brachylog, 17 bytes
:I{11|ṗ×₁₁≜.↔}ᶠ⁽t
Try it online!
This is 1-indexed.
Explanation
:I{ }ᶠ⁽t Find the Input'th result of the following:
11 Output = 11
| Or
≜. Output is an integer…
ṗ×₁₁ …which is the result of multiplying a prime by 11…
.↔ …and Output reversed is still the Output
Two realizations with this answer:
- I need to fix the fact that superscript passing to metapredicates (with
⁽
) does not work if there is no input to pass (which is why I have to add:I
). - I need to add a metapredicate to get the
N
th result of a predicate (which would avoid usingᶠ⁽t
and instead e.g.ⁿ⁽
).
Implementing both changes would make that answer 14 bytes.