aboutsummaryrefslogtreecommitdiff
path: root/challenge-155
diff options
context:
space:
mode:
authorMichael Manring <michael@manring>2022-03-12 01:46:33 +0700
committerMichael Manring <michael@manring>2022-03-12 10:53:47 +0700
commitba22ce99dfe4a2ac1185cc57a0382cb4ba234906 (patch)
tree058a5ea8621173225b2a92916ad8f7f65c2e150f /challenge-155
parent05ef2a173372747beaa65322ed4ddfd1e99c449b (diff)
downloadperlweeklychallenge-club-ba22ce99dfe4a2ac1185cc57a0382cb4ba234906.tar.gz
perlweeklychallenge-club-ba22ce99dfe4a2ac1185cc57a0382cb4ba234906.tar.bz2
perlweeklychallenge-club-ba22ce99dfe4a2ac1185cc57a0382cb4ba234906.zip
solutions in GO and refactored ch-2.pl
Diffstat (limited to 'challenge-155')
-rw-r--r--challenge-155/pokgopun/go/README1
-rw-r--r--challenge-155/pokgopun/go/ch-1.go87
-rw-r--r--challenge-155/pokgopun/go/ch-2.go45
-rw-r--r--challenge-155/pokgopun/perl/ch-2.pl60
4 files changed, 150 insertions, 43 deletions
diff --git a/challenge-155/pokgopun/go/README b/challenge-155/pokgopun/go/README
new file mode 100644
index 0000000000..33dfd303a4
--- /dev/null
+++ b/challenge-155/pokgopun/go/README
@@ -0,0 +1 @@
+Solution by PokGoPun
diff --git a/challenge-155/pokgopun/go/ch-1.go b/challenge-155/pokgopun/go/ch-1.go
new file mode 100644
index 0000000000..11106b2af7
--- /dev/null
+++ b/challenge-155/pokgopun/go/ch-1.go
@@ -0,0 +1,87 @@
+package main
+
+import (
+ "fmt"
+ "sort"
+)
+
+func main() {
+ // find the first 8 fortunate number
+ n := 8
+ var (
+ i int
+ j int
+ prime int
+ )
+ // declare with literal to allow append
+ primes := []int{}
+ fortunes := []int{}
+ for len(fortunes) < n {
+ // add next prime if not enough to calculate
+ if i <= len(primes) || j <= len(primes) {
+ primes = append(primes, nextPrime(prime))
+ prime = primes[len(primes)-1]
+ }
+ pn := 1
+ for k := 0; k <= j; k++ {
+ pn *= primes[k]
+ }
+ m := primes[i]
+ if isPrime(pn + m) {
+ //fmt.Println("Found Fortunate number", m)
+ fortunes = append(fortunes, m)
+ // sort slice by standard library which need passing a closure that defined how to sort
+ sort.Slice(fortunes, func(i, j int) bool {
+ return fortunes[i] < fortunes[j]
+ })
+ // remove duplicated slice member by just writing unseen members back to the slice
+ // this does not interfere for range because for range copy the slice before iterating
+ // s to store slice's member already seen, initial value of 0 work because it's not a fortunate number
+ // c is used as index to write unseen member back to the slice and counter of written at the same time
+ // final step is to slice the original slice up to c
+ var c, s int
+ for _, v := range fortunes {
+ if v == s {
+ continue
+ } else {
+ fortunes[c] = v
+ s = v
+ c++
+ }
+ }
+ fortunes = fortunes[:c]
+ j++
+ i = 0
+ } else {
+ i++
+ }
+ }
+ fmt.Println(fortunes)
+}
+
+// function to check for prime number, copy from wiki
+func isPrime(n int) bool {
+ if n <= 3 {
+ return n > 1
+ } else if n%2 == 0 || n%3 == 0 {
+ return false
+ }
+ for i := 5; i*i <= n; i += 6 {
+ if n%i == 0 || n%(i+2) == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// a basic function to generate next prime number, basing on the isPrime function
+// farily works on support calculating fortunate number up to 13 but freeze on 14
+func nextPrime(n int) int {
+ for {
+ n++
+ if isPrime(n) {
+ return n
+ }
+ }
+ return 0
+}
diff --git a/challenge-155/pokgopun/go/ch-2.go b/challenge-155/pokgopun/go/ch-2.go
new file mode 100644
index 0000000000..5674c747b6
--- /dev/null
+++ b/challenge-155/pokgopun/go/ch-2.go
@@ -0,0 +1,45 @@
+package main
+
+import "fmt"
+
+func main() {
+ // Generating the first twelve Pisano periods and their cycles
+ // https://en.wikipedia.org/wiki/Pisano_period => section "Table"
+ for n := 1; n <= 12; n++ {
+ // Sequence for storing Fibonacci numbers
+ fseq := []int{0, 1}
+ // Sequence for calculating Pisano periods
+ var mseq string
+ // Avoid looping more than 1000 times during the calcuation
+ for i := 0; i < 1000; i++ {
+ f1 := fseq[1]
+ f0 := fseq[0]
+ // ascii offset for convert number 0-9 to string 0-9, 10-35 to A-Z, 36-61 to a-z
+ var o int
+ switch {
+ case f0 < 10:
+ o = 48
+ case f0 < 36:
+ o = 55
+ default:
+ o = 61
+ }
+ mseq += string(f0%n + o)
+ // check for repeated cycle when mseq contains even number of charactors, that is when latest index is odd
+ if i%2 == 1 {
+ m := len(mseq) / 2
+ if string(mseq[:m]) == string(mseq[m:]) {
+ fmt.Println("n =", n, ",Pisano period =", m, ",Cycle =", mseq[:m])
+ //fmt.Println("i = ", i)
+ break
+ }
+ }
+ // fn = f1 + f0 as fseq will contain only the latest two values
+ // fseq = append(fseq, f1+f0)
+ // We can just store fn%n instead of fn as (f1+f2)%n seems to be always equal to (f1%n + f0%n)%n
+ fseq = append(fseq, (f1+f0)%n)
+ // fseq to contain only the latest two values
+ fseq = fseq[len(fseq)-2:]
+ }
+ }
+}
diff --git a/challenge-155/pokgopun/perl/ch-2.pl b/challenge-155/pokgopun/perl/ch-2.pl
index 0635eeeae1..12b647666d 100644
--- a/challenge-155/pokgopun/perl/ch-2.pl
+++ b/challenge-155/pokgopun/perl/ch-2.pl
@@ -1,70 +1,44 @@
use strict;
use warnings;
-use Math::Base::Convert;
## Take n from argument if specified when running the script otherwise assign 3 which is the number the challenge's task asked to solve
-## Support n = 1 to 36
my $n = shift;
$n = 3 unless $n;
-die "n has to be an interger between 1 and 36\n" unless $n && $n =~ /^\d+$/ && $n <= 36;
-
-my($conv4n2d,$conv4d2n);
-{
- last unless $n > 10;
- my $baseChar = [@{[0..9,'A'..'Z']}[0..$n-1]];
- $conv4n2d = new Math::Base::Convert( $baseChar, '10');
- $conv4d2n = new Math::Base::Convert('10', $baseChar);
-}
## Initial sequence of Fibonacci numbers, only need two to calculate the next one
-my $fseq = "0 + 1";
+my @f = qw/0 1/;
## Initial Sequence of Fibonacci numbers modulo n, Fi modulo n
my $mseq = '';
my $i = 0;
-## Detect repeated cycle, start from period of j = 1
-
-my $j = 1;
-
{
- ## Calcuate next Fibonacci number
+ ## Calculate next F number, modulo n first before pushing to @f and take off Fi
+ ## this to keep @f minimal while Fi modulo n still produce the same result
- #my $f = eval($fseq);
-
- ## Extracting Fi from the sequence and replace the squence with the latest two numbers
- ## For Fibonacci number modulo 10, we only need the last digit of the number to calculate
+ push @f, ($f[0] + $f[1]) % $n;
+ my $fi = shift @f;
- #my $fi;
- #($fi, $fseq) = $fseq =~ /(\d+) \+ (\d+)/ && $n==10 ? (substr($1,-1), join(" + ",substr($2,-1),substr($f,-1))) : ($1, "$2 + $f");
+ ## Get offset to convert number 0..35 to char 0..9,A..Z ,
+ ## 36... to char a..z and whatever come next in ascii table
+ ## This make the repeated cycle in $mseq comparable
- ## Generate sequence of Fi modulo n
-
- #$mseq .= $fi % $n;
-
- ## Evolve from the logic above for n==10, we can do the same for n > 10 by converting to base n before store/use the last base char
+ my $o = $fi < 10 ? 48 :
+ $fi < 36 ? 55 : 61;
- $fseq =~ /(\w+) \+ (\w+)/;
- my $f = $n > 10 ? $conv4n2d->cnv($1) + $conv4n2d->cnv($2) : $1 + $2;
- my $fi;
- ($fi, $fseq) = $n < 10 ? ($1, "$2 + $f") :
- $n == 10 ? ( substr($1,-1), join(" + ", map{substr($_,-1)} ($2,$f)) ) :
- ( scalar($conv4n2d->cnv(substr($1,-1))), join(" + ", map{substr($_,-1)} ($2,scalar($conv4d2n->cnv($f)))) );
- $mseq .= $n > 10 ? $conv4d2n->cnv($fi % $n) : $fi % $n;
-
- ## When the sequence reach j * 2, check for a repeated period of j
- ## If found, display j and the repeated cycle and exit the loop
- ## If not, continue the loop to check the period of j + 1
+ $mseq .= chr(($fi % $n) + $o);
+
+ ## Check for repeated cycle when number char of sequence is even (i.e. when $i is odd ), compare 1st and 2nd half
- if ( $j * 2 == length($mseq) ){
- if( substr($mseq,0,$j) eq substr($mseq,-$j) ){
- print "#$n Pisano Period is ".$j." => ".substr($mseq,0,$j)."\n";
+ if ( $i % 2 == 1 ){
+ my $l = ($i + 1)/2;
+ if( substr($mseq,0,$l) eq substr($mseq,-$l) ){
+ print "#$n Pisano period is ".$l.", repeated cycle is ".substr($mseq,0,$l)."\n";
last;
}
- $j++;
}
## Continue with the next Fi