Find palindromic numbers in both binary and ternary bases: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Ruby}}: commented code)
Line 229: Line 229:
r = w.reverse
r = w.reverse
num = ( w << "1" << r).to_i(3)
num = ( w << "1" << r).to_i(3)
y << num if (Math.log2(num) +1).floor.odd?
y << num if (Math.log2(num) +1).floor.odd? #don't yield if base2 size is even
n += 1
n += 1
end
end
Line 235: Line 235:


base2 = Enumerator.new do |y|
base2 = Enumerator.new do |y|
# generates palindromic base 2 numbers of odd length, with 0 or 1 in the middle
n = 0
n = 0
y << 0
y << 0

Revision as of 20:45, 27 March 2014

Find palindromic numbers in both binary and ternary bases is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
The task

Find and show (in decimal) the first six numbers (non-negative integers) that are palindromes in both base 2 and base 3.

Use zero (0) as the first number found, even though some other definitions ignore it.

Optionally, show the decimal number found in it's binary and ternary form.

It's permissible to assume the first two numbers and simply list them.

See also
  • Sequence A60792, Numbers that are palindromic in bases 2 and 3 on The On-Line Encyclopedia of Integer Sequences.


C

<lang c>#include <stdio.h> typedef unsigned long long xint;

int is_palin2(xint n) {

       xint x = 0;
       if (!(n&1)) return !n;
       while (x < n) x = x<<1 | (n&1), n >>= 1;
       return n == x || n == x>>1;

}

xint reverse3(xint n) {

       xint x = 0;
       while (n) x = x*3 + (n%3), n /= 3;
       return x;

}

void print(xint n, xint base) {

       putchar(' ');
       // printing digits backwards, but hey, it's a palindrome
       do { putchar('0' + (n%base)), n /= base; } while(n);
       printf("(%lld)", base);

}

int main(void) {

       xint i, n, cnt, top = 1, mul = 1, even = 0;
       for (i = cnt = 0; cnt < 6; i++) {
               if (i == top) {
                       if (even ^= 1)
                               top *= 3;
                       else
                               i = mul, mul = top;
               }
               n = i*mul + reverse3(even ? i/3 : i);
               if (is_palin2(n)) {
                       printf("%llu", n);
                       print(n, 3);
                       print(n, 2);
                       putchar('\n');
               }
       }
       return 0;

}</lang>

Output:
0 0(3) 0(2)
1 1(3) 1(2)
6643 100010001(3) 1100111110011(2)
1422773 2200021200022(3) 101011011010110110101(2)
5415589 101012010210101(3) 10100101010001010100101(2)
90396755477 22122022220102222022122(3) 1010100001100000100010000011000010101(2)

D

Translation of: C

<lang d>bool isPalindrome2(ulong n) pure nothrow {

   ulong x = 0;
   if (!(n & 1))
       return !n;
   while (x < n) {
       x = (x << 1) | (n & 1);
       n >>= 1;
   }
   return n == x || n == (x >> 1);

}

ulong reverse3(ulong n) pure nothrow {

   ulong x = 0;
   while (n) {
       x = x * 3 + (n % 3);
       n /= 3;
   }
   return x;

}

void printReversed(ubyte base)(ulong n) {

   putchar(' ');
   do {
       putchar('0' + (n % base));
       n /= base;
   } while(n);
   printf("(%d)", base);

}

void main() {

   import core.stdc.stdio;
   ulong i, cnt, top = 1, mul = 1, even = 0;
   uint count = 0;
   for (i = cnt = 0; cnt < 6; i++) {
       if (i == top) {
           if (even ^= 1)
               top *= 3;
           else {
               i = mul;
               mul = top;
           }
       }
       immutable n = i * mul + reverse3(even ? i / 3 : i);
       if (isPalindrome2(n)) {
           printf("%llu", n);
           printReversed!3(n);
           printReversed!2(n);
           putchar('\n');
           if (++count >= 6) // Print first 6.
               break;
       }
   }

}</lang>

Output:
0 0(3) 0(2)
1 1(3) 1(2)
6643 100010001(3) 1100111110011(2)
1422773 2200021200022(3) 101011011010110110101(2)
5415589 101012010210101(3) 10100101010001010100101(2)
90396755477 22122022220102222022122(3) 1010100001100000100010000011000010101(2)

Perl 6

Instead of searching for numbers that are palindromes in one base then checking the other, generate palindromic trinary numbers directly, then check to see if they are also binary palindromes. Outputs the list in decimal, binary and trinary.

