Generating numbers palindromic in two number bases

Here are some further ideas:

b1 = 3;
b2 = 4;
d = 3;
a = Flatten[Outer[
    List,
    Range[1, b1 - 1],
    Sequence @@ ConstantArray[Range[0, b1 - 1], d - 1]
    ], d - 1];
b1digits = a[[All, Join[Range[d], Reverse[Range[1, d - 1]]]]];
candidates = FromDigits[#, b1] & /@ b1digits;
b2digits = IntegerDigits[candidates, b2];
palindomes = Pick[n, PalindromeQ /@ IntegerDigits[candidates, b2]]
IntegerDigits[palindomes, b1]
IntegerDigits[palindomes, b2]

{130}

{{1, 1, 2, 1, 1}}

{{2, 0, 0, 2}}


(This is a self-answer after discovering I can use Reduce directly.)



The previous answer gives ideas related to your approach of iterating palindromes.

Here, I present a way to directly compute them instead.


Directly computing $2,3$-palindromes

"...whether there is a way to do this computation faster?"

Rather than brute-force checking palindromes, you can directly solve for them, for individual $b$ values, via Reduce and the corresponding system.

I've implemented get2Palindromes and get3Palindromes for getting palindromes in $b,b-1$ and $b,b-1,b-2$ respectively, using the system from the linked post. (Full code included at the end of this post.)

Since the title is referring to 2-palindromes, here is a sample input:

Do[Print["d = ", 3, ", base: ", base, "; ", Timing[get2Palindromes[3, base]]];, {base, 2, 10}]

And sample output for it:

d = 3, base: 2; {0.015625,{}}
d = 3, base: 3; {0.03125,{}}
d = 3, base: 4; {0.03125,{}}
d = 3, base: 5; {0.046875,{46}}
d = 3, base: 6; {0.0625,{67,98,104}}
d = 3, base: 7; {0.078125,{92,135,178,185}}
d = 3, base: 8; {0.09375,{121,178,235,292,300}}
d = 3, base: 9; {0.09375,{154,227,300,373,446,455}}
d = 3, base: 10; {0.09375,{191,282,373,464,555,646,656}}

If you want to display their palindromic digits, I've also implemented:

getDigits[n_, b_, k_] := 
  MatrixForm[Table[IntegerDigits[n, b - i], {i, 0, k - 1}]];

Which can be used like: getDigits[#, base, 2] & /@ on the palindrome output:

Do[Print["d = ", 3, ", base: ", base, "; ", Timing[getDigits[#, base, 2] & /@ get2Palindromes[3, base]]];, {base, 2, 10}]

Which gives a output in terms of base digits:

enter image description here


Note that Reduce will get very slow quickly for larger $d$. - This is still much faster than doing a brute force search over all palindromes, especially for large $b$. The only exceptions might be very small $b$ in combination with very large $d$, where brute-force might be faster than Reduce.

Here is the code:

(* Helper functions for representations *)
ClearAll[d, palindromePolynom, a, x, baseCoefficients, baseBorrowings,
   b, o, h];
palindromePolynom[d_, x_: x, c_: a] := 
  Sum[a[i + 1] x^i, {i, 0, (d - 1)/2}] + 
   Sum[a[d - i] x^i, {i, (d - 1)/2 + 1, d - 1}];
baseCoefficients[d_, k_: 0] := 
  Reverse[CoefficientList[palindromePolynom[d, x - k], x]];
baseBorrowings[d_, k_: 0, var_: o, 
   b_] := +Join[
    Join[{var[1]}, 
     Table[var[i + 1] - var[i] (b + k), {i, 1, 
       d - 2}]], {-var[d - 1] (b + k)}];

(* base b-1,b-2 representations digits parameterized by o,h *)
ClearAll[coefX, coefA, coefB];
coefX[d_, k_: 0, var_, b_] := 
  baseCoefficients[d, k] + baseBorrowings[d, k, var, b];
coefA[d_, b_, k_: - 1, var_: o] := coefX[d, k, var, b];
coefB[d_, b_, k_: - 2, var_: h] := coefX[d, k, var, b];

(* helper functions for conditions *)
ClearAll[varList, varConds, geCond];
varList[var_, n_] := Table[var[i], {i, 1, n}];
varConds[var_, n_, cond_, c_: 0] := 
  Fold[And, Table[cond[var[i], c], {i, 1, n}]];
geCond[d_, var_, c_: 0] := varConds[var, d, GreaterEqual, c];

(* conditions on digits, bases and parameters *)
ClearAll[paramVars, paramVarsA, paramVarsB, paramVars2, paramVars3, 
  paramConds2, paramConds3, baseConds, baseCondsA, baseCondsB, 
  baseConds2, baseConds3, palCondsA, palCondsB, palConds3];
paramVars[d_] := varList[a, (d + 1)/2];
paramVarsA[d_] := varList[o, d - 1];
paramVarsB[d_] := varList[h, d - 1];
paramVars2[d_] := Join[paramVars[d], paramVarsA[d]];
paramVars3[d_] := Join[paramVars[d], paramVarsA[d], paramVarsB[d]];
paramConds2[d_] := 
  geCond[(d + 1)/2, a] && geCond[d - 1, o] && a[1] >= 1 ;
paramConds3[d_] := 
  geCond[(d + 1)/2, a] && geCond[d - 1, o] && geCond[d - 1, h] && 
   a[1] >= 1;
baseConds[d_, b_] :=  Fold[And, Table[a[i] < b, {i, 1, (d + 1)/2}]];
baseCondsA[d_, b_] :=  
  Fold[And, Table[0 <= coefA[d, b][[i]] < b - 1, {i, 1, d}]] &&  
   coefA[d, b][[1]] >= 1 && coefA[d, b][[d]] >= 1;
baseCondsB[d_, b_] :=  
  Fold[And, Table[0 <= coefB[d, b][[i]] < b - 2, {i, 1, d}]] && 
   coefB[d, b][[1]] >= 1 && coefB[d, b][[d]] >= 1;
baseConds2[d_, b_] :=  baseConds[d, b] && baseCondsA[d, b];
baseConds3[d_, b_] :=  
  baseConds[d, b] && baseCondsA[d, b] && baseCondsB[d, b];
palCondsA[d_, b_] := 
  Fold[And, 
   Table[coefA[d, b][[i]] == coefA[d, b][[d - i + 1]], {i, 
     1, (d + 2)/2 - 1}]] ;
palCondsB[d_, b_] := 
  Fold[And, 
   Table[coefB[d, b][[i]] == coefB[d, b][[d - i + 1]], {i, 
     1, (d + 2)/2 - 1}]];
palConds3[d_, b_] := palCondsA[d, b] && palCondsB[d, b];

(* solving representations under conditions via Reduce *)
ClearAll[reduce2P, reduce3P];
reduce2P[d_, b_, conds_: True] := 
  Reduce[conds && paramConds2[d] && baseConds2[d, b] && 
    palCondsA[d, b], paramVars2[d], Integers];
reduce3P[d_, b_, conds_: True] := 
  Reduce[conds && paramConds3[d] && baseConds3[d, b] && 
    palConds3[d, b], paramVars3[d], Integers];

(* printing out solutions nicely from Reduce results *)
ClearAll[expandBase, extract2, get2Palindromes, extract3, 
  get3Palindromes, getDigits];
expandBase[digs_, base_] := 
  Sum[digs[[i]]*base^(Length[digs] - i), {i, 1, Length[digs]}];
extract2[d_, b_, cond_] := 
  Flatten[expandBase[coefA[d, b], b - 1] /. 
    Delete[FindInstance[#, 
        paramVars2[d]] & /@ (List @@ (cond || a[1] == 1)), -1]];
extract3[d_, b_, cond_] := 
  Flatten[expandBase[coefA[d, b], b - 1] /. 
    Delete[FindInstance[#, 
        paramVars3[d]] & /@ (List @@ (cond || a[1] == 1)), -1]];
get2Palindromes[d_, b_] := 
  Module[{r}, r = reduce2P[d, b]; If[r == False, Return[{}]]; 
   Return[extract2[d, b, r]]];
get3Palindromes[d_, b_] := 
  Module[{r}, r = reduce3P[d, b]; If[r == False, Return[{}]]; 
   Return[extract3[d, b, r]]];
getDigits[n_, b_, k_] := 
  MatrixForm[Table[IntegerDigits[n, b - i], {i, 0, k - 1}]];

Do[Print["d = ", 3, ", base: ", base, "; ", 
    Timing[getDigits[#, base, 2] & /@ 
      get2Palindromes[3, base]]];, {base, 2, 10}];

(*
Do[Print["d = ",3, ", base: ",base,"; \
",Timing[getDigits[#,base,3]&/@get3Palindromes[3,base]]];,{base,8,9}];
Do[Print["d = ",5, ", base: ",base,"; \
",Timing[getDigits[#,base,3]&/@get3Palindromes[5,base]]];,{base,47,47+\
4}];
Do[Print["d = ",7, ", base: ",base,"; \
",Timing[getDigits[#,base,3]&/@get3Palindromes[7,base]]];,{base,291,\
291+11}];
*)

Note that palindromes given by this will have exactly $d$ digits in all of those number bases:

To search for ones with $d,d+k_1,d+k_1+k_2$ digits in bases $b,b-1,b-2$, conditions and coefficients can be easily modified in the above code. Note that such examples for $3$-palindromes are not known yet, and that such examples for $2$-palindromes only exist for small bases $b$ and are finite for all $d$ cases so far.