Фібоначчі перевернуто!


42

Вступ

Всі ми знаємо і любимо свою послідовність Фібоначчі і вже бачили тут безліч викликів. Однак нам все одно не вистачає дуже простого випадку, який ця відповідь збирається забезпечити: Зворотний рівень! Отже, враховуючи F_nсвою роботу - знайти n.

Специфікація

Вхідні дані

Вашим входом буде невід'ємне ціле число, яке гарантовано буде частиною послідовності поля.

Вихідні дані

Вихід повинен бути і невід'ємним цілим числом.

Що робити?

У вступі вже сказано: Враховуючи число напруженості, виведіть його індекс. Цим число Fiboancci визначається як F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)і вам дано, F(n)і ви повинні повернутися n.

Потенційні випадки кутових справ

0 - допустимий вхід і вихід.
Якщо вам введено "1" як вхід, ви можете вивести "1" або "2", як вам зручніше.
Ви завжди можете припустити, що ваше введення насправді є числом волів.
Ви можете припустити, що вхід може бути представлений у вигляді 32-бітного цілого числа.

Хто виграє?

Це код-гольф, тому найкоротша відповідь у байтах виграє!
Звичайно, застосовуються стандартні правила.

Тестові кейси

0 -> 0
2 -> 3
3 -> 4
5 -> 5
8 -> 6
13 -> 7
1836311903 -> 46

39
Незначний ніт-забрати: чи не варто вважати зворотними Фібоначчі en.m.wikipedia.org/wiki/Inverse_function
Michael

19
Отже, iccanobiF ?!

6
@Michael це не зворотна Фібоначчі, тому що немає зворотної функції Фібоначчі, тому що вона не є ін'єктивною (тому що "1" з'являється двічі). Зворотний результат спочатку походив із ідеї "перегляду зворотної таблиці", що я очікував від людей, які тут роблять (наприклад, я очікував, що вони це зроблять для вирішення проблеми).
SEJPM

9
Тут функцію можна вважати правою оберненою "функцією Фібоначчі" від невід'ємних цілих чисел до набору чисел Фібоначчі. Наявність правильного зворотного не означає інжективність.
Денніс

1
@SEJPM: Я, начебто, очікував такого завдання, як "написати програму, яка розгортає послідовність посилань назад", однак.
Бергі

Відповіді:


58

Власне, 1 байт

f

Так, для цього є вбудований з 16 листопада 2015 року .

Спробуйте в Інтернеті


Для розваги, без вбудованого, це 9 байт:

╗1`F╜=`╓i

Спробуйте в Інтернеті!

Пояснення:

╗1`F╜=`╓i
╗          push input to register 0
 1`F╜=`╓   push list containing first value x (starting with x = 0) where:
   F         fib(x)
    ╜=       is equal to the input
        i  flatten the list

15
У мене є одна думка і одна думка, тільки коли я бачу це: ಠ_ಠ
Addison Crump

37
Я насправді не розумію, чому ви б "
витратили

19
@ Фаталізувати Фібоначчі та зворотні функції Фібоначчі були одними з перших, що я додав. Навіть зараз існує 39 абсолютно невикористаних однобайтових команд (і хто знає, скільки перевантажень, які можна було б використати). 256 символів у поєднанні з тим, що насправді існує 5 типів (Integer, Real, String, Iterable, Function), означає, що існує до 1280 можливих одинарних функцій та 6400 можливих бінарних функцій. Є багато місця для, здавалося б, марних команд.
Mego

23
@Mego Ви просто намагаєтеся конкурувати з Mathematica за найбільш вбудовані?
gcampbell

13
Насправді це просто байт ... хаха, люблю цю назву мови.
nicael

42

Математика, 25 байт

InverseFunction@Fibonacci

Функція. Досить зрозуміло, якщо ви запитаєте мене.


31

Python, 36 34 32 байт

lambda n:len(str(66*n**6))//1.24

