Lập chỉ mục các số Fibonacci mở rộng


21

Bạn có thể đã nghe nói về các số Fibonacci. Bạn có biết, chuỗi số nguyên đó bắt đầu bằng 1, 1, và sau đó mỗi số mới là tổng của hai số cuối không?

1 1 2 3 5 8 13...

Và như vậy. Những thách thức về số lượng Fibonacci khá phổ biến 'ở đây . Nhưng ai nói rằng các số Fibonacci phải bắt đầu bằng 1, 1? Tại sao họ không thể bắt đầu với 0, 1? Được rồi, hãy xác định lại chúng để bắt đầu từ 0:

0 1 1 2 3 5 8 13...

Nhưng ... chúng ta cũng không phải dừng lại ở đó! Nếu chúng ta có thể thêm hai số cuối để lấy số tiếp theo, chúng ta cũng có thể trừ số thứ nhất khỏi số thứ hai để thêm số mới. Vì vậy, nó có thể bắt đầu với 1, 0:

1 0 1 1 2 3 5 8 13...

Chúng tôi thậm chí có thể kết thúc với tiêu cực:

-1 1 0 1 1 2 3 5 8 13...

Và loạt bài này cũng diễn ra mãi mãi. Tôi nghĩ thật thú vị khi nó kết thúc bằng cách phản chiếu các số Fibonacci thông thường, chỉ với mỗi số khác bị âm:

13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13...

Chúng ta hãy gọi chuỗi này là "Số Fibonacci mở rộng", hoặc EFN . Vì thực sự không có số âm rõ ràng để bắt đầu chuỗi này, nên chúng tôi sẽ nói rằng 0 xuất hiện ở 0 , các số Fibonacci thông thường mở rộng đến các chỉ số dương và các số Fibonacci âm (nửa âm?) Mở rộng trong các chỉ số tiêu cực, như vậy:

Indices: ...-7  -6 -5  -4 -3  -2 -1  0  1  2  3  4  5  6  7 ...
Values:  ...13  -8  5  -3  2  -1  1  0  1  1  2  3  5  8  13...

Điều này dẫn đến thách thức ngày nay:

Cho một số nguyên N , trả về mọi chỉ số mà N xuất hiện trong chuỗi EFN .

Một số quan sát ngẫu nhiên về nhiệm vụ này:

  • 1 xuất hiện nhiều lần trong EFN hơn bất kỳ số nào khác : [-1, 1, 2]. Không có số sẽ xuất hiện ở hơn 3 nơi.

  • Mỗi số Fibonacci> 1 sẽ hiển thị một lần (3, 8, 21, v.v.) hoặc hai lần (2, 5, 13, v.v.)

Làm rõ quy tắc:

  • Nếu abs(N)không phải là số Fibonacci, nó sẽ không bao giờ xuất hiện trong chuỗi EFN , do đó bạn phải xuất ra không có gì / một bộ sưu tập trống nếu có thể, hoặc nếu điều đó là không thể trong ngôn ngữ của bạn, bạn có thể xuất một số giá trị không phải là số không đổi.
  • Nếu N xuất hiện ở nhiều nơi trong EFN , đầu ra của bạn không cần phải được sắp xếp. Mặc dù mỗi chỉ số phải xuất hiện chính xác một lần.
  • Mặc dù hầu hết thử thách theo cho phép bạn chọn xem bạn muốn sử dụng lập chỉ mục dựa trên 1 hay 0, thử thách này phải sử dụng lập chỉ mục được mô tả (trong đó 0 xuất hiện ở 0).
  • Bạn có thể đưa I / O qua bất kỳ định dạng tiêu chuẩn nào.

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

-13: []
-12: []
-11: []
-10: []
-9: []
-8: [-6]
-7: []
-6: []
-5: []
-4: []
-3: [-4]
-2: []
-1: [-2]
0: 0
1: [-1, 1, 2]
2: [-3, 3]
3: [4]
4: []
5: [-5, 5]
6: []
7: []
8: [6]
9: []
10: []
11: []
12: []
13: [-7, 7]

Và một số trường hợp thử nghiệm lớn hơn:

89: [-11, 11]
1836311903: [46]
10000: []
-39088169: [-38]

Như thường lệ, câu trả lời ngắn nhất trong byte chiến thắng!


