Tìm thời kỳ Pisano


20

Chuỗi Fibonacci là một chuỗi được biết rõ, trong đó mỗi mục nhập là tổng của hai mục trước và hai mục đầu tiên là 1. Nếu chúng ta lấy modulo của mỗi số hạng theo một hằng số, chuỗi sẽ trở thành định kỳ. Ví dụ: nếu chúng tôi quyết định tính toán trình tự mod 7, chúng tôi sẽ nhận được như sau:

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

Điều này có một khoảng thời gian là 16. Một chuỗi liên quan, được gọi là chuỗi Pisano , được định nghĩa sao cho đó a(n)là khoảng thời gian của chuỗi Wikipedia khi tính toán modulo n.

Bài tập

Bạn sẽ viết một chương trình hoặc hàm mà khi được cung cấp nsẽ tính toán và xuất ra khoảng thời gian của mod trình tự Fibonacci n. Đó là thuật ngữ thứ n trong chuỗi Pisano.

Bạn chỉ phải hỗ trợ số nguyên trên phạm vi 0 < n < 2^30

Đây là một cuộc thi vì vậy bạn nên đặt mục tiêu giảm thiểu kích thước của mã nguồn theo số byte.

Các trường hợp thử nghiệm

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
Giới hạn ở 2 ^ 30 có thể đảm bảo tất cả các giá trị trung gian nhỏ hơn 2 ^ 31 nhưng vẫn không đảm bảo rằng Thời hạn Pisano sẽ phù hợp với số nguyên có chữ ký 32 bit. (Tôi cho rằng đó là lý do cho sự giới hạn của bạn?) Thời kỳ Pisano có thể lớn hơn đáng kể so với n của họ . Ví dụ: Thời kỳ Pisano là 6 là 24. Sức mạnh của 10 trên 100 xuất hiện lớn hơn 50% so với n .
Iszi

3
Nguyên tắc Pigeonhole nói rằng f(i),f(i+1)có thể mất tối đa n^2mod giá trị n. Vì vậy, ngiới hạn để 2^30có thể kết thúc sản xuất một khoảng thời gian lên đến 2^60. Hạn chế n <= 2^16sẽ cung cấp P(n) <= 2^32.
gian hàng

@boothby Tôi không chắc là tôi hiểu những gì bạn đang nói, hoặc nếu nó thậm chí giải quyết đúng vấn đề tương tự tôi. Bạn có thể giải thích thêm một chút, có lẽ với các liên kết bổ sung? Hãy kéo tôi vào trò chuyện nếu cần.
Iszi

2
@Iszi Quan sát điều đó f(i+2) = f(i+1)+f(i), do đó, 'trạng thái' của máy lặp trong khoảng thời gian có thể được mô tả bằng một cặp số nguyên mod n. Có nhiều nhất là n^2các tiểu bang, vì vậy thời gian là nhiều nhất n^2. Oh! Wikipedia tuyên bố rằng thời gian là nhiều nhất 6n. Đừng bận tâm đến sự tầm thường của tôi.
gian hàng

Câu trả lời:


11

GolfScript ( 28 25 24 23 ký tự)

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

Đưa đầu vào vào stdin, để nó ở thiết bị xuất chuẩn (hoặc ngăn xếp, nếu bạn muốn xử lý thêm ...)

Điều này xử lý chính xác các trường hợp góc ( Demo ).

Là một điểm thú vị đối với các lập trình viên GolfScript, tôi nghĩ rằng đây là chương trình đầu tiên tôi viết với một phần mở ra thực sự ngắn hơn các cách tiếp cận khác mà tôi đã thử.


7

GolfScript, 24 ký tự

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

Lặp lại tiếp theo của một triển khai GolfScript. Phiên bản thứ hai bây giờ cũng xử lý 1 chính xác. Nó trở nên khá dài nhưng có lẽ ai đó có thể tìm cách rút ngắn phiên bản này. Bạn có thể thử phiên bản trực tuyến trên .


Điều này có xử lý đầu vào 1chính xác?
Peter Taylor

@PeterTaylor Không, đã không kiểm tra trường hợp góc đó. Trở lại với bản vẽ.
Howard

@PeterTaylor Mã mới cũng hoạt động cho đầu vào 1- và vẫn chỉ có 24 ký tự.
Howard

4

Con trăn, 188 132 101 95 87 ký tự

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

Sử dụng

$ echo 10 | python pisano.py
60

Ví dụ:

$ 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

Cảm ơn, beary605 , vì đã chơi golf bổ sung!
ESultanik

Bạn có thể muốn đếm lại ký tự của bạn. Số phản hồi của tôi thấp hơn số phản hồi của bạn.
DavidC