Попередні версії:

f=lambda n:len(str(66*n**6))//1.24
f=lambda n:(n*n*7).bit_length()//1.4

Пояснення

Основна ідея - перевернути формулу

fibonacci(n) ~ ( (1 + sqrt(5)) / 2)**n / sqrt(5)

що нам це говорить

log fibonacci(n) ~ n log((1 + sqrt(5)) / 2) - log(sqrt(5))

отримати

f(n) ~ (log(n) + log(sqrt(5))) / log((1 + sqrt(5))/2)

Оптимізаціями для гольфу є:

  • Використовувати len(str(n))для обчислення бази журналу 10 без імпорту log(стара версія, що використовується .bit_length()для обчислення бази журналу 2)
  • Підвищити nна потужність, щоб апроксимація логарифму могла розрізняти послідовні числа Фібоначчі
  • Помножуючи на постійні масштабування значень, щоб отримати їх у правильному діапазоні

Тоді дільник був урізаний з якомога меншою точністю, наскільки я міг керувати, і множник вибрав, щоб дати правильні результати для всіх 32-розрядних цифр фільтрів.


це має бути 32 байти, тому що f=не рахується.
Leaky Nun

2
Як було сказано вище в коментарі, анонімні функції / безіменні лямбдахи дозволені за замовчуванням . Крім того, якщо ви обмежите свою відповідь Python 2 і потребуєте тривалого аргументу, lambda n:~-len(`66*n**6`)//1.24слід працювати.
Денніс


10

Желе, 14 11 байт

5½×lØp+.Ḟ»0

Спробуйте в Інтернеті!

Це моя перша в історії відповідь на желе! Для цього використовується алгоритм відповіді MATL . Дякуємо Деннісу за те, що поголив 3 байти!

Пояснення:

   lØp      # Log Base phi
5½          # Of the square root of 5
  ×         # Times the input
      +     # Plus
       .    # 0.5
        Ḟ   # Floored

Це дає правильну відповідь, тепер нам просто потрібно розглянути особливий випадок '0'. З аргументом '0' ми отримуємо -infinity, тому повертаємось

»      # The maximum of 
 0     # Zero
       # And the previous calculated value.

7
+1, оскільки коментарі до пояснення - це кінець обмеження.
Даніель

10

Юлія, 27 26 18 байт

!n=log(3n+.7)÷.48

Для цього використовується зворотна формула Біне з достатньою точністю для 32-бітних цілих чисел; він фактично працює до F (153) = 42,230,279,526,998,466,217,810,220,532,898> 2 105 .

Спробуйте в Інтернеті!

Як це працює

Формула Біне зазначає наступне.

Формула Біне

Обмеження F на безлічі Фібоначчі, відображення N → F п має право зворотної F → N F .

У нас це є

прямо зворотна формулою Біне

і все, що залишилося зробити, - це мати справу з крайовим випадком 0 .

Оскільки введення обмежено 32-бітовими цілими числами, ми можемо використовувати короткі десятичні літери замість констант у формулі.

  • лог φ = 0,481211825059603447… ≈ 0,48

    На жаль, 0,5 недостатньо точний.

  • √5 = 2,2360679774997896964… ≈ 3

    На перший погляд це може здатися жахливим наближенням, але ми беремо логарифми, а оскільки log 3 - log √5 = 0,29389333245105… , результат перед округленням буде вимкнений невеликим постійним коефіцієнтом.

  • 0,5 ≈ 0,7

    Через перевищення попереднього наближення ми могли б взагалі опустити цей термін і все-таки отримати правильні результати для F> 0 . Однак якщо F = 0 , логарифм буде невизначений. 0,7 виявилося найменшим значенням, яке розширює нашу формулу до F = 0 .


8

JavaScript, 54 50 69 50 42 байт

b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c

Звичайно, це не виграє, просто для задоволення :)

