寻找皮萨诺时期


20

斐波那契序列是众所周知的序列,其中每个条目的前两个与前两项的总和是1。如果我们把每学期的模一个恒定的顺序将成为周期性的。例如,如果我们决定计算序列mod 7,我们将得到以下结果:

1 1 2 3 5 1 6 0 6 6 5 4 2 6 1 0 1 1 ...

它的周期为16。定义了一个相关序列,称为Pisano序列,使得该序列a(n)模数为n时斐波纳契序列的周期。

任务

您应该编写一个程序或函数,给定的程序或函数n将计算并输出Fibonacci序列mod的周期n。那是Pisano序列中的第n项。

您只能在范围内支持整数 0 < n < 2^30

这是一场竞赛,因此您应努力使按字节计分的源代码的大小最小化。

测试用例

1  -> 1
2  -> 3
3  -> 8
4  -> 6
5  -> 20
6  -> 24
7  -> 16
8  -> 12
9  -> 24
10 -> 60
11 -> 10
12 -> 24

3
限制为2 ^ 30可以确保所有中间值都小于2 ^ 31,但仍不能保证Pisano周期适合32位有符号整数。(我相信这是你的限制的原因是什么?)皮萨诺周期可以显著比他们更大的ñ。例如,皮萨诺(Pisano)周期6是24。100之上的10的幂比n大50%。
Iszi 2013年

3
Pigeonhole原理说f(i),f(i+1)最多可以取n^2mod的值n。因此,n限制为2^30可以产生最多的周期2^60。限制n <= 2^16会给P(n) <= 2^32
展位,2013年

@boothby我不太确定我是否理解您的意思,或者它是否能够正确解决我所遇到的相同问题。您能否进一步解释一下,也许还有其他链接?如有需要,请随时与我聊天。
Iszi 2013年

2
@Iszi观察到这一点f(i+2) = f(i+1)+f(i),因此可以使用一对整数mod来描述该周期内机器循环的“状态” n。最多有n^2州,所以期间最多n^2。哦! 维基百科声称这个时期最多6n。别管我的琐事。
2013年

Answers:


11

GolfScript(28 25 24 23个字符)

~1.{(2$+}{.@+2$%}/+\-,)

在stdin中接受输入,将其保留在stdout(或堆栈,如果您想进一步处理...)

这样可以正确处理极端情况(Demo)。

作为GolfScript程序员的兴趣点,我认为这是我编写的第一个程序,实际上比我尝试的其他方法更短。


7

GolfScript,24个字符

