Chernick's Carmichael numbers

From Rosetta Code
Revision as of 14:33, 6 June 2019 by Trizen (talk | contribs) (→‎{{header|C++}}: minor code compression)
Chernick's Carmichael numbers 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.

In 1939, Jack Chernick proved that, for n ≥ 3 and m ≥ 1:

   U(n, m) = (6m + 1) * (12m + 1) * Product_{i=1..n-2} (2^i * 9m + 1)

is a Carmichael number if all the factors are primes and, for n > 4, m is a multiple of 2^(n-4).


Example
   U(3, m) = (6m + 1) * (12m + 1) * (18m + 1)
   U(4, m) = U(3, m) * (2^2 * 9m + 1)
   U(5, m) = U(4, m) * (2^3 * 9m + 1)
   ...
   U(n, m) = U(n-1, m) * (2^(n-2) * 9m + 1)
  • The smallest Chernick's Carmichael number with 3 prime factors, is: U(3, 1) = 1729.
  • The smallest Chernick's Carmichael number with 4 prime factors, is: U(4, 1) = 63973.
  • The smallest Chernick's Carmichael number with 5 prime factors, is: U(5, 380) = 26641259752490421121.


For n = 5, the smallest number m that satisfy Chernick's conditions, is m = 380, therefore U(5, 380) is the smallest Chernick's Carmichael number with 5 prime factors.

U(5, 380) is a Chernick's Carmichael number because m = 380 is a multiple of 2^(n-4), where n = 5, and the factors { (6*380 + 1), (12*380 + 1), (18*380 + 1), (36*380 + 1), (72*380 + 1) } are all prime numbers.


Task

For n ≥ 3, let a(n) be the smallest Chernick's Carmichael number with n prime factors.

  • Compute a(n) for n = 3..9.
  • Optional: find a(10).


Note: it's perfectly acceptable to show the terms in factorized form:

 a(3) = 7 * 13 * 19
 a(4) = 7 * 13 * 19 * 37
 a(5) = 2281 * 4561 * 6841 * 13681 * 27361
 ...


See also


Related tasks



C++

Library: GMP

<lang cpp>#include <gmp.h>

  1. include <iostream>

using namespace std;

typedef unsigned long long int u64;

bool primality_pretest(u64 k) { // for k > 23

   if (!(k %  3) || !(k %  5) || !(k %  7) || !(k % 11) ||
       !(k % 13) || !(k % 17) || !(k % 19) || !(k % 23)
   ) {
       return (k <= 23);
   }
   return true;

}

bool probprime(u64 k, mpz_t n) {

   mpz_set_ui(n, k);
   return mpz_probab_prime_p(n, 0);

}

bool is_chernick(int n, u64 m, mpz_t z) {

   if (!primality_pretest(6 * m + 1)) {
       return false;
   }
   if (!primality_pretest(12 * m + 1)) {
       return false;
   }
   u64 t = 9 * m;
   for (int i = 1; i <= n - 2; i++) {
       if (!primality_pretest((t << i) + 1)) {
           return false;
       }
   }
   if (!probprime(6 * m + 1, z)) {
       return false;
   }
   if (!probprime(12 * m + 1, z)) {
       return false;
   }
   for (int i = 1; i <= n - 2; i++) {
       if (!probprime((t << i) + 1, z)) {
           return false;
       }
   }
   return true;

}

int main() {

   mpz_t z;
   mpz_inits(z, NULL);
   for (int n = 3; n <= 10; n++) {
       // `m` is a multiple of 2^(n-4), for n > 4
       u64 multiplier = (n > 4) ? (1 << (n - 4)) : 1;
       // For n > 5, m is also a multiple of 5
       if (n > 5) {
           multiplier *= 5;
       }
       for (u64 k = 1; ; k++) {
           u64 m = k * multiplier;
           if (is_chernick(n, m, z)) {
               cout << "a(" << n << ") has m = " << m << endl;
               break;
           }
       }
   }
   return 0;

}</lang>

Output:
a(3) has m = 1
a(4) has m = 1
a(5) has m = 380
a(6) has m = 380
a(7) has m = 780320
a(8) has m = 950560
a(9) has m = 950560
a(10) has m = 3208386195840

(takes ~3.5 minutes)

F#