Гаразд, перевірка нуля споживає 19 байт. WTF? Дурний-я.


Демо! Щоб побачити останній тестовий випадок, вам потрібно трохи прокрутити консоль.

a=b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c;
console.log('0: '+a(0));
console.log('2: '+a(2));
console.log('3: '+a(3));
console.log('5: '+a(5));
console.log('8: '+a(8));
console.log('13: '+a(13));
console.log('1836311903: '+a(1836311903));

Дякуємо @edc за скорочення на 8 байт.


простий b=>{for(j=1,i=c=0;b-i;c++)i=j+(j=i);return c}45, гольф b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c42.
edc65

1
@edc Вау, це розумно, спасибі <3
nicael

8

Perl 6  33 30  27 байт

{first *==$_,:k,(0,1,*+*...*>$_)}
{first *==$_,:k,(0,1,*+*...*)}
{first $_,:k,(0,1,*+*...*)}

Спробуй це

Пояснення:

# lambda with implicit 「$_」 parameter
{
  first           # find the first element
    $_,           # where something is equal to the block's argument
    :k,           # return the key rather than the value

    # of the Fibonacci sequence
    ( 0, 1, * + * ... * )
    # ^--^ first two values
    #       ^---^ lambda used to generate the next in the series
    #             ^-^ generate until
    #                 ^ Whatever
}

Тест:

#! /usr/bin/env perl6
use v6.c;
use Test;

# using the safer version that stops generating
# values bigger than the input
my &fib-index = {first $_,:k,(0,1,*+*...*>$_)}

my @tests = (
  0 => 0,
  2 => 3,
  3 => 4,
  5 => 5,
  8 => 6,
  13 => 7,
  1836311903 => 46,
  1836311904 => Nil, # this is why the safe version is used here
  12200160415121876738 => 93,
  19740274219868223167 => 94,
  354224848179261915075 => 100,
);

plan +@tests + 1;

for @tests -> $_ ( :key($input), :value($expected) ) {
  cmp-ok fib-index($input), &[eqv], $expected, .gist
}

cmp-ok fib-index((0,1,*+*...*)[1000]), &[eqv], 1000, 'works up to 1000th element of Fibonacci sequence'
1..13
ok 1 - 0 => 0
ok 2 - 2 => 3
ok 3 - 3 => 4
ok 4 - 5 => 5
ok 5 - 8 => 6
ok 6 - 13 => 7
ok 7 - 1836311903 => 46
ok 8 - 1836311904 => Nil
ok 9 - 12200160415121876738 => 93
ok 10 - 19740274219868223167 => 94
ok 11 - 354224848179261915075 => 100
ok 12 - works up to 1000th element of Fibonacci sequence

1
Ви можете замінити first *==$_на просто first $_, тому що число є дійсним розумним відповідником.
smls

24 байти , використовуючи ...оператор замістьfirst
Джо Кінг,

7

Желе , 8 байт

1+С0
¢i

Спробуйте в Інтернеті! Зауважте, що цей підхід є надто неефективним для останнього тестового випадку.

Як це працює

¢i     Main link. Argument: n

¢      Call the helper link niladically (i.e., without arguments).
       This yields the sequence of the first n positive Fibonacci numbers, i.e.,
       [1, 1, 2, 3, 5, ...].
 i     Find the first index of n (1-based, 0 if not found).


1+С0  Helper link. No arguments.

1      Set the left argument to 1.
    0  Yield 0.
 +С   Add both arguments, replacing the left argument with the sum and the right
       argument with the previous value of the left argument.
       Yield the array of all intermediate values of the left argument.


5

Пітон, 29 байт

g=lambda n:n>.7and-~g(n/1.61)

Рекурсивно ділить вхід наближенням коефіцієнта золотого рівня 1,61 до тих пір, поки він не буде нижчим за 0,7, і виводить кількість поділів.

Для 0 виводиться код False, який дорівнює 0 в Python . Цього можна уникнути за 2 байти

