by Arne Sommer

# Primarily Functional with Raku

 Published 5. June 2022.

This is my response to the Perl Weekly Challenge #167.

## Challenge #167.1: Circular Prime

Write a script to find out first `10 circular primes` having at least 3 digits (base 10).

A circular prime is a prime number with the property that the number generated at each intermediate step when cyclically permuting its (base 10) digits will also be prime.

0utput: ```113, 197, 199, 337, 1193, 3779, 11939, 19937, 193939, 199933 ```

113 is a circular prime because it is a prime, as is 131 and 311 (the «cyclically permuting» versions). Note that 131 and 311 are not part of the sequence, as they are permutations of the original one (with the lowest value).

File: circular-prime ```#! /usr/bin/env raku unit sub MAIN (Int \$c where \$c > 1 = 10); #  my \$cp := (100 .. *).grep({ is-circular(\$_) }); #  sub is-circular (\$number) #  { state %seen; #  return if %seen{\$number}; %seen{\$number} = True; #  return unless \$number ~~ /^<>+\$/; #  return unless \$number.is-prime; #  my @digits = \$number.comb; #  for (1 .. @digits.elems -1) -> \$skew #  { my \$rotated = @digits.rotate(\$skew).join; #  return if %seen{\$rotated}; #  return unless \$rotated.is-prime; #  } return True; #  } say \$cp[^\$c].join(", "); #  ```

 The number of circular primes to print, if the default 10 does not suit you.

 A sequence of the circular primes, using a cutsom procedure to sort out the member values.

 Print the first `\$c` values from the sequence, with commas between them.

 Is the current number a circular prime?.

 Using a state variable to store the visited values (i.e. 113, so that we can get rid of 131 and 311 later on).

See docs.raku.org/syntax/state for more information about the variable declarator `state`.

 The number cannot have any other digits that 1, 3, 7 and 9 (any amount of them).

 It has to be a prime.

 Get the individual digits (as rotation is easier on a list than on a string).

 As many times as necessary to get all the rotational variants of the number.

 Do the rotation (with `rotate`).

See docs.raku.org/routine/rotate for more information about `rotate`

 Return (with an implicit False) if we have seen the number before (as described in ).

 Return (with an implicit False) if it is not a prime.

 It did not fail, tahn we have succeeded - and it is a circular prime.

Running it:

```\$ ./circular-prime 113, 197, 199, 337, 1193, 3779, 11939, 19937, 193939, 199933 \$ ./circular-prime 6 113, 197, 199, 337, 1193, 3779 ```

We should, perhaps, show this very fast version:

File: circular-prime-stupid ```#! /usr/bin/env raku say "113, 197, 199, 337, 1193, 3779, 11939, 19937, 193939, 199933"; ```

Does it satisfy the «find out» clause?

Probably not.

(But it is easy to translate this program to virtually any other programming language.)

## Challenge #167.2: Gamma Function

Implement subroutine `gamma()` using the Lanczos approximation method.

Example: ```print gamma(3); # 1.99 print gamma(5); # 24 print gamma(7); # 719.99 ```

We do not actually have to implement anything, as the GNU Scientific Library has done so for us. This library is available in Raku as «Math::Libgsl::Function», using the Nativecall interface.

File: gamma-function ```#! /usr/bin/env raku use Math::Libgsl::Function :ALL; #  unit sub MAIN (Int :u(:\$upto) where \$upto > 0 = 10); #  say "\$_ -> { gamma(\$_) }" for 1 .. \$upto; #  ```

 Load the library, and import everything (`:ALL`).

 Print the values from 1 up to 10, unless another upto value is specified.

 GNU does the job for us.

Running it:

```\$ ./gamma-function 1 -> 1 2 -> 1 3 -> 2 4 -> 6 5 -> 24 6 -> 120 7 -> 720 8 -> 5040 9 -> 40320 10 -> 362880 ```

We did not get the exact same result as specified in the challenge (for 3 and 7), but I assume that Raku is correct - as it has much better rounding error prevention than Perl.

```\$ ./gamma-function -u=20 1 -> 1 2 -> 1 3 -> 2 4 -> 6 5 -> 24 6 -> 120 7 -> 720 8 -> 5040 9 -> 40320 10 -> 362880 11 -> 3628800 12 -> 39916800 13 -> 479001600 14 -> 6227020800 15 -> 87178291200 16 -> 1307674368000 17 -> 20922789888000 18 -> 355687428096000 19 -> 6.402373705728e+15 20 -> 1.21645100408832e+17 ```

Very large values do give rounding errors (using the e+ Scientific notation), but we can avoid that by telling Raku to stick with integers.

File: gamma-function-int ```#! /usr/bin/env raku use Math::Libgsl::Function :ALL; unit sub MAIN (Int :u(:\$upto) where \$upto > 0 = 10); say "\$_ -> { gamma(\$_).Int }" for 1 .. \$upto; #  ```

 Coerce the value to integer with `.Int`.

See docs.raku.org/routine/Int for more information about the `Int` coercer.

Running it:

```\$ ./gamma-function-int -u=20 1 -> 1 2 -> 1 3 -> 2 4 -> 6 5 -> 24 6 -> 120 7 -> 720 8 -> 5040 9 -> 40320 10 -> 362880 11 -> 3628800 12 -> 39916800 13 -> 479001600 14 -> 6227020800 15 -> 87178291200 16 -> 1307674368000 17 -> 20922789888000 18 -> 355687428096000 19 -> 6402373705728000 20 -> 121645100408832000 ```

And that's it.