Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
category:
- Mathematics
from: http://rosettacode.org/wiki/Pisano_period
note: Prime Numbers

View file

@ -0,0 +1,37 @@
The [[wp:Fibonacci_Number|Fibonacci sequence]] taken modulo 2 is a periodic sequence of period 3 : 0, 1, 1, 0, 1, 1, ...
For any integer n, the Fibonacci sequence taken modulo n is periodic and the length of the periodic cycle is referred to as the [[wp:Pisano_period|Pisano period]].
Prime numbers are straightforward; the Pisano period of a prime number '''p''' is simply: '''pisano(p)'''. The Pisano period of a composite number '''c''' may be found in different ways. It may be calculated directly: '''pisano(c)''', which works, but may be time consuming to find, especially for larger integers, or, it may be calculated by finding the [[wp:Least common multiple|least common multiple]] of the Pisano periods of each composite component.
;E.G.:
Given a Pisano period function: pisano(x), and a least common multiple function lcm(x, y):
<big>'''pisano(m × n)''' is equivalent to '''lcm(pisano(m), pisano(n))''' where '''m''' and '''n''' are '''[[wp:Coprime|coprime]]'''</big>
A formulae to calculate the pisano period for integer powers &nbsp; '''k''' &nbsp; of prime numbers &nbsp; '''p''' &nbsp; is:
<big>'''pisano(p<sup>k</sup>) == p<sup>(k-1)</sup>pisano(p)''' </big>
The equation is conjectured, no exceptions have been seen.
If a positive integer &nbsp; '''i''' &nbsp; is split into its prime factors, &nbsp; then the second and first equations above can be applied to generate the pisano period.
;Task
Write 2 functions: pisanoPrime(p,k) and pisano(m).
pisanoPrime(p,k) should return the Pisano period of p<sup>k</sup> where p is prime and k is a positive integer.
pisano(m) should use pisanoPrime to return the Pisano period of m where m is a positive integer.
Print pisanoPrime(p,2) for every prime lower than 15.
Print pisanoPrime(p,1) for every prime lower than 180.
Print pisano(m) for every integer from 1 to 180.
;Related tasks
* &nbsp;[[Fibonacci sequence]]
* &nbsp;[[Prime decomposition]]
* &nbsp;[[Least common multiple]]
<br><br>

View file