g=lambda n:n//.7and 1+g(n/1.61)

4

JavaScript (ES6), 39 33 байт

f=(n,j=0,k=1)=>n>j?f(n,k,j+k)+1:0

Навіть із ES7 формула зворотного бінету займає 47 байт:

x=>Math.log(x*5**.5)/Math.log(.5+1.25**.5)+.5|0
x=>Math.log(x*5**.5)/Math.log((1+5**.5)/2)+.5|0
x=>Math.log(x*(p=5**.5))/Math.log((1+p)/2)+.5|0

Просто розподіліть logі обчисліть усі константи ...
Чарлі

IMHO, якщо ви називаєте регрессивно лямбда по імені f(n,k,j+k), вам слід включити призначення f=і рахувати його як +2 байти . Тут не слід застосовувати правило для безіменних лямбда.
Чарлі

@charlie Вибачте, я про це завжди забував. Виправлено.
Ніл

4

Шавлія, 49 байт

lambda x,s=sqrt(5):x and int(log(x*s,(1+s)/2)+.5)

Дякуємо TuukkaX за пропозицію щодо економії, sqrt(5)як відголити sкілька байтів.

Спробуйте в Інтернеті .

Цей підхід із використанням зворотної формули Біне пропонує декілька вдосконалень у порівнянні з попереднім підходом: він швидший (постійний час проти квадратичного часу), він фактично працює на більші входи та коротший!

Користувачі Python можуть задатися питанням, чому я використовую sqrt(5)замість коротшого 5**.5- це тому 5**.5, що обчислюється powфункцією C , і втрачає точність через проблеми з плаваючою точкою. Багато математичних функцій (включаючи sqrtі log) перевантажені в Sage, щоб повернути точне, символічне значення, яке не втрачає точності.


Я взагалі не знаю Sage, але чи зможете ви зберегти байти, утримуючи sqrt(5)змінну та два рази, замість того, щоб sqrt(5)двічі вводити текст ?
Yytsi

4

MATL , 14 байт

t?5X^*17L&YlYo

Спробуйте в Інтернеті!

Тут використовується зворотна формула Біне , і тому це дуже швидко.

Нехай F позначає n -ве число Фібоначчі, а φ - золоте відношення . Тоді

введіть тут опис зображення

Код використовує цю формулу з двома модифікаціями:

  • Замість додавання 1/2, а потім округлення вниз код просто обертається до найближчого цілого числа, яке займає менше байтів.
  • Введення F = 0 потрібно розглядати як окремий випадок.

Як це робиться

t         % Take input F implicitly. Make a copy
?         % If (copy of) F is positive
  5X^     %   Push sqrt(5)
  *       %   Multiply by F
  17L     %   Push phi (predefined literal)
  &Yl     %   Two-input logarithm: first input is argument, second is base
  Yo      %   Round towards nearest integer
          % Else the input, which is 0, is left on the stack
          % End if implicitly
          % Display implicitly

1
Альтернативний підхід:O1G:"yy+]vGmfq
DJMcMayhem

1
11 байт:t?17L&YlXkQ
jimmy23013

@ jimmy23013 Приємний підхід! Вам слід визначити, як окрему відповідь
Луїс Мендо

Я не думаю, що варто нічого іншого відповісти, оскільки це лише спосіб усунути 5X^*. ( Я робив це раніше .) І я не знаю MATL достатньо, щоб можливо продовжувати його вдосконалювати.
jimmy23013


3

JavaScript, 22 байти

n=>Math.log(n)/.48+2|0

Я не думав, що це спрацює, коли я його побачив, але, мабуть, -Infinity|0є 0у JavaScript. Піди розберися.
Денніс

@Dennis: У JS бітові оператори беруть лише останні 32 біти та -Infinity = FFF00000 00000000. Я був радий дізнатися, що він заряджає 3 байти за те, що не потрібно проводити явний тест нуля, як n&&. Крім цього, головна мета |0- це заміна Math.trunc()(як ÷у Джулії).
Чарлі