~:&1.{.2$+&%.2$(|}do](-,

GolfScript实现的下一个迭代。现在,第二个版本也可以正确处理1。它变得相当长,但也许有人可以找到缩短此版本的方法。您可以在线尝试以上版本


这样可以1正确处理输入吗?
彼得·泰勒

@PeterTaylor Nope,没有测试那个极端情况。回到绘图板。
霍华德

@PeterTaylor新代码也可用于输入1-仍然只有24个字符。
霍华德

4

Python,第188 132 101 95 87个字符

n=input()
s=[]
a=k=0
b=1
while s[:k]!=s[k:]or k<1:s+=[a%n];k=len(s)/2;a,b=b,a+b
print k

用法

$ echo 10 | python pisano.py
60

例如:

$ for i in {1..50}; do; echo $i | python pisano.py; done
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

谢谢beary605额外的打高尔夫球!
ESultanik

您可能想要再次计算字符数。我的回应数低于您的回应数。
DavidC 2012年

@David:您在计算空格吗?我只是双重检查(由catwc -c,我也得到了相同的编号。
ESultanik

我使用Wolfram Research提供的例程。我认为,它计算出必要的空白。
DavidC 2012年

if k>0 and s[0:k]==s[k:]:break可以更改为if s and s[:k]==s[k:]:break。您还可以通过删除迭代器,将for循环更改为while 1:,并a,b=a,a+b在while循环结束时执行操作,从而显着减少开销。
Strigoides 2012年

4

蟒蛇 90 85 96 94 90 82

n=input();c=[1,1];a=[]
while(c in a)<1%n:a+=[c];c=[c[1],sum(c)%n]
print len(a)or 1

编辑:由贝里和普里莫实施建议


85 :a.append(c) -> a+=[c],而循环可以放在一行上,((n>1)>>(c in a)) -> (n>1)>>(c in a)
beary605

append实际上与的功能不同+=。谢谢你的提示。
scleaver

我认为在这种情况下,它的工作方式相同。
beary605

(n>1)>>(c in a) -> (c in a)<1%n3个字节 我同意beary关于附录的内容。无论是将引用附加到c,还是扩展a的值c,两种方法都完全相同(因为c无论如何您都会立即销毁引用)。
2012年

嗯,我的错误是我使用的a+=c不是a+=[c]
scleaver

2

Mathematica 73

p = {1, 0}; j = 0; q = p;
While[j++; s = Mod[Plus @@ p, n]; p = RotateLeft@p; p[[2]] = s; p != q]; j

2

PHP- 61 57字节

<?for(;1<$a.$b=+$a+$a=!$i+++$b%$n+=fgets(STDIN););echo$i;

这个脚本会错误地报告2n=1,但所有其他的值是否正确。

样本I / O,这是一个左截断序列,其中π(n)= 2n + 2

$ echo 3 | php pisano.php
8
$ echo 13 | php pisano.php
28
$ echo 313 | php pisano.php
628
$ echo 3313 | php pisano.php
6628
$ echo 43313 | php pisano.php
86628
$ echo 543313 | php pisano.php
1086628
$ echo 4543313 | php pisano.php
9086628
$ echo 24543313 | php pisano.php
49086628

1
1<$a.$b=+$a+$a=!$i+++$b%$n+=fgets(STDIN)哦,天哪,这就是操作开发的顺序。
拉马先生2012年

1

的PowerShell:98

高尔夫代码:

for($a,$b=0,(1%($n=read-host))){$x++;if($a+$b-eq0-or("$a$b"-eq10)){$x;break}$a,$b=$b,(($a+$b)%$n)}

取消评论,并附有评论:

for
(
    # Start with $a as zero, and $b as 1%$n.
    # Setting $b like this at the start helps catch the exceptional case where $n=1.
    $a,$b=0,(1%
    (
        # Grab user input for n.
        $n=read-host
    ))
)
{
    # Increasing the counter ($x) and testing for the end of the period at the start ensures proper output for $n=1.
    $x++;

    # Test to see if we've found the end of the Pisano Period.
    if
    (
        # The first part catches $n=1, since $a and $b will both be zero at this point.
        $a+$b-eq0-or
        (
            # A shorter way of testing $a-eq1-and$b-eq0, which is the end of a "normal" Pisano Period.
            "$a$b"-eq10
        )
    )
    {
        # Pisano Period has reached its end. Output $x and get out of the loop.
        $x;break
    }

    # Pisano Period still continues, perform operation to calculate next number.
    # Works pretty much like a Fibonacci sequence, but uses ($a+$b)%$n for the new $b instead.
    # This takes advantage of the fact we don't really need to track the actual Fibonacci numbers, just the Fibonacci pattern of %$n.
    $a,$b=$b,(($a+$b)%$n)
}

# Variable cleanup - not included in golfed code.
rv n,a,b,x

笔记:

我不确定使用此脚本对$ n的最大可靠限制是多少。它可能小于2 ^ 30,因为$ x可能在$ n到达那里之前溢出int32。除此之外,我自己还没有测试上限,因为脚本的运行时间在我的系统上已经达到30秒,价格为$ n = 1e7(仅比2 ^ 23多一点)。出于相同的原因,我不会很快倾向于对可能需要的其他语法进行测试和故障排除,以将变量升级到uint32,int64或uint64,以便扩展此脚本的范围。


样本输出:

我将其包装在另一个for循环中:

for($i=1;;$i++)

然后设置$n=$i代替=read-host,然后更改输出以"$i | $x"了解脚本的一般可靠性。这是一些输出:

1 | 1
2 | 3
3 | 8
4 | 6
5 | 20
6 | 24
7 | 16
8 | 12
9 | 24
10 | 60
11 | 10
12 | 24
13 | 28
14 | 48
15 | 40
16 | 24
17 | 36
18 | 24
19 | 18
20 | 60

...

9990 | 6840
9991 | 10192
9992 | 624
9993 | 4440
9994 | 1584
9995 | 6660
9996 | 1008
9997 | 1344
9998 | 4998
9999 | 600
10000 | 15000
10001 | 10212
10002 | 3336
10003 | 5712
10004 | 120
10005 | 1680
10006 | 10008
10007 | 20016
10008 | 552
10009 | 3336
10010 | 1680

边注: 我不太确定Pisano周期比$ n短得多。这是正常现象,还是我的脚本有问题?没关系-我只是记得,5后,斐波那契数迅速成为很多比他们的顺序发生大。因此,这现在很有意义。


1

Perl,75岁61,62 + 1 = 63

$k=1%$_;$a++,($m,$k)=($k,($m+$k)%$_)until$h{"$m,$k"}++;say$a-1

用法

$ echo 8 | perl -n -M5.010 ./pisano.pl
12

不打高尔夫球

$k = 1 % $_;
$a++, ($m, $k) = ($k, ($m + $k) % $_) until $h{"$m,$k"}++;
say $a - 1

+1字节的-n标志。感谢Gabriel Benamy削减了13个字节。


1
您可以摆脱$n=<>;(-6)并将其替换为-n标志(+1),然后$n可以将所有实例替换为$_。您可以使用-M5.010免费,使用该say命令代替print(-2)。修饰符while语句不需要在条件(-2)周围加括号。代替@{[%h]}/2,您可以$a++,在前面有一个计数器($m,$k)=,然后say$a-1在末尾(-2)。而不是"$m,$k"使用$m.$k(-2)。对于61 + 1 = 62字节,这应该$k=1%$_;$a++,($m,$k)=($k,($m+$k)%$_)while!$h{$m.$k}++;say$a-1-n标志一起出现。
加布里埃尔·贝纳米

显然,我对Perl的了解不如我以前想象的那么聪明。感谢您的提示。
西尔维奥·马约洛

在Perl线程中打高尔夫球技巧中有很多有用的指针!祝好运!^^
Gabriel Benamy '16

其实,我错了-你需要"$m,$k"的不是$m.$k,(+2),但是可以通过更改保存1个字节while!$huntil$h(-1)。抱歉!
加布里埃尔·贝纳米

嗯?在什么输入下$m.$k失败?它似乎对我有效。
西尔维奥·马约洛

0

Clojure,102字节

不太令人兴奋,请迭代公式,直到我们返回[1 1](我希望情况总是如此)。(f 1)收敛到时的特殊处理[0 0]

#(if(< % 2)1(+(count(take-while(fn[v](not=[1 1]v))(rest(iterate(fn[[a b]][b(mod(+ a b)%)])[1 1]))))1))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.