Найнижчі початкові числа в послідовності, схожі на Фібоначчі


22

Враховуючи позитивний цілий вхід N , виведіть два негативних числа, a і b , де a <b , з найменшим можливим середнім значенням, яке призведе до того, що число N буде частиною послідовності повторюваних відношень:

f(0) = a
f(1) = b
f(n) = f(n-2)+f(n-1)

У випадку, якщо існує більше одного рішення, де середні значення a і b мінімальні, слід вивести одне з найнижчим b .

Можна припустити, що N знаходиться в репрезентативному діапазоні цілих чисел у вашій мові / системі.

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

N = 1
a = 0, b = 1

N = 15
a = 0, b = 3

N = 21
a = 0, b = 1

N = 27
a = 0, b = 9   <- Tricky test case. [3, 7] is not optimal and [4, 3] is not valid

N = 100
a = 4, b = 10

N = 101
a = 1, b = 12

N = 102
a = 0, b = 3

N = 1000
a = 2, b = 10

Якщо a>=0і a<bчи є коли-небудь кілька рішень?
Джонатан Аллан

Я не можу гарантувати, що існує чи немає декількох рішень. І те 1,4і 2,3дало б 5, і вони мають однакове значення. Я думаю, можна знайти випадки, схожі на той, де це найнижчі середні значення. Якщо ви можете показати / довести, що не існує декількох рішень, то вам не потрібно перевіряти на цю умову.
Стюі Гріффін

2
повністю натхненний codegolf.stackexchange.com/q/147200/67961
J42161217

3
Відповідна послідовність OEIS для найнижчого можливого середнього рівня, A249783 , має графік дикого вигляду .
Петро Кагей

1
@ ØrjanJohansen Я додав у свою відповідь доказ того, що немає дублікатів рішення (оскільки моя відповідь залежала від цього).
cardboard_box

Відповіді:


8

Лушпиння , 19 18 16 14 13 15 байт

Дякую Zgarb за збереження 1 байта.

ḟö£⁰ƒẊ++ÖΣṖ2Θḣ⁰

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

Пояснення:

Відмова: Я дійсно не розумію ȯƒẊ++розділ коду.

Редагувати: Здається, це перекладається на Haskell fix.(mapad2(+).).(++), де mapad2функція застосувати до всіх сусідніх пар у списку. (Хоча, знаючи Хеск, в контексті цієї програми це може означати щось інше)

            Θḣ⁰    Create the list [0..input]
          Ṗ2       Generate all possible sublists of length 2
        ÖΣ         Sort them on their sums
ḟ                  Find the first element that satisfies the following predicate.
    ƒẊ++             Given [a,b], magically generate the infinite Fibonacci-like
                     sequence from [a,b] without [a,b] at the start.
 ö£⁰                 Is the input in that list (given that it is in sorted order)?


Я впевнений, що я спробував це ...
H.PWiz

8

JavaScript (Node.js) , 92 90 89 91 83 82 байт

-3 байти -1 байт завдяки ThePirateBay

-8 -9 байт завдяки Нілу.

f=(n,a=1,b=0,c=(a,b)=>b<n?c(a+b,a):b>n)=>c(a,b)?b+2<a?f(n,a-1,b+1):f(n,b-~a):[b,a]

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

Примітка: це рішення спирається на те, що ніколи не існує декількох мінімальних рішень.

Доказ того, що ніколи не існує декількох рішень:

Нехай FIB(a,b,k)буде подібна до Фібоначчі послідовність, що починається з a,b:

FIB(a,b,0) = a
FIB(a,b,1) = b
FIB(a,b,k) = FIB(a,b,k-1) + FIB(a,b,k-2)

Лема 1

Різниця між послідовностями, схожими на Фібоначчі, сама по собі є фібонацькою, тобто FIB(a1,b1,k) - FIB(a0,b0,k) = FIB(a1-a0,b1-b0,k). Доказ залишається читачеві.

Лема 2

Бо існує n >= 5рішення, a,bяке задовольняє a+b < n:

якщо nнавіть,FIB(0,n/2,3) = n

якщо nце дивно,FIB(1,(n-1)/2,3) = n

Доказ

Випадки, коли n < 5їх можна вичерпно перевірити.