3

C, 62 58 байт

g(c,a,b){return c-a?g(c,b,a+b)+1:0;}f(c){return g(c,0,1);}

Детально

int g(int c, int a, int b)
{
    if (c == a)
    {
        return 0;
    }
    else
    {
        return g(c, b, a+b) + 1;
    }
}

int f(c)
{
    return g(c, 0, 1);
}

3

Java 7, 70 байт

int c(int n){int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;}

https://ideone.com/I4rUC5


2
Ласкаво просимо до PPCG, приємна перша відповідь!
Leaky Nun

int c(int n){int a=0,b=1,c=0,t;for(;a<n;t=b,b+=a,a=t)c++;return c;}(не перевірено)
Leaky Nun

int c(int n){int a=0,b=1,c=0;while(a<n){c++;b+=a;a=b-a;}return c;}(не перевірено)
Leaky Nun

2
int c(int n){int a=0,b=1,c=0;for(;a<n;b+=a,a=b-a)c++;return c;}(не перевірено)
Leaky Nun

2

TSQL, 143 байти

Введення надходить @nяк вDECLARE @n INT = 1836311903;

DECLARE @O BIGINT=0;WITH F(R,P,N)AS(SELECT @O,@O,@O+1 UNION ALL SELECT R+1,N,P+N FROM F WHERE N<=@n)SELECT MAX(R)FROM F OPTION(MAXRECURSION 0);


2

Сесос , 28 байт

Hexdump:

0000000: 16f8be 766ef7 ae6d80 f90bde b563f0 7ded18 3ceffa  ...vn..m.....c.}..<..
0000015: b1c1bb af9f3f ff                                  .....?.

Спробуйте в Інтернеті!

(Експоненційний час, тому що в Sesos для копіювання числа потрібно експоненціальний час.)

Збірка, що використовується для створення двійкового файлу:

set numin
set numout
get
jmp
sub 1
fwd 1
add 1
fwd 1
add 1
rwd 2
jnz    ;input input
fwd 4
add 1  ;input input 0 1
fwd 2
add 1  ;input input 0 1 0 1
rwd 4
jmp
jmp    ;input input-curr curr next iterations
sub 1
jnz    ;input 0 curr next iterations
fwd 3
add 1
jmp
sub 1
fwd 2
add 1
rwd 2
jnz    ;input 0 curr next 0 0 iterations+1
rwd 1
jmp
sub 1
fwd 1
add 1
fwd 1
add 1
rwd 2
jnz    ;input 0 curr 0 next next iterations+1
rwd 1
jmp
sub 1
fwd 1
sub 1
fwd 2
add 1
rwd 3
jnz    ;input 0 0 -curr next curr+next iterations+1
rwd 2
jmp
sub 1
fwd 2
add 1
fwd 1
add 1
rwd 3
jnz    ;0 0 input input-curr next curr+next iterations+1
fwd 3
jnz
fwd 3
put

2

Java 8 61 байт

Те саме, що відповідь @dainichi лише скорочується, використовуючи лямбди Java 8. Відповідь - правильний вираз rvalue.

n->{int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;}

Безголівки:

interface F
{
    int c(int n);
}

public class Main
{

    public static void main(String[] args)
    {
        F f = n->{int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;};
    }
}


1

Java 7, 89 байт

int c(int n){int i=-1;while(f(++i)<n);return i;}int f(int n){return n<2?n:f(n-1)+f(n-2);}

Натхненний поясненням відповіді 05AB1E @Adnan .

Невикористані та тестові справи:

Спробуйте тут. (Ліміт часу перевищено для останнього тестового випадку, але він працює приблизно на 30-45 секунд на моєму ПК.)

class Main{
  static int c(int n){
    int i = -1;
    while(f(++i) < n);
    return i;
  }