@David: Bạn đang đếm khoảng trắng? Tôi chỉ kiểm tra hai lần (bằng cách gửi catđến wc -cvà tôi nhận được cùng một số.
ESultanik

Tôi sử dụng một thói quen được trang bị bởi Wolfram Research. Nó tính khoảng trắng cần thiết, tôi nghĩ vậy.
DavidC

if k>0 and s[0:k]==s[k:]:breakcó thể được thay đổi thành if s and s[:k]==s[k:]:break. Bạn cũng có thể cắt giảm đáng kể bằng cách loại bỏ iterator, thay đổi forvòng lặp thành while 1:và thực hiện a,b=a,a+bở cuối vòng lặp while.
Strigoides

4

Con trăn 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

Chỉnh sửa: Đề xuất được thực hiện bởi beary và primo


85 : a.append(c) -> a+=[c], trong khi vòng lặp có thể được đặt trên một dòng duy nhất,((n>1)>>(c in a)) -> (n>1)>>(c in a)
beary605

appendthực sự có một chức năng khác hơn +=. Cảm ơn vì lời khuyên mặc dù.
scleaver

Tôi nghĩ rằng nó hoạt động theo cách tương tự trong trường hợp này.
beary605

(n>1)>>(c in a) -> (c in a)<1%ncho 3 byte. Và tôi đồng ý với râu về phần phụ lục. Cho dù bạn nối thêm một tham chiếu đến c, hoặc mở rộng atheo giá trị của cnó, thì chính xác là như vậy (vì ngay lập tức bạn sẽ hủy tham chiếu của mình theo cách cnào).
primo

À, sai lầm của tôi là tôi đã sử dụng a+=cthay vìa+=[c]
scleaver

2

Toán học 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 byte

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

Kịch bản này sẽ sai lầm báo cáo 2cho n=1, nhưng tất cả các giá trị khác là chính xác.

I / O mẫu, một chuỗi có thể cắt ngắn trong đó π (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)Trời ơi, đó là một số thứ tự khai thác hoạt động ngay tại đó.
Ông Llama

1

PowerShell: 98

Mã đánh gôn:

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)}

Ungolfed, với ý kiế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

Ghi chú:

Tôi không chắc chính xác giới hạn đáng tin cậy tối đa là bao nhiêu cho $ n với tập lệnh này. Nó hoàn toàn có thể ít hơn 2 ^ 30, vì $ x có thể có thể vượt quá int32 trước khi $ n đến đó. Ngoài ra, tôi đã không tự mình kiểm tra giới hạn trên vì thời gian chạy cho tập lệnh đã đạt khoảng 30 giây trên hệ thống của tôi với giá $ n = 1e7 (chỉ hơn một chút so với 2 ^ 23). Vì lý do tương tự, tôi không nhanh chóng có xu hướng kiểm tra và khắc phục bất kỳ cú pháp bổ sung nào có thể cần thiết để nâng cấp các biến thành uint32, int64 hoặc uint64 khi cần để mở rộng phạm vi của tập lệnh này.


Đầu ra mẫu:

Tôi gói cái này trong một vòng lặp khác:

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

Sau đó, đặt $n=$ithay vì =read-hostvà thay đổi đầu ra "$i | $x"để có ý tưởng về độ tin cậy chung của tập lệnh. Đây là một số đầu ra:

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

Sidenote: Tôi không thực sự chắc chắn làm thế nào một số Thời kỳ Pisano ngắn hơn đáng kể so với $ n. Điều này là bình thường, hoặc là một cái gì đó sai với kịch bản của tôi? Nevermind - Tôi chỉ nhớ rằng, sau 5, số Fibonacci nhanh chóng trở thành nhiều lớn hơn vị trí của họ trong chuỗi. Vì vậy, điều này làm cho ý nghĩa hoàn toàn bây giờ.


1

Perl, 75 , 61 , 62 + 1 = 63

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

Sử dụng

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

Ung dung

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

+1 byte cho -ncờ. Cạo sạch 13 byte nhờ Gabriel Benamy.


1
Bạn có thể thoát khỏi $n=<>;(-6) và thay thế bằng -ncờ (+1), sau đó tất cả các trường hợp $ncó thể được thay thế bằng $_. Bạn có thể sử dụng -M5.010miễn phí, cho phép bạn sử dụng saylệnh thay vì print(-2). Các whilecâu lệnh sửa đổi không cần dấu ngoặc đơn xung quanh điều kiện (-2). Thay vì @{[%h]}/2, bạn có thể có một bộ đếm $a++,trước ($m,$k)=và sau đó chỉ có say$a-1ở cuối (-2). Thay vì "$m,$k"sử dụng $m.$k(-2). Điều này sẽ xuất hiện $k=1%$_;$a++,($m,$k)=($k,($m+$k)%$_)while!$h{$m.$k}++;say$a-1với -ncờ, với 61 + 1 = 62 byte.
Gabriel Benamy

Rõ ràng tôi không thông minh với Perl như tôi nghĩ. Cảm ơn vì những lời khuyên.
Silvio Mayolo

Có rất nhiều gợi ý hữu ích trong Mẹo chơi gôn trong chủ đề Perl ! Chúc may mắn! ^^
Gabriel Benamy

Trên thực tế, tôi đã sai - bạn cần "$m,$k"thay vì $m.$k, (+2), nhưng bạn có thể lưu 1 byte bằng cách thay đổi while!$hthành until$h(-1). Lấy làm tiếc!
Gabriel Benamy

Hửm Theo những gì đầu vào không $m.$kthất bại? Nó dường như làm việc trên kết thúc của tôi.
Silvio Mayolo

0

Clojure, 102 byte

Không quá thú vị, lặp đi lặp lại công thức cho đến khi chúng tôi quay lại [1 1](tôi hy vọng điều này luôn luôn như vậy). Xử lý đặc biệt (f 1)như nó hội tụ đến [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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.