@ -0,0 +1,68 @@
F lcm(m, n)
R m I/ gcd(m, n) * n
F get_primes(=n)
[Int] r
L(d) 2 .. n
V q = n I/ d
V m = n % d
L m == 0
r.append(d)
n = q
q = n I/ d
m = n % d
R r
F is_prime(a)
I a == 2
R 1B
I a < 2 | a % 2 == 0
R 0B
L(i) (3 .. Int(sqrt(a))).step(2)
I a % i == 0
R 0B
R 1B
F pisano_period(m)
V p = 0
V c = 1
L(i) 0 .< m * m
p = (p + c) % m
swap(&p, &c)
I p == 0 & c == 1
R i + 1
R 1
F pisano_prime(p, k)
R I is_prime(p) {p ^ (k - 1) * pisano_period(p)} E 0
F pisano(m)
V primes = get_primes(m)
DefaultDict[Int, Int] prime_powers
L(p) primes
prime_powers[p]++
[Int] pps
L(k, v) prime_powers
pps.append(pisano_prime(k, v))
I pps.empty
R 1
V result = pps[0]
L(i) 1 .< pps.len
result = lcm(result, pps[i])
R result
L(p) 2..14
V pp = pisano_prime(p, 2)
I pp > 0
print(pisano_prime(#2, 2) = #..format(p, pp))
print()
L(p) 2..179
V pp = pisano_prime(p, 1)
I pp > 0
print(pisano_prime(#3, 1) = #..format(p, pp))
print()
print(pisano(n) for integers 'n' from 1 to 180 are:)
L(n) 1..180
print(#3.format(pisano(n)), end' I n % 15 == 0 {"\n"} E )

View file

@ -0,0 +1,26 @@
USING: formatting fry grouping io kernel math math.functions
math.primes math.primes.factors math.ranges sequences ;
: pisano-period ( m -- n )
[ 0 1 ] dip [ sq <iota> ] [ ] bi
'[ drop tuck + _ mod 2dup [ zero? ] [ 1 = ] bi* and ]
find 3nip [ 1 + ] [ 1 ] if* ;
: pisano-prime ( p k -- n )
over prime? [ "p must be prime." throw ] unless
^ pisano-period ;
: pisano ( m -- n )
group-factors [ first2 pisano-prime ] [ lcm ] map-reduce ;
: show-pisano ( upto m -- )
[ primes-upto ] dip
[ 2dup pisano-prime "%d %d pisano-prime = %d\n" printf ]
curry each nl ;
15 2 show-pisano
180 1 show-pisano
"n pisano for integers 'n' from 2 to 180:" print
2 180 [a,b] [ pisano ] map 15 group
[ [ "%3d " printf ] each nl ] each

View file

@ -0,0 +1,136 @@
package main
import "fmt"
func gcd(a, b uint) uint {
if b == 0 {
return a
}
return gcd(b, a%b)
}
func lcm(a, b uint) uint {
return a / gcd(a, b) * b
}
func ipow(x, p uint) uint {
prod := uint(1)
for p > 0 {
if p&1 != 0 {
prod *= x
}
p >>= 1
x *= x
}
return prod
}
// Gets the prime decomposition of n.
func getPrimes(n uint) []uint {
var primes []uint
for i := uint(2); i <= n; i++ {
div := n / i
mod := n % i
for mod == 0 {
primes = append(primes, i)
n = div
div = n / i
mod = n % i
}
}
return primes
}
// OK for 'small' numbers.
func isPrime(n uint) bool {
switch {
case n < 2:
return false
case n%2 == 0:
return n == 2
case n%3 == 0:
return n == 3
default:
d := uint(5)
for d*d <= n {
if n%d == 0 {
return false
}
d += 2
if n%d == 0 {
return false
}
d += 4
}
return true
}
}
// Calculates the Pisano period of 'm' from first principles.
func pisanoPeriod(m uint) uint {
var p, c uint = 0, 1
for i := uint(0); i < m*m; i++ {
p, c = c, (p+c)%m
if p == 0 && c == 1 {
return i + 1
}
}
return 1
}
// Calculates the Pisano period of p^k where 'p' is prime and 'k' is a positive integer.
func pisanoPrime(p uint, k uint) uint {
if !isPrime(p) || k == 0 {
return 0 // can't do this one
}
return ipow(p, k-1) * pisanoPeriod(p)
}
// Calculates the Pisano period of 'm' using pisanoPrime.
func pisano(m uint) uint {
primes := getPrimes(m)
primePowers := make(map[uint]uint)
for _, p := range primes {
primePowers[p]++
}
var pps []uint
for k, v := range primePowers {
pps = append(pps, pisanoPrime(k, v))
}
if len(pps) == 0 {
return 1
}
if len(pps) == 1 {
return pps[0]
}
f := pps[0]
for i := 1; i < len(pps); i++ {
f = lcm(f, pps[i])
}
return f
}
func main() {
for p := uint(2); p < 15; p++ {
pp := pisanoPrime(p, 2)
if pp > 0 {
fmt.Printf("pisanoPrime(%2d: 2) = %d\n", p, pp)
}
}
fmt.Println()
for p := uint(2); p < 180; p++ {
pp := pisanoPrime(p, 1)
if pp > 0 {
fmt.Printf("pisanoPrime(%3d: 1) = %d\n", p, pp)
}
}
fmt.Println()
fmt.Println("pisano(n) for integers 'n' from 1 to 180 are:")
for n := uint(1); n <= 180; n++ {
fmt.Printf("%3d ", pisano(n))
if n != 1 && n%15 == 0 {
fmt.Println()
}
}
fmt.Println()
}

View file

@ -0,0 +1,155 @@
import qualified Data.Text as T
main = do
putStrLn "PisanoPrime(p,2) for prime p lower than 15"
putStrLn . see 15 . map (`pisanoPrime` 2) . filter isPrime $ [1 .. 15]
putStrLn "PisanoPrime(p,1) for prime p lower than 180"
putStrLn . see 15 . map (`pisanoPrime` 1) . filter isPrime $ [1 .. 180]
let ns = [1 .. 180] :: [Int]
let xs = map pisanoPeriod ns
let ys = map pisano ns
let zs = map pisanoConjecture ns
putStrLn "Pisano(m) for m from 1 to 180"
putStrLn . see 15 $ map pisano [1 .. 180]
putStrLn $
"map pisanoPeriod [1..180] == map pisano [1..180] = " ++ show (xs == ys)
putStrLn $
"map pisanoPeriod [1..180] == map pisanoConjecture [1..180] = " ++
show (ys == zs)
bagOf :: Int -> [a] -> [[a]]
bagOf _ [] = []
bagOf n xs =
let (us, vs) = splitAt n xs
in us : bagOf n vs
see
:: Show a
=> Int -> [a] -> String
see n =
unlines .
map unwords . bagOf n . map (T.unpack . T.justifyRight 3 ' ' . T.pack . show)
fibMod
:: Integral a
=> a -> [a]
fibMod 1 = repeat 0
fibMod n = fib
where
fib = 0 : 1 : zipWith (\x y -> rem (x + y) n) fib (tail fib)
pisanoPeriod
:: Integral a
=> a -> a
pisanoPeriod m
| m <= 0 = 0
pisanoPeriod 1 = 1
pisanoPeriod m = go 1 (tail $ fibMod m)
where
go t (0:1:_) = t
go t (_:xs) = go (succ t) xs
powMod
:: Integral a
=> a -> a -> a -> a
powMod _ _ k
| k < 0 = error "negative power"
powMod m _ _
| 1 == abs m = 0
powMod m p k
| 1 == abs p = mod v m
where
v
| 1 == p || even k = 1
| otherwise = p
powMod m p k = go p k
where
to x y = mod (x * y) m
go _ 0 = 1
go u 1 = mod u m
go u i
| even i = to w w
| otherwise = to u (to w w)
where
w = go u (quot i 2)
-- Fermat primality test
probablyPrime
:: Integral a
=> a -> Bool
probablyPrime p
| p < 2 || even p = 2 == p
| otherwise = 1 == powMod p 2 (p - 1)
primes
:: Integral a
=> [a]
primes =
2 :
3 :
5 :
7 :
[ p
| p <- [11,13 ..]
, isPrime p ]
limitDivisor
:: Integral a
=> a -> a
limitDivisor = floor . (+ 0.05) . sqrt . fromIntegral
isPrime
:: Integral a
=> a -> Bool
isPrime p
| not $ probablyPrime p = False
isPrime p = go primes
where
stop = limitDivisor p
go (n:_)
| stop < n = True
go (n:ns) = (0 /= rem p n) && go ns
go [] = True
factor
:: Integral a
=> a -> [(a, a)]
factor n
| n <= 1 = []
factor n = go n primes
where
fun x d c
| 0 /= rem x d = (x, c)
| otherwise = fun (quot x d) d (succ c)
go 1 _ = []
go _ [] = []
go x (d:ds)
| 0 /= rem x d = go x $ dropWhile ((0 /=) . rem x) ds
go x (d:ds) =
let (u, c) = fun (quot x d) d 1
in (d, c) : go u ds
pisanoPrime
:: Integral a
=> a -> a -> a
pisanoPrime p k
| p <= 0 || k < 0 = 0
pisanoPrime p k = pisanoPeriod $ p ^ k
pisano
:: Integral a
=> a -> a
pisano m
| m < 1 = 0
pisano 1 = 1
pisano m = foldl1 lcm . map (uncurry pisanoPrime) $ factor m
pisanoConjecture
:: Integral a
=> a -> a
pisanoConjecture m
| m < 1 = 0
pisanoConjecture 1 = 1
pisanoConjecture m = foldl1 lcm . map (uncurry pisanoPrime') $ factor m
where
pisanoPrime' p k = (p ^ (k - 1)) * pisanoPeriod p

View file

@ -0,0 +1,263 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class PisanoPeriod {
public static void main(String[] args) {
System.out.printf("Print pisano(p^2) for every prime p lower than 15%n");
for ( long i = 2 ; i < 15 ; i++ ) {
if ( isPrime(i) ) {
long n = i*i;
System.out.printf("pisano(%d) = %d%n", n, pisano(n));
}
}
System.out.printf("%nPrint pisano(p) for every prime p lower than 180%n");
for ( long n = 2 ; n < 180 ; n++ ) {
if ( isPrime(n) ) {
System.out.printf("pisano(%d) = %d%n", n, pisano(n));
}
}
System.out.printf("%nPrint pisano(n) for every integer from 1 to 180%n");
for ( long n = 1 ; n <= 180 ; n++ ) {
System.out.printf("%3d ", pisano(n));
if ( n % 10 == 0 ) {
System.out.printf("%n");
}
}
}
private static final boolean isPrime(long test) {
if ( test == 2 ) {
return true;
}
if ( test % 2 == 0 ) {
return false;
}
for ( long i = 3 ; i <= Math.sqrt(test) ; i += 2 ) {
if ( test % i == 0 ) {
return false;
}
}
return true;
}
private static Map<Long,Long> PERIOD_MEMO = new HashMap<>();
static {
PERIOD_MEMO.put(2L, 3L);
PERIOD_MEMO.put(3L, 8L);
PERIOD_MEMO.put(5L, 20L);
}
// See http://webspace.ship.edu/msrenault/fibonacci/fib.htm
private static long pisano(long n) {
if ( PERIOD_MEMO.containsKey(n) ) {
return PERIOD_MEMO.get(n);
}
if ( n == 1 ) {
return 1;
}
Map<Long,Long> factors = getFactors(n);
// Special cases
// pisano(2^k) = 3*n/2
if ( factors.size() == 1 & factors.get(2L) != null && factors.get(2L) > 0 ) {
long result = 3 * n / 2;
PERIOD_MEMO.put(n, result);
return result;
}
// pisano(5^k) = 4*n
if ( factors.size() == 1 & factors.get(5L) != null && factors.get(5L) > 0 ) {
long result = 4*n;
PERIOD_MEMO.put(n, result);
return result;
}
// pisano(2*5^k) = 6*n
if ( factors.size() == 2 & factors.get(2L) != null && factors.get(2L) == 1 && factors.get(5L) != null && factors.get(5L) > 0 ) {
long result = 6*n;
PERIOD_MEMO.put(n, result);
return result;
}
List<Long> primes = new ArrayList<>(factors.keySet());
long prime = primes.get(0);
if ( factors.size() == 1 && factors.get(prime) == 1 ) {
List<Long> divisors = new ArrayList<>();
if ( n % 10 == 1 || n % 10 == 9 ) {
for ( long divisor : getDivisors(prime-1) ) {
if ( divisor % 2 == 0 ) {
divisors.add(divisor);
}
}
}
else {
List<Long> pPlus1Divisors = getDivisors(prime+1);
for ( long divisor : getDivisors(2*prime+2) ) {
if ( ! pPlus1Divisors.contains(divisor) ) {
divisors.add(divisor);
}
}
}
Collections.sort(divisors);
for ( long divisor : divisors ) {
if ( fibModIdentity(divisor, prime) ) {
PERIOD_MEMO.put(prime, divisor);
return divisor;
}
}
throw new RuntimeException("ERROR 144: Divisor not found.");
}
long period = (long) Math.pow(prime, factors.get(prime)-1) * pisano(prime);
for ( int i = 1 ; i < primes.size() ; i++ ) {
prime = primes.get(i);
period = lcm(period, (long) Math.pow(prime, factors.get(prime)-1) * pisano(prime));
}
PERIOD_MEMO.put(n, period);
return period;
}
// Use Matrix multiplication to compute Fibonacci numbers.
private static boolean fibModIdentity(long n, long mod) {
long aRes = 0;
long bRes = 1;
long cRes = 1;
long aBase = 0;
long bBase = 1;
long cBase = 1;
while ( n > 0 ) {
if ( n % 2 == 1 ) {
long temp1 = 0, temp2 = 0, temp3 = 0;
if ( aRes > SQRT || aBase > SQRT || bRes > SQRT || bBase > SQRT || cBase > SQRT || cRes > SQRT ) {
temp1 = (multiply(aRes, aBase, mod) + multiply(bRes, bBase, mod)) % mod;
temp2 = (multiply(aBase, bRes, mod) + multiply(bBase, cRes, mod)) % mod;
temp3 = (multiply(bBase, bRes, mod) + multiply(cBase, cRes, mod)) % mod;
}
else {
temp1 = ((aRes*aBase % mod) + (bRes*bBase % mod)) % mod;
temp2 = ((aBase*bRes % mod) + (bBase*cRes % mod)) % mod;
temp3 = ((bBase*bRes % mod) + (cBase*cRes % mod)) % mod;
}
aRes = temp1;
bRes = temp2;
cRes = temp3;
}
n >>= 1L;
long temp1 = 0, temp2 = 0, temp3 = 0;
if ( aBase > SQRT || bBase > SQRT || cBase > SQRT ) {
temp1 = (multiply(aBase, aBase, mod) + multiply(bBase, bBase, mod)) % mod;
temp2 = (multiply(aBase, bBase, mod) + multiply(bBase, cBase, mod)) % mod;
temp3 = (multiply(bBase, bBase, mod) + multiply(cBase, cBase, mod)) % mod;
}
else {
temp1 = ((aBase*aBase % mod) + (bBase*bBase % mod)) % mod;
temp2 = ((aBase*bBase % mod) + (bBase*cBase % mod)) % mod;
temp3 = ((bBase*bBase % mod) + (cBase*cBase % mod)) % mod;
}
aBase = temp1;
bBase = temp2;
cBase = temp3;
}
return aRes % mod == 0 && bRes % mod == 1 && cRes % mod == 1;
}
private static final long SQRT = (long) Math.sqrt(Long.MAX_VALUE);
// Result is a*b % mod, without overflow.
public static final long multiply(long a, long b, long modulus) {
//System.out.println(" multiply : a = " + a + ", b = " + b + ", mod = " + modulus);
long x = 0;
long y = a % modulus;
long t;
while ( b > 0 ) {
if ( b % 2 == 1 ) {
t = x + y;
x = (t > modulus ? t-modulus : t);
}
t = y << 1;
y = (t > modulus ? t-modulus : t);
b >>= 1;
}
//System.out.println(" multiply : answer = " + (x % modulus));
return x % modulus;
}
private static final List<Long> getDivisors(long number) {
List<Long> divisors = new ArrayList<>();
long sqrt = (long) Math.sqrt(number);
for ( long i = 1 ; i <= sqrt ; i++ ) {
if ( number % i == 0 ) {
divisors.add(i);
long div = number / i;
if ( div != i ) {
divisors.add(div);
}
}
}
return divisors;
}
public static long lcm(long a, long b) {
return a*b/gcd(a,b);
}
public static long gcd(long a, long b) {
if ( b == 0 ) {
return a;
}
return gcd(b, a%b);
}
private static final Map<Long,Map<Long,Long>> allFactors = new TreeMap<Long,Map<Long,Long>>();
static {
Map<Long,Long> factors = new TreeMap<Long,Long>();
factors.put(2L, 1L);
allFactors.put(2L, factors);
}
public static Long MAX_ALL_FACTORS = 100000L;
public static final Map<Long,Long> getFactors(Long number) {
if ( allFactors.containsKey(number) ) {
return allFactors.get(number);
}
Map<Long,Long> factors = new TreeMap<Long,Long>();
if ( number % 2 == 0 ) {
Map<Long,Long> factorsdDivTwo = getFactors(number/2);
factors.putAll(factorsdDivTwo);
factors.merge(2L, 1L, (v1, v2) -> v1 + v2);
if ( number < MAX_ALL_FACTORS ) {
allFactors.put(number, factors);
}
return factors;
}
boolean prime = true;
long sqrt = (long) Math.sqrt(number);
for ( long i = 3 ; i <= sqrt ; i += 2 ) {
if ( number % i == 0 ) {
prime = false;
factors.putAll(getFactors(number/i));
factors.merge(i, 1L, (v1, v2) -> v1 + v2);
if ( number < MAX_ALL_FACTORS ) {
allFactors.put(number, factors);
}
return factors;
}
}
if ( prime ) {
factors.put(number, 1L);
if ( number < MAX_ALL_FACTORS ) {
allFactors.put(number, factors);
}
}
return factors;
}
}

View file

@ -0,0 +1,34 @@
using Primes
const pisanos = Dict{Int, Int}()
function pisano(p)
p < 2 && return 1
(i = get(pisanos, p, 0)) > 0 && return i
lastn, n = 0, 1
for i in 1:p^2
lastn, n = n, (lastn + n) % p
if lastn == 0 && n == 1
pisanos[p] = i
return i
end
end
return 1
end
pisanoprime(p, k) = (@assert(isprime(p)); p^(k-1) * pisano(p))
pisanotask(n) = mapreduce(p -> pisanoprime(p[1], p[2]), lcm, collect(factor(n)), init=1)
for i in 1:15
if isprime(i)
println("pisanoPrime($i, 2) = ", pisanoprime(i, 2))
end
end
for i in 1:180
if isprime(i)
println("pisanoPrime($i, 1) = ", pisanoprime(i, 1))
end
end
println("\nPisano(n) for n from 2 to 180:\n", [pisano(i) for i in 2:180])
println("\nPisano(n) using pisanoPrime for n from 2 to 180:\n", [pisanotask(i) for i in 2:180])

View file

@ -0,0 +1,71 @@
import math, strformat, tables
func primes(n: Positive): seq[int] =
## Return the list of prime divisors of "n".
var n = n.int
for d in 2..n:
var q = n div d
var m = n mod d
while m == 0:
result.add d
n = q
q = n div d
m = n mod d
func isPrime(n: Positive): bool =
## Return true if "n" is prime.
if n < 2: return false
if n mod 2 == 0: return n == 2
if n mod 3 == 0: return n == 3
var d = 5
while d <= sqrt(n.toFloat).int:
if n mod d == 0: return false
inc d, 2
if n mod d == 0: return false
inc d, 4
result = true
func pisanoPeriod(m: Positive): int =
## Calculate the Pisano period of 'm' from first principles.
var p = 0
var c = 1
for i in 0..<m*m:
p = (p + c) mod m
swap p, c
if p == 0 and c == 1: return i + 1
result = 1
func pisanoPrime(p, k: Positive): int =
## Calculate the Pisano period of p^k where 'p' is prime and 'k' is a positive integer.
if p.isPrime: p^(k-1) * p.pisanoPeriod() else: 0
func pisano(m: Positive): int =
## Calculate the Pisano period of 'm' using pisanoPrime.
let primes = m.primes
var primePowers = primes.toCountTable
var pps: seq[int]
for k, v in primePowers.pairs:
pps.add pisanoPrime(k, v)
if pps.len == 0: return 1
result = pps[0]
for i in 1..pps.high:
result = lcm(result, pps[i])
when isMainModule:
for p in 2..14:
let pp = pisanoPrime(p, 2)
if pp > 0:
echo &"pisanoPrime({p:2}, 2) = {pp}"
echo()
for p in 2..179:
let pp = pisanoPrime(p, 1)
if pp > 0:
echo &"pisanoPrime({p:3}, 1) = {pp}"
echo()
echo "pisano(n) for integers 'n' from 1 to 180 are:"
for n in 1..180:
stdout.write &"{pisano(n):3}", if n mod 15 == 0: '\n' else: ' '

View file

@ -0,0 +1,22 @@
use strict;
use warnings;
use feature 'say';
use ntheory qw(primes factor_exp lcm);
sub pisano_period_pp {
my($a, $b, $n, $k) = (0, 1, $_[0]**$_[1]);
while (++$k) {
($a, $b) = ($b, ($a+$b) % $n);
return $k if $a == 0 and $b == 1;
}
}
sub pisano_period {
(lcm map { pisano_period_pp($$_[0],$$_[1]) } factor_exp($_[0])) or 1;
}
sub display { (sprintf "@{['%5d' x @_]}", @_) =~ s/(.{75})/$1\n/gr }
say "Pisano periods for squares of primes p <= 50:\n", display( map { pisano_period_pp($_, 2) } @{primes(1, 50)} ),
"\nPisano periods for primes p <= 180:\n", display( map { pisano_period_pp($_, 1) } @{primes(1, 180)} ),
"\n\nPisano periods for integers n from 1 to 180:\n", display( map { pisano_period ($_ ) } 1..180 );

View file

@ -0,0 +1,60 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">pisano_period</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Calculates the Pisano period of 'm' from first principles. (copied from Go)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">*</span><span style="color: #000000;">m</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">pisanoPrime</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">is_prime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">pisano_period</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">pisano</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Calculates the Pisano period of 'm' using pisanoPrime.</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">prime_factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">true</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">get_maxprime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">))&</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">pps</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">p</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">pps</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pps</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pisanoPrime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">))</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">lcm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pps</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lim</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- test harness</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pisanoPrimes"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_prime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pdx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">lim</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">7</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n "</span><span style="color: #0000FF;">)</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">pdx</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">", "</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(%3d,%d)=%3d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pisanoPrime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)})</span>
<span style="color: #000000;">pdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">p</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">p</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">180</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p180</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">180</span> <span style="color: #008080;">do</span> <span style="color: #000000;">p180</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">pisano</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pisano(1..180):\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p180</span><span style="color: #0000FF;">,{</span><span style="color: #004600;">pp_IntFmt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%4d"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_IntCh</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">})</span>
<!--

View file

@ -0,0 +1,40 @@
from sympy import isprime, lcm, factorint, primerange
from functools import reduce
def pisano1(m):
"Simple definition"
if m < 2:
return 1
lastn, n = 0, 1
for i in range(m ** 2):
lastn, n = n, (lastn + n) % m
if lastn == 0 and n == 1:
return i + 1
return 1
def pisanoprime(p, k):
"Use conjecture π(p ** k) == p ** (k 1) * π(p) for prime p and int k > 1"
assert isprime(p) and k > 0
return p ** (k - 1) * pisano1(p)
def pisano_mult(m, n):
"pisano(m*n) where m and n assumed coprime integers"
return lcm(pisano1(m), pisano1(n))
def pisano2(m):
"Uses prime factorization of m"
return reduce(lcm, (pisanoprime(prime, mult)
for prime, mult in factorint(m).items()), 1)
if __name__ == '__main__':
for n in range(1, 181):
assert pisano1(n) == pisano2(n), "Wall-Sun-Sun prime exists??!!"
print("\nPisano period (p, 2) for primes less than 50\n ",
[pisanoprime(prime, 2) for prime in primerange(1, 50)])
print("\nPisano period (p, 1) for primes less than 180\n ",
[pisanoprime(prime, 1) for prime in primerange(1, 180)])
print("\nPisano period (p) for integers 1 to 180")
for i in range(1, 181):
print(" %3d" % pisano2(i), end="" if i % 10 else "\n")

View file

@ -0,0 +1,68 @@
[ dip number$
over size -
space swap of
swap join echo$ ] is recho ( n n --> )
[ witheach
[ 4 recho
i^ 1+ 10 mod
0 = if cr ] ] is prettyecho ( [ --> )
[ primefactors size 1 = ] is isprime ( n --> b )
[ dup [] = if done
[] [] rot
witheach
[ over [] = iff
join done
over 0 peek over = iff
join done
dip [ nested join ]
nested ]
nested join ] is runs ( [ --> [ )
[ stack ] is modulus ( --> s )
[ dip dup 1 - **
swap dup 2 < iff
[ 2drop 1 ] done
modulus put
0 temp put
0 1
[ 1 temp tally
tuck +
modulus share mod
dup 1 = until
over 0 = until ]
2drop
modulus release
temp take * ] is pisanoprime ( n n --> n )
[ dup 2 < iff
[ drop 1 ] done
primefactors
runs
[] swap
witheach
[ dup 0 peek
swap size
pisanoprime
join ]
behead swap
witheach lcm ] is pisano ( n --> n )
[] 15 times
[ i^ isprime if
[ i^ 2 pisanoprime
join ] ]
prettyecho
cr cr
[] 180 times
[ i^ isprime if
[ i^ 1 pisanoprime
join ] ]
prettyecho
cr cr
[] 180 times
[ i^ 1+ pisano join ]
prettyecho

View file

@ -0,0 +1,37 @@
/*REXX pgm calculates pisano period for a range of N, and pisanoPrime(N,m) [for primes]*/
numeric digits 500 /*ensure enough decimal digits for Fib.*/
parse arg lim.1 lim.2 lim.3 . /*obtain optional arguments from the CL*/
if lim.1=='' | lim.1=="," then lim.1= 15 - 1 /*Not specified? Then use the default.*/
if lim.2=='' | lim.2=="," then lim.2= 180 - 1 /* " " " " " " */
if lim.3=='' | lim.3=="," then lim.3= 180 /* " " " " " " */
call Fib /* " " Fibonacci numbers. */
do i=1 for max(lim.1, lim.2, lim.3); call pisano(i) /*find pisano periods.*/
end /*i*/; w= length(i)
do j=1 for 2; #= word(2 1, j)
do p=1 for lim.j; if \isPrime(p) then iterate /*Not prime? Skip this number.*/
say ' pisanoPrime('right(p, w)", "#') = 'right( pisanoPrime(p, #), 5)
end /*p*/; say
end /*j*/
say center(' pisano numbers for 1'lim.3" ", 20*4 - 1, "") /*display a title.*/
$=
do j=1 for lim.3; $= $ right(@.j, w) /*append pisano number to the $ list.*/
if j//20==0 then do; say substr($, 2); $=; end /*display 20 numbers to a line*/
end /*j*/
say substr($, 2) /*possible display any residuals──►term*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
fib: procedure expose fib.; parse arg x; fib.=.; if x=='' then x= 1000
fib.0= 0; fib.1= 1; if fib.x\==. then return fib.x
do k=2 for x-1; a= k-1; b= k-2; fib.k= fib.a + fib.b
end /*k*/; return fib.k
/*──────────────────────────────────────────────────────────────────────────────────────*/
isPrime: parse arg n; if n<11 then return pos(n, '2 3 5 7')>0; if n//2==0 then return 0
do k=3 by 2 while k*k<=n; if n//k==0 then return 0; end /*k*/; return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
pisano: procedure expose @. fib.; parse arg m; if m==1 then do; @.m=1; return 1; end
do k=1; _= k+1; if fib.k//m==0 & fib._//m==1 then leave
end /*k*/; @.m= k; return k
/*──────────────────────────────────────────────────────────────────────────────────────*/
pisanoPrime: procedure expose @. fib.; parse arg m,n; return m**(n-1) * pisano(m)

View file

@ -0,0 +1,25 @@
use Prime::Factor;
constant @fib := 1,1,*+**;
my %cache;
multi pisano-period (Int $p where *.is-prime, Int $k where * > 0 = 1) {
return %cache{"$p|$k"} if %cache{"$p|$k"};
my $fibmod = @fib.map: * % $p**$k;
%cache{"$p|$k"} = (1..*).first: { !$fibmod[$_-1] and ($fibmod[$_] == 1) }
}
multi pisano-period (Int $p where * > 0 ) {
[lcm] prime-factors($p).Bag.map: { samewith .key, .value }
}
put "Pisano period (p, 2) for primes less than 50";
put (map { pisano-period($_, 2) }, ^50 .grep: *.is-prime )».fmt('%4d');
put "\nPisano period (p, 1) for primes less than 180";
.put for (map { pisano-period($_, 1) }, ^180 .grep: *.is-prime )».fmt('%4d').batch(15);
put "\nPisano period (p, 1) for integers 1 to 180";
.put for (1..180).map( { pisano-period($_) } )».fmt('%4d').batch(15);

View file

@ -0,0 +1,25 @@
func pisano_period_pp(p,k) is cached {
assert(k.is_pos, "k = #{k} must be positive")
assert(p.is_prime, "p = #{p} must be prime")
var (a, b, n) = (0, 1, p**k)
1..Inf -> first_by {
(a, b) = (b, (a+b) % n)
(a == 0) && (b == 1)
}
}
func pisano_period(n) {
n.factor_map {|p,k| pisano_period_pp(p, k) }.lcm
}
say "Pisano periods for squares of primes p <= 15:"
say 15.primes.map {|p| pisano_period_pp(p, 2) }
say "\nPisano periods for primes p <= 180:"
say 180.primes.map {|p| pisano_period_pp(p, 1) }
say "\nPisano periods for integers n from 1 to 180:"
say pisano_period.map(1..180)

View file

@ -0,0 +1,22 @@
func pisano_period_pp(p, k=1) {
(p - kronecker(5, p)).divisors.first_by {|d| fibmod(d, p) == 0 } * p**(k-1)
}
func pisano_period(n) {
return 0 if (n <= 0)
return 1 if (n == 1)
var d = n.factor_map {|p,k| pisano_period_pp(p, k) }.lcm
3.times {|k|
var t = d<<k
if ((fibmod(t, n) == 0) && (fibmod(t+1, n) == 1)) {
return t
}
}
}
for k in (1..8) {
say ("Pisano(F_#{k}) = ", pisano_period(2**(2**k) + 1))
}

View file

@ -0,0 +1,58 @@
import "/math" for Int
import "/fmt" for Fmt
// Calculates the Pisano period of 'm' from first principles.
var pisanoPeriod = Fn.new { |m|
var p = 0
var c = 1
for (i in 0...m*m) {
var t = p
p = c
c = (t + c) % m
if (p == 0 && c == 1) return i + 1
}
return 1
}
// Calculates the Pisano period of p^k where 'p' is prime and 'k' is a positive integer.
var pisanoPrime = Fn.new { |p, k|
if (!Int.isPrime(p) || k == 0) return 0 // can't do this one
return p.pow(k-1) * pisanoPeriod.call(p)
}
// Calculates the Pisano period of 'm' using pisanoPrime.
var pisano = Fn.new { |m|
var primes = Int.primeFactors(m)
var primePowers = {}
for (p in primes) {
var v = primePowers[p]
primePowers[p] = v ? v + 1 : 1
}
var pps = []
for (me in primePowers) pps.add(pisanoPrime.call(me.key, me.value))
if (pps.count == 0) return 1
if (pps.count == 1) return pps[0]
var f = pps[0]
var i = 1
while (i < pps.count) {
f = Int.lcm(f, pps[i])
i = i + 1
}
return f
}
for (p in 2..14) {
var pp = pisanoPrime.call(p, 2)
if (pp > 0) Fmt.print("pisanoPrime($2d: 2) = $d", p, pp)
}
System.print()
for (p in 2..179) {
var pp = pisanoPrime.call(p, 1)
if (pp > 0) Fmt.print("pisanoPrime($3d: 1) = $d", p, pp)
}
System.print("\npisano(n) for integers 'n' from 1 to 180 are:")
for (n in 1..180) {
Fmt.write("$3d ", pisano.call(n))
if (n != 1 && n%15 == 0) System.print()
}
System.print()

View file

@ -0,0 +1,15 @@
var [const] BI=Import("zklBigNum"); // libGMP
fcn pisanoPeriod(p){
if(p<2) return(0);
lastn,n,t := 0,1,0;
foreach i in ([0..p*p]){
t,n,lastn = n, (lastn + n) % p, t;
if(lastn==0 and n==1) return(i + 1);
}
1
}
fcn pisanoPrime(p,k){
_assert_(BI(p).probablyPrime(), "%s is not a prime number".fmt(p));
pisanoPeriod(p.pow(k))
}

View file

@ -0,0 +1,7 @@
println("Pisano period (p, 2) for primes less than 50:");
[1..50].pump(List,BI,"probablyPrime",Void.Filter, pisanoPrime.fp1(2))
.concat(" "," ").println();
println("Pisano period (p, 1) for primes less than 180:");
[1..180].pump(List,BI,"probablyPrime",Void.Filter, pisanoPrime.fp1(1))
.pump(Void,T(Void.Read,14,False),fcn{ vm.arglist.apply("%4d".fmt).concat().println() });

View file

@ -0,0 +1,19 @@
fcn pisano(m){
primeFactors(m).pump(Dictionary().incV) //18 --> (2,3,3) --> ("2":1, "3":2)
.reduce(fcn(z,[(k,v])){ lcm(z,pisanoPrime(k.toInt(),v)) },1)
}
fcn lcm(a,b){ a / a.gcd(b) * b }
fcn primeFactors(n){ // Return a list of prime factors of n
acc:=fcn(n,k,acc,maxD){ // k is 2,3,5,7,9,... not optimum
if(n==1 or k>maxD) acc.close();
else{
q,r:=n.divr(k); // divr-->(quotient,remainder)
if(r==0) return(self.fcn(q,k,acc.write(k),q.toFloat().sqrt()));
return(self.fcn(n,k+1+k.isOdd,acc,maxD)) # both are tail recursion
}
}(n,2,Sink(List),n.toFloat().sqrt());
m:=acc.reduce('*,1); // mulitply factors
if(n!=m) acc.append(n/m); // opps, missed last factor
else acc;
}

View file

@ -0,0 +1,3 @@
println("Pisano(m) for integers 1 to 180:");
[1..180].pump(List, pisano, "%4d".fmt)
.pump(Void,T(Void.Read,14,False),fcn{ vm.arglist.concat().println() });