Ormiston pairs: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
Line 210: Line 210:
printfn $"<10 million: %d{primes32()|>Seq.takeWhile((>)10000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<10 million: %d{primes32()|>Seq.takeWhile((>)10000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<100 million: %d{primes32()|>Seq.takeWhile((>)100000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<100 million: %d{primes32()|>Seq.takeWhile((>)100000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<1 trillion: %d{primes32()|>Seq.takeWhile((>)1000000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<1 billion: %d{primes32()|>Seq.takeWhile((>)1000000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
</syntaxhighlight>
</syntaxhighlight>
{{out}}
{{out}}
Line 218: Line 218:
<10 million: 3722
<10 million: 3722
<100 million: 34901
<100 million: 34901
<1 trillion: 326926
<1 billion: 326926
</pre>
</pre>



Revision as of 15:57, 31 January 2023

Ormiston pairs 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.

An Ormiston pair is two consecutive prime numbers which are anagrams, i.e. contain the same decimal digits but in a different order.


(1913, 1931) is the first such pair.


Task
  • Find and show the first 30 Ormiston pairs.
  • Find and show the count of Ormiston pairs up to one million.


Stretch
  • Find and show the count of Ormiston pairs up to ten million.


See also


ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

When running this with ALGOL 68G, you will need to specify a large heap size with e.g., -heap 256M on the ALGOL 68G command.

Uses the "signature" idea from the XPL0 sample and the "difference is 0 MOD 18" filter from the Wren sample.
Also shows the number of prime pairs whose difference is 0 MOD 18 but are not Ormiston pairs.

BEGIN # find some Orimiston pairs - pairs of primes where the first and next  #
      # prime are anagrams                                                    #
    PR read "primes.incl.A68" PR                    # include prime utilities #
    INT max prime  = 10 000 000;            # maximum number we will consider #
    INT max digits = BEGIN                    # count the digits of max prime # 
                        INT v := 1;
                        INT d := 1;
                        WHILE ( v *:= 10 ) < max prime DO d +:= 1 OD;
                        d
                     END;
    [ 0 : 9 ]LONG INT dp;  # table of max digit powers for signature creation #
    dp[ 0 ] := 1; FOR i TO UPB dp DO dp[ i ] := max digits * dp[ i - 1 ] OD;
    []BOOL prime      = PRIMESIEVE max prime;
    # construct a list of the primes up to the maximum prime to consider      #
    []INT  prime list = EXTRACTPRIMESUPTO max prime FROMPRIMESIEVE prime;
    # splits n into its digits, returning the sum of their counts, each       #
    # scaled by the digit power of max digits                                 #
    PROC get digits = ( INT n )LONG INT:
         BEGIN
            INT      v      := n;
            LONG INT result := dp[ v MOD 10 ];
            WHILE ( v OVERAB 10 ) > 0 DO
                result +:= dp[ v MOD 10 ]
            OD;
            result
         END # get digits # ;
    # count the Ormiston pairs                                                #
    INT o count := 0;
    INT n count := 0;
    INT p10     := 100 000;
    FOR i TO UPB prime list - 1 DO
        INT p1 = prime list[ i     ];
        INT p2 = prime list[ i + 1 ];
        IF ( p2 - p1 ) MOD 18 = 0 THEN
            # p2 and p1 might be anagrams                                     #
            IF get digits( p1 ) /= get digits( p2 ) THEN
                # not an Ormiston pair afterall                               #
                n count +:= 1
            ELSE
                # p1 and p2 are an Ormiston pair                              #
                o count +:= 1;
                IF o count <= 30 THEN
                    print( ( " (", whole( p1, -5 ), ", ", whole( p2, -5 ), ")"
                           , IF o count MOD 3 = 0 THEN newline ELSE " " FI
                           )
                         )
                ELIF p1 >= p10 THEN
                    print( ( whole( o count - 1, -9 )
                           , " Ormiston pairs below "
                           , whole( p10, 0 )
                           , newline
                           )
                         );
                    p10 *:= 10
                FI
            FI
        FI
    OD;
    print( ( whole( o count, -9 ), " Ormiston pairs below ", whole( max prime, 0 ), newline ) );
    print( ( whole( n count, -9 ), " non-Ormiston ""0 MOD 18"" pairs bwlow ", whole( max prime, 0 ) ) )