Припустимо, у нас є два мінімальних рішення для n >= 5, a0,b0і a1,b1з a0 + b0 = a1 + b1і a0 != a1.

Тоді існують k0,k1такі, що FIB(a0,b0,k0) = FIB(a1,b1,k1) = n.

  • Випадок 1: k0 = k1

    Припустимо WLOG b0 < b1(і, отже a0 > a1)

    Нехай DIFF(k)буде різниця між послідовностями, схожими на Фібонанці, починаючи з a1,b1та a0,b0:

    DIFF(k) = FIB(a1,b1,k) - FIB(a0,b0,k) = FIB(a1-a0,b1-b0,k) (Лема 1)

    DIFF(0) = a1 - a0 < 0

    DIFF(1) = b1 - b0 > 0

    DIFF(2) = (a1+b1) - (a0+b0) = 0

    DIFF(3) = DIFF(1) + DIFF(2) = DIFF(1) > 0

    DIFF(4) = DIFF(2) + DIFF(3) = DIFF(3) > 0

    Після того, як послідовність, схожа на Фібоннаці, має 2 позитивні терміни, усі наступні терміни є позитивними.

    Таким чином, єдиний час DIFF(k) = 0- це коли k = 2, тому єдиним вибором k0 = k1є 2.

    Тому n = FIB(a0,b0,2) = a0 + b0 = a1 + b1

    Мінімальність цих рішень суперечить лемі 2.

  • Випадок 2 k0 != k1:

    Без втрати спільності припустимо k0 < k1.

    Ми маємо FIB(a1,b1,k1) = n

    Дозволяє a2 = FIB(a1,b1,k1-k0)

    Дозволяє b2 = FIB(a1,b1,k1-k0+1)

    Потім FIB(a2,b2,k0) = FIB(a1,b1,k1) = FIB(a0,b0,k0)(вправа для читача)

    Оскільки FIB(a1,b1,k)є негативним для k >= 0, воно також не зменшується.

    Це дає нам a2 >= b1 > a0і b2 >= a1+b1 = a0+b0.

    Тоді нехай DIFF(k) = FIB(a2,b2,k) - FIB(a0,b0,k) = FIB(a2-a0,b2-b0,k)(лема 1)

    DIFF(0) = a2 - a0 > 0

    DIFF(1) = b2 - b0 >= (a0 + b0) - b0 = a0 >= 0

    DIFF(2) = DIFF(0) + DIFF(1) >= DIFF(0) > 0

    DIFF(3) = DIFF(1) + DIFF(2) >= DIFF(2) > 0

    Ще раз, DIFFмає 2 позитивні терміни, тому всі наступні умови є позитивними.

    Таким чином, єдиний час, коли це можливо, DIFF(k) = 0є k = 1, тому єдиним вибором k0є 1.

    FIB(a0,b0,1) = n

    b0 = n

    Це суперечить лемі 2.




@Neil Це мінімізує bзамість мінімізації a+b, і, отже, ваше рішення дає, f(27) = [3,7]але оптимальне рішення є f(27)=[0,9]. Після відновлення переломних змін ми знизимось до 83 байт.
cardboard_box

1
Я думаю, ви можете зберегти ще один байт, використовуючи b-~aзамість a+b+1.
Ніл

1
У вашому другому випадку a2 >= a1 + b1є невелика помилка: невірно, коли k1-k0=1. Замість цього ви можете використовувати a2 >= b1 > a0і b2 >= a1+b1 = a0+b0, і далі випливає решта.
Ørjan Johansen

8

Haskell , 76 72 74 байт

Редагувати:

  • -4 байти: @ H.PWiz запропонував використовувати /замість div, хоча для цього потрібно використовувати тип дробового числа.
  • +2 байти: виправлено помилку з Enumдіапазонами шляхом додавання -1.

fприймає значення Doubleабо Rationalтип і повертає кордону того ж. Doubleповинно вистачити на всі величини, які недостатньо великі, щоб викликати помилки округлення, в той час Rationalяк теоретично необмежені.

f n|let a?b=b==n||b<n&&b?(a+b)=[(a,s-a)|s<-[1..],a<-[0..s/2-1],a?(s-a)]!!0

Спробуйте в Інтернеті! (з коригуваннями заголовка H.PWiz для введення / виводу Rationals у цілому форматі)

