Coprime triplets: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Go)
Line 13: Line 13:
# iterative Greatest Common Divisor routine, returns the gcd of m and n #
# iterative Greatest Common Divisor routine, returns the gcd of m and n #
PROC gcd = ( INT m, n )INT:
PROC gcd = ( INT m, n )INT:
IF m = 0 THEN
BEGIN
n
ELSE
INT a := ABS m, b := ABS n;
INT a := ABS m, b := ABS n;
WHILE b /= 0 DO
WHILE b /= 0 DO
Line 23: Line 21:
OD;
OD;
a
a
FI # gcd # ;
END # gcd # ;
# returns an array of the coprime triplets up to n #
# returns an array of the coprime triplets up to n #
OP COPRIMETRIPLETS = ( INT n )[]INT:
OP COPRIMETRIPLETS = ( INT n )[]INT:

Revision as of 16:10, 12 June 2021

Coprime triplets 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.
Task

Find and show the smallest number which is coprime to the last two predecessors and has not yet appeared; a(1)=1, a(2)=2.
p and q are coprimes if they have no common factors other than 1.
Let p, q < 50

ALGOL 68

<lang algol68>BEGIN # find members of the coprime triplets sequence: starting from 1, 2 the #

     # subsequent members are the lowest number coprime to the previous two  #
     # that haven't appeared in the sequence yet                             #
   # iterative Greatest Common Divisor routine, returns the gcd of m and n   #
   PROC gcd = ( INT m, n )INT:
        BEGIN
           INT a := ABS m, b := ABS n;
           WHILE b /= 0 DO
               INT new a = b;
               b        := a MOD b;
               a        := new a
           OD;
           a
        END # gcd # ;
   # returns an array of the coprime triplets up to n                        #
   OP   COPRIMETRIPLETS = ( INT n )[]INT:
        BEGIN
           [ 1 : n ]INT result;
           IF n > 0 THEN
               result[ 1 ] := 1;
               IF n > 1 THEN
                   [ 1 : n ]BOOL used;
                   used[ 1 ] := used[ 2 ] := TRUE;
                   FOR i FROM 3 TO n DO used[ i ] := FALSE; result[ i ] := 0 OD;
                   result[ 2 ] := 2;
                   FOR i FROM 3 TO n DO
                       INT p1 = result[ i - 1 ];
                       INT p2 = result[ i - 2 ];
                       BOOL found := FALSE;
                       FOR j TO n WHILE NOT found DO
                           IF NOT used[ j ] THEN
                               found := gcd( p1, j ) = 1 AND gcd( p2, j ) = 1;
                               IF found THEN
                                   used[   j ] := TRUE;
                                   result[ i ] := j
                               FI
                           FI
                       OD
                   OD
               FI
           FI;
           result
        END # COPRIMETRIPLETS # ;
   []INT cps = COPRIMETRIPLETS 49;
   INT printed := 0;
   FOR i TO UPB cps DO
       IF cps[ i ] /= 0 THEN
           print( ( whole( cps[ i ], -3 ) ) );
           printed +:= 1;
           IF printed MOD 10 = 0 THEN print( ( newline ) ) FI
       FI
   OD;
   print( ( newline, "Found ", whole( printed, 0 ), " coprime triplets up to ", whole( UPB cps, 0 ), newline ) )

END</lang>

Output:
  1  2  3  5  4  7  9  8 11 13
  6 17 19 10 21 23 16 15 29 14
 25 27 22 31 35 12 37 41 18 43
 47 20 33 49 26 45
Found 36 coprime triplets up to 49

AppleScript

<lang applescript>on hcf(a, b)

   repeat until (b = 0)
       set x to a
       set a to b
       set b to x mod b
   end repeat
   
   if (a < 0) then return -a
   return a

end hcf

