Pisano period: Difference between revisions

Content added Content deleted
Line 1,543: Line 1,543:
48 216 328 120 40 168 336 48 364 180
48 216 328 120 40 168 336 48 364 180
72 264 348 168 400 120 232 132 178 120
72 264 348 168 400 120 232 132 178 120
</pre>

=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''

'''Works with jq, the C implementation of jq'''

'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">
### 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(" "))
</syntaxhighlight>
{{output}}
<pre style="height:20lh;overflow:auto>
pisanoPrime(2; 2) = 6
pisanoPrime(3; 2) = 24
pisanoPrime(5; 2) = 100
pisanoPrime(7; 2) = 112
pisanoPrime(11; 2) = 110
pisanoPrime(13; 2) = 364

pisanoPrime(2;1) = 3
pisanoPrime(3;1) = 8
pisanoPrime(5;1) = 20
pisanoPrime(7;1) = 16
pisanoPrime(11;1) = 10
pisanoPrime(13;1) = 28
pisanoPrime(17;1) = 36
pisanoPrime(19;1) = 18
pisanoPrime(23;1) = 48
pisanoPrime(29;1) = 14
pisanoPrime(31;1) = 30
pisanoPrime(37;1) = 76
pisanoPrime(41;1) = 40
pisanoPrime(43;1) = 88
pisanoPrime(47;1) = 32
pisanoPrime(53;1) = 108
pisanoPrime(59;1) = 58
pisanoPrime(61;1) = 60
pisanoPrime(67;1) = 136
pisanoPrime(71;1) = 70
pisanoPrime(73;1) = 148
pisanoPrime(79;1) = 78
pisanoPrime(83;1) = 168
pisanoPrime(89;1) = 44
pisanoPrime(97;1) = 196
pisanoPrime(101;1) = 50
pisanoPrime(103;1) = 208
pisanoPrime(107;1) = 72
pisanoPrime(109;1) = 108
pisanoPrime(113;1) = 76
pisanoPrime(127;1) = 256
pisanoPrime(131;1) = 130
pisanoPrime(137;1) = 276
pisanoPrime(139;1) = 46
pisanoPrime(149;1) = 148
pisanoPrime(151;1) = 50
pisanoPrime(157;1) = 316
pisanoPrime(163;1) = 328
pisanoPrime(167;1) = 336
pisanoPrime(173;1) = 348
pisanoPrime(179;1) = 178

pisano(n) for integers 'n' from 1 to 180 are:
1 3 8 6 20 24 16 12 24 60 10 24 28 48 40
24 36 24 18 60 16 30 48 24 100 84 72 48 14 120
30 48 40 36 80 24 76 18 56 60 40 48 88 30 120
48 32 24 112 300 72 84 108 72 20 48 72 42 58 120
60 30 48 96 140 120 136 36 48 240 70 24 148 228 200
18 80 168 78 120 216 120 168 48 180 264 56 60 44 120
112 48 120 96 180 48 196 336 120 300 50 72 208 84 80
108 72 72 108 60 152 48 76 72 240 42 168 174 144 120
110 60 40 30 500 48 256 192 88 420 130 120 144 408 360
36 276 48 46 240 32 210 140 24 140 444 112 228 148 600
50 36 72 240 60 168 316 78 216 240 48 216 328 120 40
168 336 48 364 180 72 264 348 168 400 120 232 132 178 120
</pre>
</pre>


Line 1,581: Line 1,769:
println("\nPisano(n) using pisanoPrime for n from 2 to 180:\n", [pisanotask(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])
</syntaxhighlight>{{out}}
</syntaxhighlight>{{out}}
<pre style="height:20lh;overflow:auto>
<pre>
pisanoPrime(2, 2) = 6
pisanoPrime(2, 2) = 6
pisanoPrime(3, 2) = 24
pisanoPrime(3, 2) = 24