The idea is that we simply count from 0
to 10**k
, and consider each of these "integers" as a palindrome sequence. We left pad with 0
where necessary. So, for k==6
, 0 -> [0, 0, 0, 0, 0, 0]
, 1 -> [0, 0, 0, 0, 0, 1]
, etc. This enumerates over all possible combinations. If it's a palindrome, we also check that it adds up to n
.
Below is some code that (should) give a correct result for arbitrary n
and k
, but is not terribly efficient. I'll leave optimizing up to you (if it's necessary), and give some tips on how to do it.
Here's the code:
def find_all_palindromic_sequences(n, k):
result = []
for i in range(10**k):
paly = gen_palindrome(i, k, n)
if paly is not None:
result.append(paly)
return result
def gen_palindrome(i, k, n):
i_padded = str(i).zfill(k)
i_digits = [int(digit) for digit in i_padded]
if i_digits == i_digits[::-1] and sum(i_digits) == n:
return i_digits
to test it, we can do:
for paly in find_all_palindromic_sequences(n=16, k=6):
print(paly)
this outputs:
[0, 0, 8, 8, 0, 0]
[0, 1, 7, 7, 1, 0]
[0, 2, 6, 6, 2, 0]
[0, 3, 5, 5, 3, 0]
[0, 4, 4, 4, 4, 0]
[0, 5, 3, 3, 5, 0]
[0, 6, 2, 2, 6, 0]
[0, 7, 1, 1, 7, 0]
[0, 8, 0, 0, 8, 0]
[1, 0, 7, 7, 0, 1]
[1, 1, 6, 6, 1, 1]
[1, 2, 5, 5, 2, 1]
[1, 3, 4, 4, 3, 1]
[1, 4, 3, 3, 4, 1]
[1, 5, 2, 2, 5, 1]
[1, 6, 1, 1, 6, 1]
[1, 7, 0, 0, 7, 1]
[2, 0, 6, 6, 0, 2]
[2, 1, 5, 5, 1, 2]
[2, 2, 4, 4, 2, 2]
[2, 3, 3, 3, 3, 2]
[2, 4, 2, 2, 4, 2]
[2, 5, 1, 1, 5, 2]
[2, 6, 0, 0, 6, 2]
[3, 0, 5, 5, 0, 3]
[3, 1, 4, 4, 1, 3]
[3, 2, 3, 3, 2, 3]
[3, 3, 2, 2, 3, 3]
[3, 4, 1, 1, 4, 3]
[3, 5, 0, 0, 5, 3]
[4, 0, 4, 4, 0, 4]
[4, 1, 3, 3, 1, 4]
[4, 2, 2, 2, 2, 4]
[4, 3, 1, 1, 3, 4]
[4, 4, 0, 0, 4, 4]
[5, 0, 3, 3, 0, 5]
[5, 1, 2, 2, 1, 5]
[5, 2, 1, 1, 2, 5]
[5, 3, 0, 0, 3, 5]
[6, 0, 2, 2, 0, 6]
[6, 1, 1, 1, 1, 6]
[6, 2, 0, 0, 2, 6]
[7, 0, 1, 1, 0, 7]
[7, 1, 0, 0, 1, 7]
[8, 0, 0, 0, 0, 8]
Which looks similar to your result, plus the results that contain 0
.
Ideas for making it faster (this will slow down a lot as k
becomes large):
This is an embarrassingly parallel problem, consider multithreading/multiprocessing.
The palindrome check of i_digits == i_digits[::-1]
isn't as efficient as it could be (both in terms of memory and CPU). Having a pointer at the start and end, and traversing characters one by one till the pointers cross would be better.
There are some conditional optimizations you can do on certain values of n
. For instance, if n
is 0
, it doesn't matter how large k
is, the only palindrome will be [0, 0, 0, ..., 0, 0]
. As another example, if n
is 8
, we obviously don't have to generate any permutations with 9
in them. Or, if n
is 20
, and k
is 6
, then we can't have 3
9
's in our permutation. Generalizing this pattern will pay off big assuming n
is reasonably small. It works the other way, too, actually. If n
is large, then there is a limit to the number of 0
s and 1
s that can be in each permutation.
There is probably a better way of generating palindromes than testing every single integer. For example, if we know that integer X is a palindrome sequence, then X+1 will not be. It's pretty easy to show this: the first and last digits can't match for X+1 since we know they must have matched for X. You might be able to show that X+2 and X+3 cannot be palindromes either, etc. If you can generalize where you must test for a new palindrome, this will be key. A number theorist could help more in this regard.
HTH.