Data update

This commit is contained in:
Ingy döt Net 2024-07-13 15:19:22 -07:00
parent 29a5eea0d4
commit 5c1bb7bfa9
2011 changed files with 35081 additions and 3229 deletions

View file

@ -0,0 +1,17 @@
pisano_period{
prime 20.1(*0.5)|
select {(¨)/}
factors {2 ×: 0=|:,÷ (+1)}
pisanoPeriod {1 0(,|(+/¯2))(×),0 1}
pisanoPrime {(pisanoPeriod )×*-1}
pisano {/{=0:1 pisanoPrime }factors }
showPisanoPrimes {+'pisanoPrime''→'( pisanoPrime )}¨
_2 showPisanoPrimes prime select 15
''
_1 showPisanoPrimes prime select 180
''
'pisano ⍵ for integers ''⍵'' from 1 to 180 are:'
pisano¨12 15180
}

View file

@ -0,0 +1,114 @@
### In case gojq is used:
# Require $n > 0
def _nwise($n):
def _n: if length <= $n then . else .[:$n] , (.[$n:] | _n) end;
if $n <= 0 then "nwise: argument should be non-negative" else _n end;
### Generic utilities
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;
def lcm($m; $n):
# The helper function takes advantage of jq's tail-recursion optimization
def _lcm:
# state is [m, n, i]
if (.[2] % .[1]) == 0 then .[2] else (.[0:2] + [.[2] + $m]) | _lcm end;
[$m, $n, $m] | _lcm;
# Preserve integer accuracy as much as the implementation of jq allows
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
def is_prime:
. as $n
| if ($n < 2) then false
elif ($n % 2 == 0) then $n == 2
elif ($n % 3 == 0) then $n == 3
elif ($n % 5 == 0) then $n == 5
elif ($n % 7 == 0) then $n == 7
elif ($n % 11 == 0) then $n == 11
elif ($n % 13 == 0) then $n == 13
elif ($n % 17 == 0) then $n == 17
elif ($n % 19 == 0) then $n == 19
else sqrt as $s
| 23
| until( . > $s or ($n % . == 0); . + 2)
| . > $s
end;
# Emit an array of the prime factors of . in order using a wheel with basis [2, 3, 5]
# e.g. 44 | primeFactors => [2,2,11]
def primeFactors:
def out($i): until (.n % $i != 0; .factors += [$i] | .n = ((.n/$i)|floor) );
if . < 2 then []
else [4, 2, 4, 2, 4, 6, 2, 6] as $inc
| { n: .,
factors: [] }
| out(2)
| out(3)
| out(5)
| .k = 7
| .i = 0
| until(.k * .k > .n;
if .n % .k == 0
then .factors += [.k]
| .n = ((.n/.k)|floor)
else .k += $inc[.i]
| .i = ((.i + 1) % 8)
end)
| if .n > 1 then .factors += [ .n ] else . end
| .factors
end;
# Calculate the Pisano period of . from first principles.
def pisanoPeriod:
. as $m
| {p: 0, c: 1}
| first(foreach range(0; $m*$m) as $i (.;
.p as $t
| .p = .c
| .c = ($t + .c) % $m;
select(.p == 0 and .c == 1) | $i + 1
)) // 1;
# Calculate the Pisano period of $p^$k where $p is prime and $k is a positive integer.
def pisanoPrime($p; $k):
$p
| if (is_prime|not) or $k == 0 then 0 # no can do
else ( power($k-1) * pisanoPeriod )
end;
# Calculate the Pisano period of . using pisanoPrime/2.
def pisano:
. as $m
| (reduce primeFactors[] as $p ({}; .[$p|tostring] += 1)
| to_entries | map([(.key|tonumber), .value]) ) as $primePowers
| (reduce $primePowers[] as [$p, $n] ([];
. + [ pisanoPrime($p;$n) ] ) ) as $pps
| ($pps|length) as $ppsl
| if $ppsl == 0 then 1
elif $ppsl == 1 then $pps[0]
else {f: $pps[0], i: 1}
| until(.i >= $ppsl;
.f = lcm(.f; $pps[.i])
| .i += 1)
| .f
end;
def examples:
(range( 2; 15)
| pisanoPrime(.; 2) as $pp
| select($pp > 0)
| "pisanoPrime(\(.); 2) = \($pp)" ),
"",
(range( 2; 180)
| pisanoPrime(.; 1) as $pp
| select($pp > 0)
| "pisanoPrime(\(.);1) = \($pp)" )
;
examples,
"\npisano(n) for integers 'n' from 1 to 180 are:",
( [range(1; 181) | pisano ]
| _nwise(15)
| map(lpad(3))
| join(" "))

View file

@ -0,0 +1,79 @@
program pisano_period;
loop for p in [2..15] | prime p do
print("pisanoPrime(" + lpad(str p,3) + ", 2) = "
+ lpad(str pisanoPrime(p,2), 3));
end loop;
print;
loop for p in [2..180] | prime p do
print("pisanoPrime(" + lpad(str p,3) + ", 1) = "
+ lpad(str pisanoPrime(p,1), 3));
end loop;
print;
print("pisano(n) for integers 'n' from 1 to 180 are:");
loop for n in [1..180] do
nprint(lpad(str pisano n,4));
if (col +:= 1) mod 15 = 0 then print; end if;
end loop;
op gcd(a, b);
return {[0, a]}(b) ? (b gcd (a mod b));
end op;
op lcm(a, b);
return a div (a gcd b) * b;
end op;
op factors(n);
d := 2;
f := {};
loop while d <= n do
loop while n mod d=0 do
f(d) +:= 1;
n div:= d;
end loop;
d +:= 1;
end loop;
return f;
end op;
op prime(n);
if n<=4 then return n in {2,3}; end if;
if n mod 2=0 then return n=2; end if;
if n mod 3=0 then return n=3; end if;
d := 5;
loop while d*d <= n do
if n mod d=0 then return false; end if;
d +:= 2;
if n mod d=0 then return false; end if;
d +:= 4;
end loop;
return true;
end op;
op pisanoPeriod(n);
[p, c, i] := [0, 1, 0];
loop while i < n*n do
[p, c] := [c, (p+c) mod n];
i +:= 1;
if p=0 and c=1 then return i; end if;
end loop;
return 1;
end op;
proc pisanoPrime(p, k);
return if not prime p or k=0
then om
else p**(k-1) * pisanoPeriod p
end;
end proc;
op pisano(m);
primePowers := factors m;
pps := [pisanoPrime(p, k) : k = primePowers(p)];
if #pps = 0 then return 1; end if;
if #pps = 1 then return pps(1); end if;
return lcm/pps;
end op;
end program;