on coprimeTriplets(max)

   if (max < 3) then return {}
   script o
       property candidates : {}
       property output : {1, 2}
   end script
   
   -- When repeatedly searching for lowest unused numbers, it's faster in
   -- AppleScript to take numbers from a preset list of candidates which
   -- grows shorter from at or near the low end as used numbers are removed
   -- than it is to test increasing numbers of previous numbers each time
   -- against a list that's growing longer with them.
   -- Generate the list of candidates here.
   repeat with i from 3 to max
       set end of o's candidates to i
   end repeat
   set candidateCount to max - 2
   set {p1, p2} to o's output
   set ok to true
   repeat while (ok) -- While suitable coprimes found and candidates left.
       repeat with i from 1 to candidateCount
           set q to item i of o's candidates
           set ok to ((hcf(p1, q) is 1) and (hcf(p2, q) is 1))
           if (ok) then -- q is coprime with both p1 and p2.
               set end of o's output to q
               set p1 to p2
               set p2 to q
               -- Remove q from the candidate list.
               set item i of o's candidates to missing value
               set o's candidates to o's candidates's numbers
               set candidateCount to candidateCount - 1
               set ok to (candidateCount > 0)
               exit repeat
           end if
       end repeat
   end repeat
   
   return o's output

end coprimeTriplets

-- Task code: return coprimeTriplets(49)</lang>

Output:

<lang applescript>{1, 2, 3, 5, 4, 7, 9, 8, 11, 13, 6, 17, 19, 10, 21, 23, 16, 15, 29, 14, 25, 27, 22, 31, 35, 12, 37, 41, 18, 43, 47, 20, 33, 49, 26, 45}</lang>

Arturo

<lang rebol>lst: [1 2]

while [true][

   n: 3
   prev2: lst\[dec dec size lst]
   prev1: last lst
   while -> any? @[
       contains? lst n
       1 <> gcd @[n prev2]
       1 <> gcd @[n prev1]
   ] -> n: n + 1
   if n >= 50 -> break
   'lst ++ n

]

loop split.every:10 lst 'a ->

   print map a => [pad to :string & 3]</lang>
Output:
  1   2   3   5   4   7   9   8  11  13 
  6  17  19  10  21  23  16  15  29  14 
 25  27  22  31  35  12  37  41  18  43 
 47  20  33  49  26  45

Delphi

Translation of: Julia

<lang Delphi> program Coprime_triplets;

{$APPTYPE CONSOLE}

uses

 System.SysUtils;

//https://rosettacode.org/wiki/Greatest_common_divisor#Pascal_.2F_Delphi_.2F_Free_Pascal function Gcd(u, v: longint): longint; begin

 if v = 0 then
   EXIT(u);
 result := Gcd(v, u mod v);

end;

function IsIn(value: Integer; a: TArray<Integer>): boolean; begin

 for var e in a do
   if e = value then
     exit(true);
 Result := false;

end;

function CoprimeTriplets(less_than: Integer = 50): TArray<Integer>; var

 cpt: TArray<Integer>;
 _end: Integer;

begin

 cpt := [1, 2];
 _end := high(cpt);
 while True do
 begin
   var m := 1;
   while IsIn(m, cpt) or (gcd(m, cpt[_end]) <> 1) or (gcd(m, cpt[_end - 1]) <> 1) do
     inc(m);
   if m >= less_than then
     exit(cpt);
   SetLength(cpt, Length(cpt) + 1);
   _end := high(cpt);
   cpt[_end] := m;
 end;

end;

begin

 var trps := CoprimeTriplets();
 writeln('Found ', length(trps), ' coprime triplets less than 50:');
 for var i := 0 to High(trps) do
 begin
   write(trps[i]: 2, ' ');
   if (i + 1) mod 10 = 0 then
     writeln;
 end;
 {$IFNDEF UNIX} Readln; {$ENDIF}

end.</lang>

F#

<lang fsharp> // Coprime triplets: Nigel Galloway. May 12th., 2021 let rec fN g=function 0->g=1 |n->fN n (g%n) let rec fG t n1 n2=seq{let n=seq{1..0x0FFFFFFF}|>Seq.find(fun n->not(List.contains n t) && fN n1 n && fN n2 n) in yield n; yield! cT(n::t) n2 n} let cT=seq{yield 1; yield 2; yield! fG [1;2] 1 2} cT|>Seq.takeWhile((>)50)|>Seq.iter(printf "%d "); printfn "" </lang>

