ค้นหายุค Pisano


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)คือช่วงเวลาของลำดับ fibonacci เมื่อคำนวณแบบโมดูโล n

งาน

คุณจะควรจะเขียนโปรแกรมหรือฟังก์ชั่นที่เมื่อได้รับจะคำนวณและการส่งออกระยะเวลาของลำดับฟีโบนักชีพอควรn nนั่นคือคำที่ n ในลำดับ Pisano

คุณจะต้องสนับสนุนจำนวนเต็มในช่วงเท่านั้น 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 สามารถอย่างมีนัยสำคัญมีขนาดใหญ่กว่าของพวกเขาn ยกตัวอย่างเช่นระยะเวลา Pisano ของ 6 24. อำนาจของ 10 สูงกว่า 100 ออกมามีขนาดใหญ่กว่าร้อยละ 50 n
Iszi

3
หลักรังนกพิราบบอกว่าf(i),f(i+1)สามารถใช้เวลาส่วนใหญ่ค่าพอควรn^2 nดังนั้นจึงnจำกัด อยู่ที่อาจจะลมผลิตระยะเวลาของการขึ้นไป2^30 2^60จำกัดจะให้n <= 2^16 P(n) <= 2^32
บูธโดย

@boothby ฉันค่อนข้างแน่ใจว่าฉันเข้าใจสิ่งที่คุณพูดหรือถ้ามันถูกต้องที่จะจัดการกับปัญหาเดียวกันฉัน คุณช่วยอธิบายเพิ่มเติมอีกเล็กน้อยได้หรืออาจจะมีลิงค์เพิ่มเติม? รู้สึกฟรีเพื่อดึงฉันเข้าสู่การแชทหากจำเป็น
Iszi

2
@Iszi สังเกตว่าf(i+2) = f(i+1)+f(i)เพื่อให้ 'รัฐ' nของเครื่องวนลูปในช่วงระยะเวลาที่สามารถอธิบายกับคู่ของจำนวนเต็มพอควร มีอย่างมากที่สุดรัฐดังนั้นระยะเวลาที่มากที่สุดn^2 n^2Oh! 6nวิกิพีเดียบอกว่าระยะเวลาที่มากที่สุด ไม่ต้องสนใจเรื่องเล็กน้อยของฉัน
บูธโดย

คำตอบ:


11

GolfScript ( 28 25 24 23 ตัวอักษร)

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

รับอินพุตเป็น stdin ทิ้งไว้ที่ stdout (หรือสแต็กหากคุณต้องการประมวลผลเพิ่มเติม ... )

นี้จัดการกรณีมุมอย่างถูกต้อง ( สาธิต )

ในฐานะที่เป็นจุดสนใจของนักเขียนโปรแกรม GolfScript ฉันคิดว่านี่เป็นโปรแกรมแรกที่ฉันเขียนด้วยแฉซึ่งจริง ๆ แล้วออกมาสั้นกว่าวิธีอื่น ๆ ที่ฉันลอง


7

GolfScript 24 ตัวอักษร

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

การทำซ้ำครั้งต่อไปของการนำ GolfScript ไปใช้ รุ่นที่สองในขณะนี้ยังจัดการ 1 อย่างถูกต้อง มันค่อนข้างนาน แต่อาจมีบางคนสามารถหาวิธีทำให้เวอร์ชันนี้สั้นลง คุณสามารถลองเวอร์ชันด้านบนออนไลน์ได้


หมายเลขอ้างอิงนี้1ถูกต้องหรือไม่
Peter Taylor

@PeterTaylor Nope ไม่ได้ทดสอบกรณีมุมนั้น กลับไปที่กระดานวาดภาพ
Howard

@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