END
Output:
 ( 1913,  1931)  (18379, 18397)  (19013, 19031)
 (25013, 25031)  (34613, 34631)  (35617, 35671)
 (35879, 35897)  (36979, 36997)  (37379, 37397)
 (37813, 37831)  (40013, 40031)  (40213, 40231)
 (40639, 40693)  (45613, 45631)  (48091, 48109)
 (49279, 49297)  (51613, 51631)  (55313, 55331)
 (56179, 56197)  (56713, 56731)  (58613, 58631)
 (63079, 63097)  (63179, 63197)  (64091, 64109)
 (65479, 65497)  (66413, 66431)  (74779, 74797)
 (75913, 75931)  (76213, 76231)  (76579, 76597)
       40 Ormiston pairs below 100000
      382 Ormiston pairs below 1000000
     3722 Ormiston pairs below 10000000
    53369 non-Ormiston "0 MOD 18" pairs bwlow 10000000

C++

#include <algorithm>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <vector>

std::vector<bool> prime_sieve(int limit) {
    std::vector<bool> sieve(limit, true);
    if (limit > 0)
        sieve[0] = false;
    if (limit > 1)
        sieve[1] = false;
    for (int i = 4; i < limit; i += 2)
        sieve[i] = false;
    for (int p = 3, sq = 9; sq < limit; p += 2) {
        if (sieve[p]) {
            for (int q = sq; q < limit; q += p << 1)
                sieve[q] = false;
        }
        sq += (p + 1) << 2;
    }
    return sieve;
}

class digit_set {
public:
    explicit digit_set(int n) {
        for (; n > 0; n /= 10)
            ++count_[n % 10];
    }

    bool operator==(const digit_set& other) const {
        return std::equal(count_, count_ + 10, other.count_);
    }

private:
    int count_[10] = {};
};

int main() {
    const int limit = 100000000;
    std::vector<bool> sieve = prime_sieve(limit);
    int count = 0, count1 = 0, count2 = 0;
    std::cout << "First 30 Ormiston pairs:\n";
    for (int p1 = 0, p2 = 0; p2 < limit; ++p2) {
        if (!sieve[p2])
            continue;
        if (digit_set(p2) == digit_set(p1)) {
            if (count1 == 0 && p2 > 1000000)
                count1 = count;
            if (count2 == 0 && p2 > 10000000)
                count2 = count;
            ++count;
            if (count <= 30)
                std::cout << '(' << std::setw(5) << p1 << ", " << std::setw(5)
                          << p2 << ')' << (count % 3 == 0 ? '\n' : ' ');
        }
        p1 = p2;
    }
    std::cout << "\nNumber of Ormiston pairs < 1,000,000: " << count1 << '\n';
    std::cout << "Number of Ormiston pairs < 10,000,000: " << count2 << '\n';
    std::cout << "Number of Ormiston pairs < 100,000,000: " << count << '\n';
}
Output:
First 30 Ormiston pairs:
( 1913,  1931) (18379, 18397) (19013, 19031)
(25013, 25031) (34613, 34631) (35617, 35671)
(35879, 35897) (36979, 36997) (37379, 37397)
(37813, 37831) (40013, 40031) (40213, 40231)
(40639, 40693) (45613, 45631) (48091, 48109)
(49279, 49297) (51613, 51631) (55313, 55331)
(56179, 56197) (56713, 56731) (58613, 58631)
(63079, 63097) (63179, 63197) (64091, 64109)
(65479, 65497) (66413, 66431) (74779, 74797)
(75913, 75931) (76213, 76231) (76579, 76597)

Number of Ormiston pairs < 1,000,000: 382
Number of Ormiston pairs < 10,000,000: 3722
Number of Ormiston pairs < 100,000,000: 34901

F#