Як це працює

  • ?є локально вкладеним оператором в межах області f. a?bрекурсивно крокує через послідовність, подібну до Фібоначчі, починаючи з a,bдо b>=n, повертаючи, Trueякщо вона nточно впадає.
  • У списку розуміння:
    • sповторюється через всі числа 1вгору, представляючи суму aі b.
    • aповторюється через числа від 0до s/2-1. (Якщо sнепарне, кінець діапазону округляється.)
    • a?(s-a)перевіряє, чи послідовність починається з a,s-aхітів n. Якщо так, то розуміння списку включає кортеж (a,s-a). (Тобто b=s-a, хоча це було занадто коротко, щоб його варто було назвати.)
    • !!0 вибирає перший елемент (удар) у розумінні.

8

APL (Діалог) , 75 71 64 59 53 48 44 43 байт

2 байти збережено завдяки @ Adám

12 байт збережено завдяки @ngn

o/⍨k∊¨+\∘⌽⍣{k≤⊃⍺}¨oa/⍨</¨a←,⍉|-21+k←⎕

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

Використання ⎕IO←0.

Як? Це пішло справжніми горіхами.

k←⎕ - призначити вхід до k

⍳2⍴1+k←⎕- декартовій твір діапазону 0на kсам з собою

|-\¨ - піднесіть кожен правий елемент пари зліва і отримайте абсолютні значення

a←,⍉ - перекласти, вирівняти та призначити a

o←a/⍨</¨a - зберігайте лише пари, де лівий елемент менший за правий, і призначте o

oтепер містить список усіх пар з a < b, упорядкованими за їх арифметичним середнім

+\∘⌽⍣{k≤⊃⍺}¨o- для кожної пари в oзастосуйте поле (переверніть пару та закінчення) до досягнення kабо більш високого терміну

k∊¨- тоді вирішіть, чи kце останній термін (тобто він міститься в послідовності)

o/⍨- і зберігати пари oтам, де застосовується попередня перевірка

- повернути перший результат.


5

Python 2 , 127 109 107 байт

-2 байти завдяки ovs (змінюється andна *)

g=lambda x,a,b:a<=b<x and g(x,b,a+b)or b==x
f=lambda n,s=1,a=0:g(n,a,s-a)*(a,s-a)or f(n,s+(a==s),a%s+(a<s))

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

Будь-які бонусні бали за n,a,s-a?

Пояснення:

  • Перший рядок оголошує рекурсивну лямбда, gяка перевіряє, чи a, bбуде досягнуто розширення у послідовності Фібоначчі x. Це також перевіряє a <= bодин із критеріїв питання. (Це дозволило б мати випадки, коли a == b, але в такому випадку 0, aвони вже були б виявлені та повернуті).
    • Ланцюгова нерівність a<=b<xвиконує одразу дві зручні завдання: перевірка a <= b, і це b < x.
    • Якщо b < xприбутковість True, то функція викликає себе знову наступних двох чисел в послідовності Фібоначчі: b, a+b. Це означає, що функція буде працювати над новими умовами до ...
    • Якщо b < xврожайність False, то ми дійшли до того, коли нам потрібно перевірити, чи є b==x. Якщо так, це повернеться True, що означає, що початкова пара a, bв підсумку дійде x. Інакше, якщо b > x, пара недійсна.
  • Другий рядок оголошує іншу рекурсивну лямбда f, яка знаходить рішення для заданого значення n. Рекурсивно пробує нові початкові пари a, b, до g(n, a, b)врожайності True. Потім це рішення повертається.
    • Функція рекурсивно підраховує початкові пари Фібоначчі, використовуючи дві змінні s(спочатку 1) та a(спочатку 0). На кожній ітерації aзбільшується і a, s-aвикористовується як перша пара. Однак при aзверненні sвона повертається до 0 і sзбільшується. Це означає, що пари підраховуються за такою схемою:
      s = 1 (0, 1) (1, 0)
      s = 2 (0, 2) (1, 1) (2, 0)
      s = 3 (0, 3) (1, 2), (2, 1), (3, 0)
      
      Очевидно, що в ньому є кілька недійсних пар, однак вони усуваються миттєво при передачі g(див. Першу точку кулі).
    • Коли значення aі sвиявляються такими, що g(n, a, s-a) == True, то це значення повертається. Оскільки можливі рішення підраховуються в порядку "розміру" (відсортованого за середнім значенням, а потім значенням min), перше знайдене рішення завжди буде найменшим, як вимагає завдання.