  static int f(int n){
    return n < 2
             ? n
             : f(n - 1) + f(n - 2);
  }

  public static void main(String[] a){
    System.out.println(c(0));
    System.out.println(c(2));
    System.out.println(c(3));
    System.out.println(c(5));
    System.out.println(c(8));
    System.out.println(c(1836311903));
  }
}

Вихід:

0
3
4
5
6
46


1

J, 32 27 17 байт

i.~0,+/@(!|.)\@i.

Обчислює перші n чисел Фібоначчі, а потім знаходить індекс n у цьому списку.

Використання

Додаткові команди використовуються для форматування декількох входів / виходів. Останній тестовий випадок опущений, оскільки для обчислення знадобиться значно більше часу.

   f =: i.~0,+/@(!|.)\@i.
   (,.f"0) 0 1 2 3 5 8 13
 0 0
 1 1
 2 3
 3 4
 5 5
 8 6
13 7

Пояснення

i.~0,+/@(!|.)\@i.  Input: n
               i.  Get the range [0, 1, ..., n-1]
             \@    For each prefix of that range
          |.         Reverse the prefix
         !           Find the binomial coefficient between each value in the original
                     prefix and the reversed prefix
     +/@             Sum those binomial coefficients
                   This will create the Fibonacci numbers from 1 to n
   0,              Prepend a 0 to the list of Fibonacci numbers
i.~                Find the index of n in that list and return

1

Математика, 30 байт

Round@Log[5^.5/2+.5,.8+5^.5#]&

Чиста функція; повертає 2, якщо вхід 1.

Не перемагає інший запис Mathematica, але демонструє незвичний метод. Це (дуже класно) факт, що число N-го Фібоначчі є найближчим цілим числом до [1 / sqrt (5) кратне число N-го значення золотого відношення] (" Формула Біне ").

Тому обернена функція буде логарифмом базового [золотого відношення] в [sqrt (5) кратному номері Фібоначчі]. Це .8+хак, щоб переконатися, що ми не приймемо логарифм 0, не розкручуючи інші значення.



1

Брахілог , 14 байт

≜∧0;1⟨t≡+⟩ⁱ↖?h

Спробуйте в Інтернеті!

Приймає вхід через вихідну змінну і виводить через вхідну змінну.

≜                 Label the input variable, trying 0, 1, -1, 2...,
  0               then starting with 0
 ∧                (which is not necessarily the input variable)
   ;1             paired with 1,
     ⟨t≡ ⟩        replace the first element of the pair with the last element
     ⟨ ≡+⟩        and the last element of the pair with the sum of the elements
          ⁱ↖?     a number of times equal to the input variable,
             h    such that the first element of the pair is the output variable.

Я не зовсім впевнений, чому це потрібно.


0

Javascript (за допомогою зовнішньої бібліотеки) (84 байти)

n=>_.Until((i,a)=>{l=a.length;if(a[l-1]!=n){return i<=1?i:a[l-1]+a[l-2]}}).Count()-1

Посилання на lib: https://github.com/mvegh1/Eumerable

Пояснення коду: Бібліотека має статичний метод, який створює послідовність, поки предикат не має невизначеного зворотного значення. Присудок має підпис ("i" ndex, поточний внутрішній "a" згенерований масив). При кожній ітерації ми перевіряємо, чи останній елемент внутрішнього масиву дорівнює входу, n. Якщо ні, поверніть наступне значення у послідовності fib. В іншому випадку присудок має невизначений результат, який припиняє генерацію послідовності. Потім повертаємо довжину послідовності (і віднімаємо 1 для того, щоб відповідати 0-базі, як видно з ОП

введіть тут опис зображення


53 байти, використовуючи код звідси. n=>{a=c=t=0,b=1;while(a<n){c++;t=b;b+=a;a=t}return c} Спробуйте в Інтернеті!
pixma140
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.