Output:
1 2 3 5 4 7 9 8 11 13 6 17 19 10 21 23 16 15 29 14 25 27 22 31 35 12 37 41 18 43 47 20 33 49 26 45

Factor

Works with: Factor version 0.99 2021-02-05

<lang factor>USING: combinators.short-circuit.smart formatting grouping io kernel make math prettyprint sequences sets ;

coprime? ( m n -- ? ) simple-gcd 1 = ;
coprime-both? ( m n o -- ? ) '[ _ coprime? ] both? ;
triplet? ( hs m n o -- ? )
   { [ coprime-both? nip ] [ 2nip swap in? not ] } && ;
next ( hs m n -- hs' m' n' )
   0 [ 4dup triplet? ] [ 1 + ] until
   nipd pick [ adjoin ] keepd ;
(triplets-upto) ( n -- )
   [ HS{ 1 2 } clone 1 , 1 2 ] dip
   '[ 2dup [ _ < ] both? ] [ dup , next ] while 3drop ;
triplets-upto ( n -- seq ) [ (triplets-upto) ] { } make ;

"Coprime triplets under 50:" print 50 triplets-upto [ 9 group simple-table. nl ] [ length "Found %d terms.\n" printf ] bi</lang>

Output:
Coprime triplets under 50:
1  2  3  5  4  7  9  8  11
13 6  17 19 10 21 23 16 15
29 14 25 27 22 31 35 12 37
41 18 43 47 20 33 49 26 45

Found 36 terms.

FreeBASIC

<lang freebasic>function gcd( a as uinteger, b as uinteger ) as uinteger

   if b = 0 then return a
   return gcd( b, a mod b )

end function

function num_in_array( array() as integer, num as integer ) as boolean

   for i as uinteger = 1 to ubound(array)
       if array(i) = num then return true
   next i
   return false

end function

redim as integer trips(1 to 2) trips(1) = 1 : trips(2) = 2 dim as integer last

do

   last = ubound(trips)
   for q as integer = 1 to 49
       if not num_in_array( trips(), q ) _
         andalso gcd(q, trips(last)) = 1 _
         andalso gcd(q, trips(last-1)) = 1 then
           redim preserve as integer trips( 1 to last+1 )
           trips(last+1) = q
           continue do 
       end if
   next q
   exit do

loop

print using "Found ## terms:"; ubound(trips)

for i as integer = 1 to last

   print trips(i);" ";

next i : print</lang>

Output:
Found 36 terms:
1  2  3  5  4  7  9  8  11  13  6  17  19  10  21  23  16  15  29  14  25  27  22  31  35  12  37  41  18  43  47  20  33  49  26  45

Go

Translation of: Wren
Library: Go-rcu

<lang go>package main

import (

   "fmt"
   "rcu"

)

func contains(a []int, v int) bool {

   for _, e := range a {
       if e == v {
           return true
       }
   }
   return false

}

func main() {

   const limit = 50
   cpt := []int{1, 2}
   for {
       m := 1
       l := len(cpt)
       for contains(cpt, m) || rcu.Gcd(m, cpt[l-1]) != 1 || rcu.Gcd(m, cpt[l-2]) != 1 {
           m++
       }
       if m >= limit {
           break
       }
       cpt = append(cpt, m)
   }
   fmt.Printf("Coprime triplets under %d:\n", limit)
   for i, t := range cpt {
       fmt.Printf("%2d ", t)
       if (i+1)%10 == 0 {
           fmt.Println()
       }
   }
   fmt.Printf("\n\nFound %d such numbers\n", len(cpt))

}</lang>

Output:
Coprime triplets under 50:
 1  2  3  5  4  7  9  8 11 13 
 6 17 19 10 21 23 16 15 29 14 
25 27 22 31 35 12 37 41 18 43 
47 20 33 49 26 45 

Found 36 such numbers

Haskell

<lang haskell>import Data.List (find, transpose, unfoldr) import Data.List.Split (chunksOf) import qualified Data.Set as S


COPRIME TRIPLES --------------------

coprimeTriples :: Integral a => [a] coprimeTriples =

 [1, 2] <> unfoldr go (S.fromList [1, 2], (1, 2))
 where
   go (seen, (a, b)) =
     Just
       (c, (S.insert c seen, (b, c)))
     where
       Just c =
         find
           ( ((&&) . flip S.notMember seen)
               <*> ((&&) . coprime a <*> coprime b)
           )
           [3 ..]

coprime :: Integral a => a -> a -> Bool coprime a b = 1 == gcd a b



TEST -------------------------

main :: IO () main =

 let xs = takeWhile (< 50) coprimeTriples
  in putStrLn (show (length xs) <> " terms below 50:\n")
       >> putStrLn
         ( spacedTable
             justifyRight
             (chunksOf 10 (show <$> xs))
         )



FORMAT ------------------------

spacedTable ::

 (Int -> Char -> String -> String) -> String -> String

spacedTable aligned rows =

 unlines $
   unwords
     . zipWith
       (`aligned` ' ')
       (maximum . fmap length <$> transpose rows)
     <$> rows

justifyRight :: Int -> Char -> String -> String justifyRight n c = (drop . length) <*> (replicate n c <>)</lang>

Output:
36 terms below 50:

 1  2  3  5  4  7  9  8 11 13
 6 17 19 10 21 23 16 15 29 14
25 27 22 31 35 12 37 41 18 43
47 20 33 49 26 45

Julia

Translation of: Phix

<lang julia>function coprime_triplets(less_than = 50)

   cpt = [1, 2]
   while true
       m = 1
       while m in cpt || gcd(m, cpt[end]) != 1 || gcd(m, cpt[end - 1]) != 1
           m += 1
       end
       m >= less_than && return cpt
       push!(cpt, m)
   end

end

trps = coprime_triplets() println("Found $(length(trps)) coprime triplets less than 50:") foreach(p -> print(rpad(p[2], 3), p[1] %10 == 0 ? "\n" : ""), enumerate(trps))

</lang>

Output:

Found 36 coprime triplets less than 50: 1 2 3 5 4 7 9 8 11 13 6 17 19 10 21 23 16 15 29 14 25 27 22 31 35 12 37 41 18 43 47 20 33 49 26 45

Nim

<lang Nim>import math, strutils

var list = @[1, 2]

while true:

 var n = 3
 let prev2 = list[^2]
 let prev1 = list[^1]
 while n in list or gcd(n, prev2) != 1 or gcd(n, prev1) != 1:
   inc n
 if n >= 50: break
 list.add n

echo list.join(" ")</lang>

Output:
1 2 3 5 4 7 9 8 11 13 6 17 19 10 21 23 16 15 29 14 25 27 22 31 35 12 37 41 18 43 47 20 33 49 26 45

Perl

Library: ntheory

<lang perl>use strict; use warnings; use feature <state say>; use ntheory 'gcd'; use List::Util 'first'; use List::Lazy 'lazy_list'; use enum qw(False True); use constant Inf => 1e5;

my $ct = lazy_list {

   state @c = (1, 2);
   state %seen = (1 => True, 2 => True);
   state $min = 3;
   my $g = $c[-2] * $c[-1];
   my $n = first { !$seen{$_} and gcd($_,$g) == 1 } $min .. Inf;
   $seen{$n} = True;
   $min = first { !$seen{$_} } $min .. Inf;
   push @c, $n;
   shift @c

};

my @ct; do { push @ct, $ct->next() } until $ct[-1] > 50; pop @ct; say join ' ', @ct</lang>

Output:
1 2 3 5 4 7 9 8 11 13 6 17 19 10 21 23 16 15 29 14 25 27 22 31 35 12 37 41 18 43 47 20 33 49 26 45

Phix

function coprime_triplets(integer less_than=50)
    sequence cpt = {1,2}
    while true do
        integer m = 1
        while find(m,cpt) 
           or gcd(m,cpt[$])!=1
           or gcd(m,cpt[$-1])!=1 do
            m += 1
        end while
        if m>=less_than then exit end if
        cpt &= m
    end while
    return cpt
end function
sequence res = apply(true,sprintf,{{"%2d"},coprime_triplets()})
printf(1,"Found %d coprime triplets:\n%s\n",{length(res),join_by(res,1,10," ")})
Output:
Found 36 coprime triplets:
 1  2  3  5  4  7  9  8 11 13
 6 17 19 10 21 23 16 15 29 14
25 27 22 31 35 12 37 41 18 43
47 20 33 49 26 45

Raku

<lang perl6>my @coprime-triplets = 1, 2, {

  state %seen = 1, True, 2, True;
  state $min = 3;
  my $g = $^a * $^b;
  my $n = ($min .. *).first: { !%seen{$_} && ($_ gcd $g == 1) }
  %seen{$n} = True;
  if %seen.elems %% 100 { $min = ($min .. *).first: { !%seen{$_} } }
  $n

} … *;

put "Coprime triplets before first > 50:\n", @coprime-triplets[^(@coprime-triplets.first: * > 50, :k)].batch(10)».fmt("%4d").join: "\n";

put "\nOr maybe, minimum Coprime triplets that encompass 1 through 50:\n", @coprime-triplets[0..(@coprime-triplets.first: * == 42, :k)].batch(10)».fmt("%4d").join: "\n";

put "\nAnd for the heck of it: 1001st through 1050th Coprime triplet:\n", @coprime-triplets[1000..1049].batch(10)».fmt("%4d").join: "\n";</lang>

Output:
Coprime triplets before first > 50:
   1    2    3    5    4    7    9    8   11   13
   6   17   19   10   21   23   16   15   29   14
  25   27   22   31   35   12   37   41   18   43
  47   20   33   49   26   45

Or maybe, minimum Coprime triplets that encompass 1 through 50:
   1    2    3    5    4    7    9    8   11   13
   6   17   19   10   21   23   16   15   29   14
  25   27   22   31   35   12   37   41   18   43
  47   20   33   49   26   45   53   28   39   55
  32   51   59   38   61   63   34   65   57   44
  67   69   40   71   73   24   77   79   30   83
  89   36   85   91   46   75   97   52   81   95
  56   87  101   50   93  103   58   99  107   62
 105  109   64  111  113   68  115  117   74  119
 121   48  125  127   42

And for the heck of it: 1001st through 1050th Coprime triplet:
 682 1293 1361  680 1287 1363  686 1299 1367  688
1305 1369  692 1311 1373  694 1317 1375  698 1323
1381  704 1329 1379  706 1335 1387  716 1341 1385
 712 1347 1391  700 1353 1399  710 1359 1393  718
1371 1397  722 1365 1403  724 1377 1405  728 1383

REXX

<lang rexx>/*REXX program finds and display coprime triplets below a specified limit (limit=50).*/ parse arg n cols . /*obtain optional arguments from the CL*/ if n== | n=="," then n= 50 /*Not specified? Then use the default.*/ if cols== | cols=="," then cols= 10 /* " " " " " " */ w= max(3, length( commas(n) ) ) /*width of a number in any column. */

                                    @copt= ' coprime triplets  where  N  < '    commas(n)

if cols>0 then say ' index │'center(@copt, 1 + cols*(w+1) ) if cols>0 then say '───────┼'center("" , 1 + cols*(W+1), '─') !.= 0; @.= !.; idx= 1; $= /*initialize some variables. */

      do #=1
         do j=1;     if @.j  then iterate       /*J in list of coprime triplets?  Skip.*/
         if #<3  then leave                     /*First two entries not defined? Use it*/
                     a= # - 1;    b= # - 2      /*get the last two indices of sequence.*/
         if gcd(j, !.a)\==1  then iterate       /*J not coprime with    last    number?*/
         if gcd(j, !.b)\==1  then iterate       /*"  "     "      "  penultimate   "   */
         leave                                  /*OK, we've found a new coprime triplet*/
         end   /*j*/
      if j>=n  then leave                       /*Have we exceeded the limit? Then quit*/
      @.j= 1;              !.#= j               /*flag a coprime triplet (two methods).*/
      if cols==0  then iterate                  /*Not showing the numbers? Keep looking*/
      $= $  right( commas(j), w)                /*append coprime triplet to output list*/
      if #//cols\==0  then iterate              /*Is output line full? No, keep looking*/
      say center(idx, 7)'│' substr($, 2);    $= /*show output line of coprime triplets.*/
      idx= idx + cols                           /*bump the index for the output line.  */
      end   /*forever*/

if $\== then say center(idx, 7)'│' substr($, 2) /*show any residual output numbers*/ if cols>0 then say '───────┴'center("" , 1 + cols*(w+1), '─') say say 'Found ' commas(#-1) @copt exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ? gcd: procedure; parse arg x,y; do until _==0; _= x//y; x= y; y= _; end; return x</lang>

output   when using the default inputs:
 index │    coprime triplets  where  N  <  50
───────┼─────────────────────────────────────────
   1   │   1   2   3   5   4   7   9   8  11  13
  11   │   6  17  19  10  21  23  16  15  29  14
  21   │  25  27  22  31  35  12  37  41  18  43
  31   │  47  20  33  49  26  45
───────┴─────────────────────────────────────────

Found  36  coprime triplets  where  N  <  50

Ring

<lang ring> see "working..." + nl row = 2 numbers = 1:50 first = 1 second = 2 see "Coprime triplets are:" + nl see "" + first + " " + second + " "

    for n = 3 to len(numbers)
        flag1 = 1
        flag2 = 1
        if first < numbers[n]
           min = first
        else
           min = numbers[n]
        ok
        for m = 2 to min
            if first%m = 0 and numbers[n]%m = 0
               flag1 = 0
               exit
            ok
        next
        if second < numbers[n]
           min = second
        else
           min = numbers[n]
        ok
        for m = 2 to min
            if second%m = 0 and numbers[n]%m = 0 
               flag2 = 0
               exit
            ok
        next
        if flag1 = 1 and flag2 = 1
           see "" + numbers[n] + " "
           first = second 
           second = numbers[n] 
           del(numbers,n)
           row = row+1
           if row%10 = 0
              see nl
           ok
           n = 2
        ok
   next
   see nl + "Found " + row + " coprime triplets" + nl
   see "done..." + nl

</lang>

Output:
working...
Coprime triplets are:
1 2 3 5 4 7 9 8 11 13 
6 17 19 10 21 23 16 15 29 14 
25 27 22 31 35 12 37 41 18 43 
47 20 33 49 26 45 
Found 36 coprime triplets
done...

Wren

Translation of: Phix
Library: Wren-math
Library: Wren-seq
Library: Wren-fmt

<lang ecmascript>import "/math" for Int import "/seq" for Lst import "/fmt" for Fmt

var limit = 50 var cpt = [1, 2]

while (true) {

   var m = 1
   while (cpt.contains(m) || Int.gcd(m, cpt[-1]) != 1 || Int.gcd(m, cpt[-2]) != 1) {
       m = m + 1
   }
   if (m >= limit) break
   cpt.add(m)

} System.print("Coprime triplets under %(limit):") for (chunk in Lst.chunks(cpt, 10)) Fmt.print("$2d", chunk) System.print("\nFound %(cpt.count) such numbers.")</lang>

Output:
Coprime triplets under 50:
 1  2  3  5  4  7  9  8 11 13
 6 17 19 10 21 23 16 15 29 14
25 27 22 31 35 12 37 41 18 43
47 20 33 49 26 45

Found 36 such numbers.