This task uses Extensible Prime Generator (F#)

// Ormiston pairs. Nigel Galloway: January 31st., 2023
let fG(n,g)=let i=Array.zeroCreate<int>10
            let rec fG n g=if g<10 then i[g]<-n i[g] 1 else i[g%10]<-n i[g%10] 1; fG n (g/10)
            fG (+) n; fG (-) g; Array.forall ((=)0) i
primes32()|>Seq.pairwise|>Seq.filter fG|>Seq.take 30|>Seq.iter(printf "%A "); printfn ""
printfn $"<1 million: %d{primes32()|>Seq.takeWhile((>)1000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<10 million: %d{primes32()|>Seq.takeWhile((>)10000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<100 million: %d{primes32()|>Seq.takeWhile((>)100000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
printfn $"<1 billion: %d{primes32()|>Seq.takeWhile((>)1000000000)|>Seq.pairwise|>Seq.filter fG|>Seq.length}"
Output:
(1913, 1931) (18379, 18397) (19013, 19031) (25013, 25031) (34613, 34631) (35617, 35671) (35879, 35897) (36979, 36997) (37379, 37397) (37813, 37831) (40013, 40031) (40213, 40231) (40639, 40693) (45613, 45631) (48091, 48109) (49279, 49297) (51613, 51631) (55313, 55331) (56179, 56197) (56713, 56731) (58613, 58631) (63079, 63097) (63179, 63197) (64091, 64109) (65479, 65497) (66413, 66431) (74779, 74797) (75913, 75931) (76213, 76231) (76579, 76597)
<1 million: 382
<10 million: 3722
<100 million: 34901
<1 billion: 326926

Factor

Works with: Factor version 0.99 2022-04-03
USING: grouping io kernel lists lists.lazy math math.parser
math.primes.lists math.statistics prettyprint sequences ;

: ormistons ( -- list )
    lprimes dup cdr lzip
    [ first2 [ >dec histogram ] same? ] lfilter ;

"First 30 Ormiston pairs:" print
30 ormistons ltake list>array 5 group simple-table. nl

ormistons [ first 1e6 < ] lwhile llength pprint bl
"Ormiston pairs less than a million." print
Output:
First 30 Ormiston pairs:
{ 1913 1931 }   { 18379 18397 } { 19013 19031 } { 25013 25031 } { 34613 34631 }
{ 35617 35671 } { 35879 35897 } { 36979 36997 } { 37379 37397 } { 37813 37831 }
{ 40013 40031 } { 40213 40231 } { 40639 40693 } { 45613 45631 } { 48091 48109 }
{ 49279 49297 } { 51613 51631 } { 55313 55331 } { 56179 56197 } { 56713 56731 }
{ 58613 58631 } { 63079 63097 } { 63179 63197 } { 64091 64109 } { 65479 65497 }
{ 66413 66431 } { 74779 74797 } { 75913 75931 } { 76213 76231 } { 76579 76597 }

382 Ormiston pairs less than a million.

Go

Translation of: Wren
Library: Go-rcu
package main

import (
    "fmt"
    "rcu"
    "sort"
)

func areEqual(l1, l2 []int) bool {
    len1 := len(l1)
    len2 := len(l2)
    if len1 != len2 {
        return false
    }
    for i := 0; i < len1; i++ {
        if l1[i] != l2[i] {
            return false
        }
    }
    return true
}

func main() {
    const limit = 1e7
    primes := rcu.Primes(limit)
    var orm30 [][2]int
    i := 0
    j := int(1e5)
    count := 0
    var counts []int
    for i < len(primes)-1 {
        p1 := primes[i]
        p2 := primes[i+1]
        if (p2-p1)%18 != 0 {
            i++
            continue
        }
        d1 := rcu.Digits(p1, 10)
        d2 := rcu.Digits(p2, 10)
        sort.Ints(d1)
        sort.Ints(d2)
        if areEqual(d1, d2) {
            if count < 30 {
                orm30 = append(orm30, [2]int{p1, p2})
            }
            if p1 >= j {
                counts = append(counts, count)
                j *= 10
            }
            count++
            i += 2
        } else {
            i++
        }
    }
    counts = append(counts, count)
    fmt.Println("First 30 Ormiston pairs:")
    for i := 0; i < 30; i++ {
        fmt.Printf("%5v ", orm30[i])
        if (i+1)%3 == 0 {
            fmt.Println()
        }
    }
    fmt.Printf("\n%d Ormiston pairs before 100,000\n", counts[0])
    fmt.Printf("%d Ormiston pairs before 1,000,000\n", counts[1])
    fmt.Printf("%s Ormiston pairs before 10,000,000\n", rcu.Commatize(counts[2]))
}
Output:
First 30 Ormiston pairs:
[ 1913  1931] [18379 18397] [19013 19031] 
[25013 25031] [34613 34631] [35617 35671] 
[35879 35897] [36979 36997] [37379 37397] 
[37813 37831] [40013 40031] [40213 40231] 
[40639 40693] [45613 45631] [48091 48109] 
[49279 49297] [51613 51631] [55313 55331] 
[56179 56197] [56713 56731] [58613 58631] 
[63079 63097] [63179 63197] [64091 64109] 
[65479 65497] [66413 66431] [74779 74797] 
[75913 75931] [76213 76231] [76579 76597] 

40 Ormiston pairs before 100,000
382 Ormiston pairs before 1,000,000
3,722 Ormiston pairs before 10,000,000

J

For this, we would like to be able to test if a prime number is the first value in an Ormiston pair:

   isorm=: -:&(/:~)&":&> 4 p: ]

We could also use a routine to organize pairs of numbers as moderate width lines of text:

   fmtpairs=: {{ names <@([,',',])&":/"1 y}}

Then the task becomes:

   fmtpairs (,. 4 p:]) p:30{.I. isorm i.&.(p:inv) 1e6
1913,1931   18379,18397 19013,19031 25013,25031 
34613,34631 35617,35671 35879,35897 36979,36997 
37379,37397 37813,37831 40013,40031 40213,40231 
40639,40693 45613,45631 48091,48109 49279,49297 
51613,51631 55313,55331 56179,56197 56713,56731 
58613,58631 63079,63097 63179,63197 64091,64109 
65479,65497 66413,66431 74779,74797 75913,75931 
76213,76231 76579,76597                         
   +/isorm i.&.(p:inv) 1e6   NB. number of Ormiston pairs less than 1e6
382
   +/isorm i.&.(p:inv) 1e7   NB. number of Ormiston pairs less than 1e7
3722

Python

""" rosettacode.org task Ormiston_pairs """

from sympy import primerange


PRIMES1M = list(primerange(1, 1_000_000))
ASBASE10SORT = [str(sorted(list(str(i)))) for i in PRIMES1M]
ORMISTONS = [(PRIMES1M[i - 1], PRIMES1M[i]) for i in range(1, len(PRIMES1M))
             if ASBASE10SORT[i - 1] == ASBASE10SORT[i]]

print('First 30 Ormiston pairs:')
for (i, o) in enumerate(ORMISTONS):
    if i < 30:
        print(f'({o[0] : 6} {o[1] : 6} )',
              end='\n' if (i + 1) % 5 == 0 else '  ')
    else:
        break

print(len(ORMISTONS), 'is the count of Ormiston pairs up to one million.')
Output:
First 30 Ormiston pairs:
(  1913   1931 )  ( 18379  18397 )  ( 19013  19031 )  ( 25013  25031 )  ( 34613  34631 )
( 35617  35671 )  ( 35879  35897 )  ( 36979  36997 )  ( 37379  37397 )  ( 37813  37831 )
( 40013  40031 )  ( 40213  40231 )  ( 40639  40693 )  ( 45613  45631 )  ( 48091  48109 )
( 49279  49297 )  ( 51613  51631 )  ( 55313  55331 )  ( 56179  56197 )  ( 56713  56731 )
( 58613  58631 )  ( 63079  63097 )  ( 63179  63197 )  ( 64091  64109 )  ( 65479  65497 )
( 66413  66431 )  ( 74779  74797 )  ( 75913  75931 )  ( 76213  76231 )  ( 76579  76597 )
382 is the count of Ormiston pairs up to one million.

Raku

use Lingua::EN::Numbers;
use List::Divvy;

my @primes = lazy (^∞).hyper.grep( &is-prime ).map: { $_ => .comb.sort.join };
my @Ormistons = @primes.kv.map: { ($^value.key, @primes[$^key+1].key) if $^value.value eq @primes[$^key+1].value };

say "First thirty Ormiston pairs:"; 
say @Ormistons[^30].batch(3)».map( { "({.[0].fmt: "%5d"}, {.[1].fmt: "%5d"})" } ).join: "\n";
say '';
say +@Ormistons.&before( *[1] > $_ ) ~ " Ormiston pairs before " ~ .Int.&cardinal for 1e5, 1e6, 1e7;
Output:
First thirty Ormiston pairs:
( 1913,  1931) (18379, 18397) (19013, 19031)
(25013, 25031) (34613, 34631) (35617, 35671)
(35879, 35897) (36979, 36997) (37379, 37397)
(37813, 37831) (40013, 40031) (40213, 40231)
(40639, 40693) (45613, 45631) (48091, 48109)
(49279, 49297) (51613, 51631) (55313, 55331)
(56179, 56197) (56713, 56731) (58613, 58631)
(63079, 63097) (63179, 63197) (64091, 64109)
(65479, 65497) (66413, 66431) (74779, 74797)
(75913, 75931) (76213, 76231) (76579, 76597)

40 Ormiston pairs before one hundred thousand
382 Ormiston pairs before one million
3722 Ormiston pairs before ten million

Wren

Library: Wren-math
Library: Wren-seq
Library: Wren-fmt
import "./math" for Int
import "./seq" for Lst
import "./fmt" for Fmt

var limit = 1e7
var primes = Int.primeSieve(limit)
var orm30 = []
var i = 0
var j = 1e5
var count = 0
var counts = []
while (i < primes.count-1) {
    var p1 = primes[i]
    var p2 = primes[i+1]
    if ((p2 - p1) % 18 != 0) {
        i = i + 1
        continue
    }
    var d1 = Int.digits(p1)
    var d2 = Int.digits(p2)
    if (Lst.areEqual(d1.sort(), d2.sort())) {
        if (count < 30) orm30.add([p1, p2])
        if (p1 >= j) {
            counts.add(count)
            j = j * 10
        }
        count = count + 1
        i = i + 2
    } else {
        i = i + 1
    }
}
counts.add(count)
System.print("First 30 Ormiston pairs:")
Fmt.tprint("[$,6d] ", orm30, 3)
Fmt.print("\n$,d Ormiston pairs before 100,000",  counts[0])
Fmt.print("$,d Ormiston pairs before 1,000,000",  counts[1])
Fmt.print("$,d Ormiston pairs before 10,000,000", counts[2])
Output:
First 30 Ormiston pairs:
[ 1,913  1,931]  [18,379 18,397]  [19,013 19,031]  
[25,013 25,031]  [34,613 34,631]  [35,617 35,671]  
[35,879 35,897]  [36,979 36,997]  [37,379 37,397]  
[37,813 37,831]  [40,013 40,031]  [40,213 40,231]  
[40,639 40,693]  [45,613 45,631]  [48,091 48,109]  
[49,279 49,297]  [51,613 51,631]  [55,313 55,331]  
[56,179 56,197]  [56,713 56,731]  [58,613 58,631]  
[63,079 63,097]  [63,179 63,197]  [64,091 64,109]  
[65,479 65,497]  [66,413 66,431]  [74,779 74,797]  
[75,913 75,931]  [76,213 76,231]  [76,579 76,597]  

40 Ormiston pairs before 100,000
382 Ormiston pairs before 1,000,000
3,722 Ormiston pairs before 10,000,000

XPL0

func IsPrime(N);        \Return 'true' if N is prime
int  N, I;
[if N <= 2 then return N = 2;
if (N&1) = 0 then \even >2\ return false;
for I:= 3 to sqrt(N) do
    [if rem(N/I) = 0 then return false;
    I:= I+1;
    ];
return true;
];

func GetSig(N);         \Return signature of N
\A "signature" is the count of each digit in N packed into a 32-bit word
int N, Sig;
[Sig:= 0;
repeat  N:= N/10;
        Sig:= Sig + 1<<(rem(0)*3);
until   N = 0;
return Sig;
];

int Cnt, N, N0, Sig, Sig0;
[Cnt:= 0;  N0:= 0;  Sig0:= 0;  N:= 3;
Format(6, 0);
loop    [if IsPrime(N) then
            [Sig:= GetSig(N);
            if Sig = Sig0 then
                [Cnt:= Cnt+1;
                if Cnt <= 30 then
                    [RlOut(0, float(N0));  RlOut(0, float(N));
                    if rem(Cnt/3) = 0 then CrLf(0) else Text(0, "  ");
                    ];
                ];
            Sig0:= Sig;
            N0:= N;
            ];
        if N = 1_000_000-1 then
            [Text(0, "^m^jOrmiston pairs up to one million: ");
            IntOut(0, Cnt);
            ];
        if N = 10_000_000-1 then
            [Text(0, "^m^jOrmiston pairs up to ten million: ");
            IntOut(0, Cnt);
            quit;
            ];
        N:= N+2;
        ];
]
Output:
  1913  1931   18379 18397   19013 19031
 25013 25031   34613 34631   35617 35671
 35879 35897   36979 36997   37379 37397
 37813 37831   40013 40031   40213 40231
 40639 40693   45613 45631   48091 48109
 49279 49297   51613 51631   55313 55331
 56179 56197   56713 56731   58613 58631
 63079 63097   63179 63197   64091 64109
 65479 65497   66413 66431   74779 74797
 75913 75931   76213 76231   76579 76597

Ormiston pairs up to one million: 382
Ormiston pairs up to ten million: 3722