Liên quan , mặc dù không phải là một bản sao, vì nó không yêu cầu xử lý các số âm hoặc số không phải là Fibonacci.
DJMcMayhem

12
Nhân tiện, có một lý do chính đáng khác là các số Fibonacci phải luôn được lập chỉ mục sao cho $ F_0 = 0 $, ngay cả khi chỉ sử dụng các số Fibonacci dương. Đó là cách lập chỉ mục cho phép thuộc tính tuyệt đẹp này: nếu $ k $ chia $ n $, thì $ F_k $ chia $ F_n $.
Greg Martin

Câu trả lời:


9

Haskell , 78 byte

4 byte được lưu nhờ nimi

a#b=a:b#(a-b)
f 0=[0]
f a=do{(i,x)<-zip[0..a*a+1]$0#1;[-i|x==a]++[i|abs x==a]}

Hãy thử trực tuyến!

Đầu tiên chúng tôi thiết lập (#), (#)có hai tham số, ab, và trả về một danh sách bắt đầu với avà tiếp theo b#(a-b). Điều này tạo ra một danh sách vô hạn, nhưng vì Haskell lười biếng, chúng ta không cần phải lo lắng về việc lặp đi lặp lại mãi mãi. Điều này về cơ bản hoạt động ngược lại tạo ra chuỗi Fibonacci trước một cặp nhất định. Ví dụ, (0#1)sẽ là danh sách của tất cả các số Fibonacci có chỉ số âm.

Từ đây chúng tôi thực hiện f. flấy một đối số alà số chúng ta đang cố gắng tìm trong chuỗi. Ở đây chúng tôi sử dụng doký hiệu để làm một danh sách hiểu. Chúng tôi bắt đầu bằng cách lấy các a*a+1yếu tố đầu tiên của danh sách 0#11 . Vì hàm a*a+1phát triển nhanh hơn nghịch đảo của chuỗi Fibonacci, chúng tôi có thể chắc chắn rằng nếu chúng tôi kiểm tra trong giới hạn này, chúng tôi sẽ tìm thấy tất cả các kết quả. Điều này ngăn chúng tôi tìm kiếm một danh sách vô hạn. Sau đó, với mỗi giá trị xvà chỉ số i, nếu x==achúng tôi tìm thấy atrong nửa âm của chuỗi thì chúng tôi sẽ trả về -ivà nếu abs x==achúng tôi cũng trả về ivì giá trị tuyệt đối của nửa âm là nửa dương nên chúng tôi đã tìm thấy nó ở đó.

Vì điều này làm cho danh sách [0,0]cho 0chúng tôi mã hóa cứng đầu ra chính xác cho cái đó.

1: Thủ thuật này được lấy từ câu trả lời'urous 'Clean . Các ứng dụng tăng tốc tương tự ở đây như ở đó, thay thế a*a+1bằng abs a+1để tiết kiệm rất nhiều thời gian.


Thay thế ubằng dấu a#b=a:b#(a-b)cộng 0#1tiết kiệm một byte: Hãy thử trực tuyến!
nimi

@nimi Nó thực sự tiết kiệm 4 byte, liên kết tio của bạn có thêm 3 khoảng trắng.
Thuật sĩ lúa mì

5

Sạch , 132 120 109 byte

import StdEnv
g n|n<2=n=g(n-1)+g(n-2)
?k=[e\\p<-[0..k*k+1],e<-if(isOdd p)([~p,p]%(0,k))[p*sign k]|g p==abs k]

Hãy thử trực tuyến!

g :: Int -> Intlà hàm Fibonacci.
? :: Int -> [Int]chỉ chỉ vào các yếu tố của EFN trong k^2+1của 0.

Đối với một phiên bản chạy trong một khoảng thời gian lành mạnh, hãy đổi k*k+1thành abs k+1.


1
Đó là mẹo hiểu danh sách là khá gọn gàng! Lưu 14 byte của tôi vào câu trả lời của tôi.
Thuật sĩ lúa mì




1

Võng mạc 0.8.2 , 104 102 byte

[1-9].*
$*
(-)?(\b1|(?>\3?)(\2))*(1)$|(0)?.*
$5$1$4$4$#2$*
-1(11)+$

^1(11)+$
-$&,$&
1+
$.&
^2$
-1,1,2

Hãy thử trực tuyến! Giải trình:

[1-9].*
$*

Chuyển đổi thành unary, trừ khi đầu vào bằng không.

(-)?(\b1|(?>\3?)(\2))*(1)$|(0)?.*
$5$1$4$4$#2$*

Tính chỉ số Fibonacci của giá trị tuyệt đối, nhưng nếu số đó không phải là số Fibonacci thì hãy xóa nó, trừ khi nó bằng không. Điều này sử dụng biểu thức kiểm tra Fibonacci của @ MartinEnder.

-1(11)+$

Xóa các số âm có giá trị tuyệt đối là các số Fibonacci lẻ.

^1(11)+$
-$&,$&

Thêm các chỉ số âm cho các số Fibonacci dương lẻ.

1+
$.&

Chuyển đổi thành số thập phân.

^2$
-1,1,2

Thêm các chỉ số phụ cho 1.


1

Trên thực tế , 34 byte

;╗3*;±kSix⌠;;AF@;1&@0>*YτD(s**╜=⌡░

Brute-force tiết kiệm trong ngày

Giải trình:

;╗3*;±kSix⌠;;AF@;1&@0>*YτD(s**╜=⌡░
;╗                                  save a copy of the input (let's call it N) to register 0 (the main way to get additional values into functions)
  3*;±                              -3*N, 3*N
      kSi                           push to list, sort, flatten (sort the two values on the stack so that they are in the right order for x)
         x                          range(min(-3*N, 3*N), max(-3*N, 3*N))
          ⌠;;AF@;1&@0>*YτD(s**╜=⌡░  filter (remove values where function leaves a non-truthy value on top of the stack):
           ;;                         make two copies of parameter (let's call it n)
             AF                       absolute value, Fib(|n|)
               @;                     bring a copy of n to the top of the stack and make another copy
                 1&                   0 if n is divisible by 2 else 1
                   @0>                1 if n is negative else 0 (using another copy of n)
                      *               multiply those two values (acts as logical AND: is n negative and not divisible by 2)
                       YτD            logical negate, double, decrement (maps [0, 1] to [1, -1])
                          (s          sign of n (using the last copy)
                            **        multiply Fib(|n|), sign of n, and result of complicated logic (deciding whether or not to flip the sign of the value for the extended sequence)
                              ╜=      push value from register 0, equality comparison (1 if value equals N else 0)

Hãy thử trực tuyến!




0

05AB1E , 36 byte

x*ÝʒÅfIÄQ}Ii®šë1KIdiÐ`ÉiD(ì}ëD`Èi(ë¯

Phải có một cách tiếp cận tốt hơn ..>.> Có sáu (hoặc bảy nếu chúng ta bao gồm 0) các kịch bản khác nhau cho thử thách này và nó đang giết chết tôi ..

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

x            # Create a list in the range [0, (implicit) input * input * 2]
   ʒ     }     # Filter this list by:
    Åf         #  Where the Fibonacci value at that index
      IÄQ      #  Is equal to the absolute value of the input
Ii             # If the input is exactly 1:
  ®š           #  Prepend -1 to the list
ë              # Else:
 1K            #  Remove all 1s (only applies to input -1)
 Idi           #  If the input is non-negative:
    Ð`Éi   }   #   If the found index in the list is odd:
        D    #    Prepend its negative index to the list
   ë           #  Else (the input is negative):
    Di       #   If the found index in the list is even:
        (      #    Negate the found index
       ë       #   Else (found index is odd):
        ¯      #    Push an empty array
               # (Output the top of the stack implicitly as result)

Một số ví dụ từng bước:

Input:  Filtered indices:  Path it follows (with actions) and result:

-8      [6]                NOT 1 → neg → even index → negate index: [-6]
-5      [5]                NOT 1 → neg → odd index → push empty array: []
-1      [1,2]              NOT 1 → (remove 1) neg → even remaining index: negate index: [-2]
0       [0]                NOT 1 → even index → negate index: [0]    
1       [1,2]              1 → prepend -1: [-1,1,2]
5       [5]                NOT 1 → non-neg → odd index → Prepend neg index: [-5,5]
8       [6]                NOT 1 → non-neg → even index → (nothing): [6]


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.