3

R , 183 байт 160 байт

n=scan();e=expand.grid(n:0,n:0);e=e[e[,2]>e[,1],];r=e[mapply(h<-function(n,a,b,r=a+b)switch(sign(n-r)+2,F,T,h(n,b,r)),n,e[,1],e[,2]),];r[which.min(rowSums(r)),]

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

Завдяки Джузеппе за те, що виграли 23 байти

Пояснення коду

n=scan()                        #STDIO input
e=expand.grid(n:0,n:0)          #full outer join of integer vector n to 0
e=e[e[,2]>e[,1],]               #filter so b > a
r=e[mapply(
  h<-function(n,a,b,r=a+b)switch(sign(n-r)+2,F,T,h(n,b,r)),
                                #create a named recursive function mid-call 
                                #(requires using <- vs = to denote local variable creation 
                                #rather than argument assignment
  n,e[,1],e[,2]),]              #map n, a and b to h() which returns a logical
                                #which is used to filter the possibilities
r[which.min(rowSums(r)),]       #calculate sum for each possibility, 
                                #get index of the minimum and return
                                #because each possibility has 2 values, the mean and 
                                #sum will sort identically.

1
160 байт - загалом, ви повинні зберігати байти де завгодно, тому збереження 4 байт шляхом видалення приємного іменування не тільки прийнятне чи заохочене, але в певному сенсі вимагає код-гольф . Навіть так, приємна відповідь, +1.
Джузеппе


1

Желе , 19 байт

ṫ-Sṭµ¡³e
0rŒcÇÐfSÐṂ

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

-1 байт завдяки докази по cardboard_box . Якщо це спростується, ви можете додати UṂṚдо кінця другого рядка загалом 22 байти.


... провідний приріст повинен вирішити спостереження @ StewieGriffin.
Джонатан Аллан

У мене є відчуття, що ти можеш скинути
Джонатана Аллана

1
Нам потрібно лише знайти насіння, яке робить внесок x, з’являється останнім. Якщо вони x були знайдені в третьому індексі для кратного, він працює для, 0,xі тому він також буде працювати або 1,(x-1)/2( xнепарне), або 2,x/2-1( xпарне), після чого xв результаті з’явиться пізніше, так що трапиться не буде. Для більш пізнього зіткнення середнє значення може бути однаковим, якщо і треті члени є однаковими, але тоді має бути менша різниця між початковими термінами (інакше вони були б однакові) і, отже, вони xзнайдуться при більш пізньому індексі . Як такий, ми можемо ṫ-Sṭµ¡i³¶ḶŒcÇÐṀзберегти чотири байти.
Джонатан Аллан


@StewieGriffin Цей тестовий випадок не існував, коли я відповів: p
Erik the Outgolfer

1

GolfScript - 88 77 байт

~:N[,{1+:a,{[.;a]}/}/][{[.~{.N<}{.@+}while\;N=]}/]{)1=\;},{(\;~+}$(\;);~~' '\

Я не перевіряв численні рішення, завдяки cardboard_box!

Пояснення

~:N                           # Reads input
[,{1+:a,{[.;a]}/}/]           # Creates an array of pairs [a b]
[{[.~{.N<}{.@+}while\;N=]}/]  # Compute solutions
{)1=\;},         # Pairs that are not solutions are discarded
{(\;~+}$         # Sorts by mean
(\;);~~' '\      # Formats output


0

Пакетна, 160 158 байт

@set/aa=b=0
:g
@if %a% geq %b% set/ab-=~a,a=0
@set/ac=a,d=b
:l
@if %c% lss %1 set/ad+=c,c=d-c&goto l
@if %c% gtr %1 set/aa+=1,b-=1&goto g
@echo %a% %b%

Це (також) дає 3 7на вході 27. Правильне рішення 0 9.
cardboard_box

@cardboard_box Ще не бачимо, де питання вимагає цього ...
Ніл

У першому реченні: "з найменшим можливим середнім значенням".
cardboard_box

@cardboard_box Ах, вибачте, це було занадто просто не помітити.
Ніл

1
@cardboard_box OK слід виправити зараз.
Ніл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.