Note: finding the first six takes a depressingly long time with this implementation. Seven would be unbearable. :-(

<lang perl6>my @palindromes := 0, 1, gather for 1 .. * -> $n {

    my $p = $n.base(3);
    my $q = $p.flip;
    for "$p$q", "{$p}0$q", "{$p}1$q", "{$p}2$q" -> $r { 
       my $s = :3($r);
       next if $s %% 2;
       $s = $s.base(2);
       next unless $s eq $s.flip;
       take :2($s);
    }

}

printf "%d, %s, %s\n", $_, $_.base(2), $_.base(3) for @palindromes[^6]</lang>

Output:
0, 0, 0
1, 1, 1
6643, 1100111110011, 100010001
1422773, 101011011010110110101, 2200021200022
5415589, 10100101010001010100101, 101012010210101
90396755477, 1010100001100000100010000011000010101, 22122022220102222022122

REXX

Programming note:   This version takes advantage of the properties of a binary number such
that some powers of two can be bypassed because they have an even number of binary digits.

For this REXX program, a few deterministic assumptions were made:

  • for the requirement of binary palindromes, the numbers have to be odd.
  • for the requirement of binary palindromes, the number of binary digits have to be odd.
  • for the requirement of ternary palindromes, the numbers can't end in zero (in base 3).

<lang rexx>/*REXX pgm finds decimal #s that are palindromic in binary and ternary.*/ numeric digits 50 /*being reasonable instead of 500*/ hits=0 /*number of hits (palindromes). */ say right(0, digits()); hits=hits+1 /*display the 1st pal (in B2&B3).*/ say right(1, digits()); hits=hits+1 /*display the 2nd pal (in B2&B3).*/ !.= /* [↓] build list of powers of 3*/

    do i=1  until  pos('E',!.i)\==0;  !.i=3**i;   end  /*i*/

o=1 /* [↓] primary search: bin pals.*/

 do p=1                               /*P =power of 2 used to start #s.*/
 start=2**p + 1                       /*compute #s from  a  power of 2.*/
 b=strip(x2b(d2x(start)),'L',0)       /*express START number in binary.*/
 if length(b)//2==0  then iterate p   /*if bin# has even# digits, skip.*/
                                      /* [↓]   do searches in batches. */
     do m=0  to  2**p   by 2          /*base 2 pals must be odd (|zero)*/
     n=start+m                        /*continue from START for odd #s.*/
     if n//3==0         then iterate  /*base 3 pals mustn't end in zero*/
     b=strip(x2b(d2x(n)),'L',0)       /*express the number in binary.  */
     if b\==reverse(b)  then iterate  /*is binary number palindromic?  */
     x=n                              /*convert the number to base 3.  */
       do j=o; if !.j>x then leave; end /*find upper limit of pow of 3.*/
     q=                               /*set base 3 result holder to nul*/
     o=j-1                            /*use this pow of 3 for next time*/
       do k=o  to 1  by -1;  _=!.k;  d=x%_;  q=q||d;  x=x//_;  end  /*k*/
     t=q||x                           /*handle the conversion residual.*/
     if t\==reverse(t)  then iterate  /*is this ternary # palindromic? */
     say right(n, digits())           /*display a palindrome (in B2&B3)*/
     hits=hits+1                      /*bump hit counter (palindromes).*/
     if hits==6  then leave p         /*when there are 6 hits, leave P.*/
     end   /*m*/                      /* [↑]  this process is sluggish.*/
 end       /*p*/                      /* [↑]  leave the P loop @ 6 hits*/
                                      /*stick a fork in it, we're done.*/</lang>

output

                                                 0
                                                 1
                                              6643
                                           1422773
                                           5415589
                                       90396755477

Ruby

I observed that the double palindromic numbers in base 3 all have a "1" right in the middle. Also, both base 2 and base 3 representations have an odd number of digits. (NB I have no mathematical proof of this). This program constructs possible palindromes using the above "rules" and checks if they happen to be the same number. The first six took less then one second, 381920985378904469 took around 40 minutes (using one core) and 146 million possible candidates. <lang ruby> base3 = Enumerator.new do |y|

  1. generates palindromic base 3 numbers of odd length, with 1 in the middle
 n = 0
 y << 0
 y << 1
 loop do
   w = n.to_s(3)
   r = w.reverse
   num = ( w << "1" << r).to_i(3)
   y << num if (Math.log2(num) +1).floor.odd? #don't yield if base2 size is even
   n += 1
 end

end

base2 = Enumerator.new do |y|

  1. generates palindromic base 2 numbers of odd length, with 0 or 1 in the middle
 n = 0
 y << 0
 y << 1
 loop do
   w = n.to_s(2)
   r = w.reverse
   y << "#{w}0#{r}".to_i(2)
   y << "#{w}1#{r}".to_i(2)
   n += 1
 end

end

b2 = 0 counter = 0 loop do

 b3 = base3.next
 b2 = base2.next until b2 >= b3
 p b2 if b2 ==b3
 if counter % 1_000_000 == 0 then
   puts"#{counter} b2: #{b2} b3: #{b3}"
 end
 counter += 1

end</lang>

Output:
0
0 b2: 0 b3: 0
1
6643
1422773
5415589
90396755477
1000000 b2: 23905993887669 b3: 23905990910359
2000000 b2: 290686519348257 b3: 290686517832919
.
.
.
146000000 b2: 381113553041095829 b3: 381113552941511621
381920985378904469
147000000 b2: 382275814715933589 b3: 382275814546908221
^Ctest2.rb:37:in `next': Interrupt