This task uses Extensible Prime Generator (F#) <lang fsharp> // Generate Chernick's Carmichael numbers. Nigel Galloway: June 1st., 2019 let fMk m k=isPrime(6*m+1) && isPrime(12*m+1) && [1..k-2]|>List.forall(fun n->isPrime(9*(pown 2 n)*m+1)) let fX k=Seq.initInfinite(fun n->(n+1)*(pown 2 (k-4))) |> Seq.filter(fun n->fMk n k ) let cherCar k=let m=Seq.head(fX k) in printfn "m=%d primes -> %A " m ([6*m+1;12*m+1]@List.init(k-2)(fun n->9*(pown 2 (n+1))*m+1)) [4..9] |> Seq.iter cherCar </lang>

Output:
cherCar(4): m=1 primes -> [7; 13; 19; 37] 
cherCar(5): m=380 primes -> [2281; 4561; 6841; 13681; 27361] 
cherCar(6): m=380 primes -> [2281; 4561; 6841; 13681; 27361; 54721] 
cherCar(7): m=780320 primes -> [4681921; 9363841; 14045761; 28091521; 56183041; 112366081; 224732161] 
cherCar(8): m=950560 primes -> [5703361; 11406721; 17110081; 34220161; 68440321; 136880641; 273761281; 547522561] 
cherCar(9): m=950560 primes -> [5703361; 11406721; 17110081; 34220161; 68440321; 136880641; 273761281; 547522561; 1095045121] 

Go

<lang go>package main

import (

   "fmt"
   "math/big"

)

var (

   zero = new(big.Int)
   prod = new(big.Int)
   fact = new(big.Int)

)

func ccFactors(n, m uint64) (*big.Int, bool) {

   prod.SetUint64(6*m + 1)
   if !prod.ProbablyPrime(0) {
       return zero, false
   }
   fact.SetUint64(12*m + 1)
   if !fact.ProbablyPrime(0) { // 100% accurate up to 2 ^ 64
       return zero, false
   }
   prod.Mul(prod, fact)
   for i := uint64(1); i <= n-2; i++ {
       fact.SetUint64((1<<i)*9*m + 1)
       if !fact.ProbablyPrime(0) {
           return zero, false
       }
       prod.Mul(prod, fact)
   }
   return prod, true

}

func ccNumbers(start, end uint64) {

   for n := start; n <= end; n++ {
       m := uint64(1)
       if n > 4 {
           m = 1 << (n - 4)
       }
       for {
           num, ok := ccFactors(n, m)
           if ok {
               fmt.Printf("a(%d) = %d\n", n, num)
               break
           }
           if n <= 4 {
               m++
           } else {
               m += 1 << (n - 4)
           }
       }
   }

}

func main() {

   ccNumbers(3, 9)

}</lang>

Output:
a(3) = 1729
a(4) = 63973
a(5) = 26641259752490421121
a(6) = 1457836374916028334162241
a(7) = 24541683183872873851606952966798288052977151461406721
a(8) = 53487697914261966820654105730041031613370337776541835775672321
a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841

PARI/GP

Just The Impossible

As I've said before a day isn't worth living unless I've done the impossible before breakfast! If before breakfast means starting last night and seeing what happened when I get up then this qualifies. See the discussion page. <lang parigp> n=0 ? until(isprime(6*n+1)&isprime(12*n+1)&isprime(18*n+1)&isprime(36*n+1)&isprime(72*n+1)&isprime(144*n+1)&isprime(288*n+1)&isprime(576*n+1)&isprime(1152*n+1)&isprime(2304*n+1),n=n+ print(n) </lang>

Output:

3208386195840

Perl

Library: ntheory

<lang perl>use 5.020; use warnings; use ntheory qw/:all/; use experimental qw/signatures/;

sub chernick_carmichael_factors ($n, $m) {

   (6*$m + 1, 12*$m + 1, (map { (1 << $_) * 9*$m + 1 } 1 .. $n-2));

}

sub chernick_carmichael_number ($n, $callback) {

   my $multiplier = ($n > 4) ? (1 << ($n-4)) : 1;
   for (my $m = 1 ; ; ++$m) {
       my @f = chernick_carmichael_factors($n, $m * $multiplier);
       next if not vecall { is_prime($_) } @f;
       $callback->(@f);
       last;
   }

}

foreach my $n (3..9) {

   chernick_carmichael_number($n, sub (@f) { say "a($n) = ", vecprod(@f) });

}</lang>

Output:
a(3) = 1729
a(4) = 63973
a(5) = 26641259752490421121
a(6) = 1457836374916028334162241
a(7) = 24541683183872873851606952966798288052977151461406721
a(8) = 53487697914261966820654105730041031613370337776541835775672321
a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841

Perl 6

Works with: Rakudo version 2019.03
Translation of: Perl

Use the ntheory library from Perl 5 for primality testing since it is much, much faster than Perl 6s built-in .is-prime method.

<lang perl6>use Inline::Perl5; use ntheory:from<Perl5> <:all>;

sub chernick-carmichael-factors ($n, $m) {

   6*$m + 1, 12*$m + 1, |((1 .. $n-2).map: { (1 +< $_) * 9*$m + 1 } )

}

sub chernick-carmichael-number ($n) {

   my $multiplier = 1;
   my $iterator   = 1 .. *;
   if $n > 4 {
       $multiplier = 1 +< ($n-4);
       $iterator   = (1..*).map: * * 5;
   }
   my $i = $iterator.first: -> $m {
       [&&] chernick-carmichael-factors($n, $m * $multiplier).map: { is_prime($_) #`[ .is-prime ] }
   }
   chernick-carmichael-factors($n, $i * $multiplier)

}

for 3 .. 9 -> $n {

   my @f = chernick-carmichael-number($n);
   say "a($n): {[*] @f} = {@f.join(' ⨉ ')}";

}</lang>

Output:
a(3): 1729 = 7 ⨉ 13 ⨉ 19
a(4): 63973 = 7 ⨉ 13 ⨉ 19 ⨉ 37
a(5): 26641259752490421121 = 2281 ⨉ 4561 ⨉ 6841 ⨉ 13681 ⨉ 27361
a(6): 1457836374916028334162241 = 2281 ⨉ 4561 ⨉ 6841 ⨉ 13681 ⨉ 27361 ⨉ 54721
a(7): 24541683183872873851606952966798288052977151461406721 = 4681921 ⨉ 9363841 ⨉ 14045761 ⨉ 28091521 ⨉ 56183041 ⨉ 112366081 ⨉ 224732161
a(8): 53487697914261966820654105730041031613370337776541835775672321 = 5703361 ⨉ 11406721 ⨉ 17110081 ⨉ 34220161 ⨉ 68440321 ⨉ 136880641 ⨉ 273761281 ⨉ 547522561
a(9): 58571442634534443082821160508299574798027946748324125518533225605795841 = 5703361 ⨉ 11406721 ⨉ 17110081 ⨉ 34220161 ⨉ 68440321 ⨉ 136880641 ⨉ 273761281 ⨉ 547522561 ⨉ 1095045121

Sidef

<lang ruby>func chernick_carmichael_factors (n, m) {

   [6*m + 1, 12*m + 1, {|i| 2**i * 9*m + 1 }.map(1 .. n-2)...]

}

func is_chernick_carmichael (n, m) {

   (n == 2) ? (is_prime(6*m + 1) && is_prime(12*m + 1))
            : (is_prime(2**(n-2) * 9*m + 1) && __FUNC__(n-1, m))

}

func chernick_carmichael_number(n, callback) {

   var multiplier = (n>4 ? 2**(n-4) : 1)
   var m = (1..Inf -> first {|m| is_chernick_carmichael(n, m * multiplier) })
   var f = chernick_carmichael_factors(n, m * multiplier)
   callback(f...)

}

for n in (3..9) {

   chernick_carmichael_number(n, {|*f| say "a(#{n}) = #{f.join(' * ')}" })

}</lang>

Output:
a(3) = 7 * 13 * 19
a(4) = 7 * 13 * 19 * 37
a(5) = 2281 * 4561 * 6841 * 13681 * 27361
a(6) = 2281 * 4561 * 6841 * 13681 * 27361 * 54721
a(7) = 4681921 * 9363841 * 14045761 * 28091521 * 56183041 * 112366081 * 224732161
a(8) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561
a(9) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 * 1095045121

zkl

Translation of: Go
Library: GMP

GNU Multiple Precision Arithmetic Library

Using GMP (probabilistic primes), because it is easy and fast to check primeness. <lang zkl>var [const] BI=Import("zklBigNum"); // libGMP

fcn ccFactors(n,m){ // not re-entrant

  prod:=BI(6*m + 1);
  if(not prod.probablyPrime())    return(False);
  fact:=BI(12*m + 1);
  if(not fact.probablyPrime())    return(False);
  prod.mul(fact);
  foreach i in ([1..n-2]){
     fact.set((2).pow(i) *9*m + 1);
     if(not fact.probablyPrime()) return(False);
     prod.mul(fact);
  }
  prod

}

fcn ccNumbers(start,end){

  foreach n in ([start..end]){
     a,m := ( if(n<=4) 1  else (2).pow(n - 4) ), a;
     while(1){

if(num := ccFactors(n,m)){ println("a(%d) = %,d".fmt(n,num)); break; } m+=a;

     }
  }

}</lang> <lang zkl>ccNumbers(3,9);</lang>

Output:
a(3) = 1,729
a(4) = 63,973
a(5) = 26,641,259,752,490,421,121
a(6) = 1,457,836,374,916,028,334,162,241
a(7) = 24,541,683,183,872,873,851,606,952,966,798,288,052,977,151,461,406,721
a(8) = 53,487,697,914,261,966,820,654,105,730,041,031,613,370,337,776,541,835,775,672,321
a(9) = 58,571,442,634,534,443,082,821,160,508,299,574,798,027,946,748,324,125,518,533,225,605,795,841