From 3a4d95f637d1a157d8c04ad08dfeb14c6f233ca0 Mon Sep 17 00:00:00 2001 From: e78783 Date: Tue, 31 May 2022 09:48:33 +0800 Subject: Week 167 first commit --- challenge-167/cheok-yin-fung/perl/ch-1.pl | 111 ++++++++++++++++++++++++++++++ challenge-167/cheok-yin-fung/perl/ch-2.pl | 87 +++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 challenge-167/cheok-yin-fung/perl/ch-1.pl create mode 100644 challenge-167/cheok-yin-fung/perl/ch-2.pl diff --git a/challenge-167/cheok-yin-fung/perl/ch-1.pl b/challenge-167/cheok-yin-fung/perl/ch-1.pl new file mode 100644 index 0000000000..12f147fd47 --- /dev/null +++ b/challenge-167/cheok-yin-fung/perl/ch-1.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl +# The Weekly Challenge 167 +# Task 1 Circular Prime + +# Array @c_prime Indexing following OEIS:A068652; +# thus set $c_prime[0] as -1 +use v5.24.0; +use warnings; +use List::Util qw/min reduce pairmap any all/; + + + +my @c_prime = ("-1", 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, 97); +my @circular_prime = (2, 3, 5, 7, 11, 13, 17, 37, 79); + +my $num = 19; + + + +while ( scalar @circular_prime < $num ) { + my $candidate = reduce {$a . $b} my_permute(); + + if (prime_test($candidate)) { + my $younger_self = min_self($candidate); + if ($younger_self != $candidate) { + push @c_prime, $candidate + if any {$_ == $younger_self} @circular_prime; + } + elsif (all { prime_test($_) } cyclic($candidate)->@*) { + push @c_prime, $candidate; + push @circular_prime, $candidate; + } + } +} + + + +sub my_permute { + + state $permuted = 1; + state $len = 3; + state $ordered = 0; + + my @digits = (1, 3, 7, 9); + my @a_base4num; + + my $bin = sprintf("%b", $ordered); + # generate bit string here + $bin = ( "0" x ($len*2 - length $bin) ) . $bin; + # convert bit string to base-4 integer representation + @a_base4num = pairmap { $a*2 + $b } split("", $bin); + + $permuted = join "", map { $digits[$_] } @a_base4num; + + if ($permuted =~ /^9+$/) { + $len++; + $ordered = 0; + } + else { + $ordered++; + } + + return $permuted; +} + + + +sub prime_test { + my $n = $_[0]; + return 0 if $n % 3 == 0; + my $k = 1; + while ( 6*$k <= sqrt($n) ) { + return 0 if $n % (6*$k-1) == 0; + return 0 if $n % (6*$k+1) == 0; + $k++; + } + return 1; + # return (1 x $_[0]) !~ /^1?$|^(11+?)\1+$/; + # unable to using Abigail's regex to test for prime numbers + # + # Complex regular subexpression recursion limit (65534) exceeded at ch-1.pl line xxx. +} + + + +sub cyclic { + my $w = $_[0]; + my $ans = [$w]; + my @arr = split "", $w; + for (1..(length $w) - 1) { + push $ans->@*, substr($w, $_). substr($w, 0, $_) + } + return $ans; +} + + + +sub min_self { + return min(cyclic($_[0])->@*); + # not an effective implementation, can be further edited +} + + + + +use Test::More tests=>2; +my $task_requirement = join ", ", @circular_prime[9..9+9]; +ok + $task_requirement eq + "113, 197, 199, 337, 1193, 3779, 11939, 19937, 193939, 199933"; +ok $c_prime[30] == 7793; diff --git a/challenge-167/cheok-yin-fung/perl/ch-2.pl b/challenge-167/cheok-yin-fung/perl/ch-2.pl new file mode 100644 index 0000000000..5a519ad831 --- /dev/null +++ b/challenge-167/cheok-yin-fung/perl/ch-2.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +# The Weekly Challenge 167 +# Task 2 Gamma Function +# simplified "translated" from Maxima code: +# https://mrob.com/pub/ries/lanczos-gamma.html +use v5.24.0; +use warnings; + +say l_gamma($ARGV[0]) if defined($ARGV[0]); + + + +sub lanczos_log_gamma { + my $pi = 4*atan2(1,1); + + my $ln_sqrt_2_pi = log sqrt (2*$pi); + + my $LG_g = 5; + my @lct = ( + 1.000000000190015, + 76.18009172947146, + -86.50532032941677, + 24.01409824083091, + -1.231739572450155, + 0.1208650973866179e-2, + -0.5395239384953e-5 + ); + +=pod Another Set of Paramaters (also from mrob.com) + # which in turn is from from Mihai Preda and/or Paul Godfrey + + my $LG_g = 4.7421875; + my @lct = qw{ + 0.99999999999999709182 + 57.156235665862923517 + -59.597960355475491248 + 14.136097974741747174 + -0.49191381609762019978 + .33994649984811888699e-4 + .46523628927048575665e-4 + -.98374475304879564677e-4 + .15808870322491248884e-3 + -.21026444172410488319e-3 + .21743961811521264320e-3 + -.16431810653676389022e-3 + .84418223983852743293e-4 + -.26190838401581408670e-4 + .36899182659531622704e-5 }; +=cut + + my $z = $_[0]; + $z = $z-1; + my $base = $z + $LG_g + 0.5; + my $sum = 0; + for (reverse (1 .. $#lct)) { + $sum += $lct[$_] / ($z + $_); + } + $sum += $lct[0]; + return (($ln_sqrt_2_pi + log($sum)) - $base) + log($base)*($z+0.5); +} + + + +sub l_gamma { + my $z = $_[0]; + die "This simple script not supported real number smaller than 0.5.\n" + if $z <= 0.5; + + return exp(lanczos_log_gamma($z)); +} + + +use Test::More tests => 10; +# ref: https://en.wikipedia.org/wiki/Gamma_function#Particular_values +my $acceptable_error = 1e-5; +# my $acceptable_error = 1e-7; # Test gamma(11) will fail + +ok abs(l_gamma(1) - 1) < $acceptable_error; +ok abs(l_gamma(1.5) - 0.88622_69254_52758_01364) < $acceptable_error; +ok abs(l_gamma(2) - 1) < $acceptable_error; +ok abs(l_gamma(2.5) - 1.32934_03881_79137_02047) < $acceptable_error; +ok abs(l_gamma(3) - 2) < $acceptable_error; +ok abs(l_gamma(3.5) - 3.32335_09704_47842_55118) < $acceptable_error; +ok abs(l_gamma(4) - 6) < $acceptable_error; +ok abs(l_gamma(5) - 24) < $acceptable_error; +ok abs(l_gamma(7) - 720) < $acceptable_error; +ok abs(l_gamma(11) - 3628800) < $acceptable_error; -- cgit