@ David: คุณนับช่องว่างหรือไม่ ฉันเพียงแค่สองตรวจสอบ (โดยcatทิ้งไปwc -cและฉันได้รับหมายเลขเดียวกัน.
ESultanik

ฉันใช้งานประจำที่ตกแต่งโดย Wolfram Research ฉันนับพื้นที่สีขาวที่จำเป็นฉันคิดว่า
DavidC

if k>0 and s[0:k]==s[k:]:breakif s and s[:k]==s[k:]:breakสามารถเปลี่ยนเป็น คุณสามารถลดลงอย่างมากโดยการลบตัววนซ้ำการเปลี่ยนforลูปเป็นwhile 1:และดำเนินการa,b=a,a+bเมื่อสิ้นสุดลูปในขณะที่
Strigoides

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

แก้ไข: คำแนะนำการใช้งานโดย beary และ primo


85 a.append(c) -> a+=[c]((n>1)>>(c in a)) -> (n>1)>>(c in a)
:,

append+=ที่จริงมีการทำงานที่แตกต่างกว่า ขอบคุณสำหรับเคล็ดลับแม้ว่า
scleaver

ฉันคิดว่ามันใช้งานได้เหมือนกันในกรณีนี้
beary605

(n>1)>>(c in a) -> (c in a)<1%nสำหรับ 3 ไบต์ และฉันเห็นด้วยกับ beary เกี่ยวกับการผนวก ไม่ว่าคุณจะเพิ่มการอ้างอิงต่อท้ายcหรือขยายaด้วยค่าของcมันก็จะเหมือนกันcทุกประการ(ในขณะที่คุณทำลายการอ้างอิงของคุณทันที)
โม่

Ah ตกลงผิดพลาดของฉันคือการที่ฉันถูกใช้a+=cแทนa+=[c]
scleaver


2

PHP - 61 57 ไบต์

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

สคริปต์นี้ไม่สมควรจะรายงาน2สำหรับn=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)โอ้พระเจ้านั่นคือคำสั่งของการแสวงหาผลประโยชน์การดำเนินงานที่นั่น
Mr. Llama

1

PowerShell: 98

รหัส Golfed:

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 พร้อมความคิดเห็น:

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 อาจล้น int32 ก่อนที่ $ n จะไปถึงที่นั่น นอกจากนั้นฉันยังไม่ได้ทดสอบขีด จำกัด สูงสุดเพราะเวลารันสคริปต์นานถึง 30 วินาทีสำหรับระบบของฉันในราคา $ n = 1e7 (ซึ่งน้อยกว่า 2 ^ 23) ด้วยเหตุผลเดียวกันฉันไม่อยากทดสอบและแก้ไขปัญหาอะไรเพิ่มเติมไวยากรณ์ใด ๆ ที่จำเป็นในการอัพเกรดตัวแปรเป็น uint32, int64 หรือ uint64 ตามต้องการเพื่อขยายช่วงของสคริปต์นี้


ตัวอย่างผลลัพธ์:

ฉันห่อสิ่งนี้ไว้ในห่วงอีกอันหนึ่ง:

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

Sidenote: ฉันไม่แน่ใจจริงๆว่าช่วงเวลา Pisano บางช่วงสั้นกว่า $ n อย่างมาก นี่เป็นเรื่องปกติหรือเป็นสิ่งผิดปกติกับสคริปต์ของฉันหรือไม่ ไม่เป็นไร - ฉันก็จำได้ว่าหลังจากที่ 5 ตัวเลข Fibonacci อย่างรวดเร็วกลายเป็นมากมีขนาดใหญ่กว่าสถานที่ในลำดับ ดังนั้นตอนนี้ก็สมเหตุสมผลแล้ว


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

Ungolfed

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

+1 ไบต์สำหรับการ-nตั้งค่าสถานะ ลดขนาดลง 13 ไบต์ขอบคุณ Gabriel Benamy


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) สิ่งนี้ควรออกมา$k=1%$_;$a++,($m,$k)=($k,($m+$k)%$_)while!$h{$m.$k}++;say$a-1พร้อมกับ-nค่าสถานะสำหรับ 61 + 1 = 62 ไบต์
Gabriel Benamy

เห็นได้ชัดว่าฉันไม่ได้ฉลาดกับ Perl เท่าที่ฉันคิด ขอบคุณสำหรับเคล็ดลับ
Silvio Mayolo

มีเคล็ดลับที่เป็นประโยชน์มากมายในเคล็ดลับสำหรับการเล่นกอล์ฟในหัวข้อPerl ! โชคดี! ^^
Gabriel Benamy

ที่จริงฉันผิด - คุณต้องการ"$m,$k"แทน$m.$k(+2) แต่คุณสามารถบันทึกได้ 1 ไบต์โดยเปลี่ยนwhile!$hเป็นuntil$h(-1) ขออภัย!
Gabriel Benamy

หืม? ภายใต้อินพุตใดที่$m.$kล้มเหลว ดูเหมือนว่าจะทำงานในตอนท้ายของฉัน
Silvio Mayolo

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))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.