11 = (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3) + (6) - (4)


35

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

  1. Знайти найменше трикутне число Т я таке , що Т я  ≥ Н . Побудуйте відповідний список L = [1, 2, ..., i] .

  2. Поки сума доданків L більша від N , вилучіть із списку перший доданок.

  3. Якщо сума доданків L тепер менша за N , з приростом i додайте її до списку. Перейдіть до кроку №2.

Ми зупиняємось, як тільки N досягається. Систематично виконується лише перший крок. Кроки №2 та №3 взагалі можуть не оброблятися.

Приклади

Нижче наведено приклад для N = 11 :

Приклад

Тож очікуваний вихід для N = 11 - 4 .

Інші приклади:

  • N = 5 - Почнемо з T 3 = 1 + 2 + 3 = 6 , а потім 2 + 3 = 5 . Очікуваний вихід: 2 .
  • N = 10 - потрібен лише перший крок, оскільки 10 - трикутне число: T 4 = 1 + 2 + 3 + 4 = 10 . Очікуваний вихід: 1 .

Перші 100 значень

Нижче наведені результати для 1 ≤ N ≤ 100 :

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

Правила

  • Ви можете написати або повну програму, або функцію, яка або друкує, або повертає результат.
  • Вам потрібно обробити будь-який N ≤ 65536 менш ніж за одну хвилину на апараті середнього класу.
  • Зважаючи на достатній час, ваша програма / функція повинна теоретично працювати для будь-якого значення N, яке підтримується вашою мовою. Якщо цього немає, будь ласка, поясніть, чому у своїй відповіді.
  • Це кодовий гольф, тому найкоротша відповідь у байтах виграє!

Пов'язані. (Я підозрюю, що ви вже знаєте про це, але просто
розміщуєте

Яке максимальне значення N нам потрібно обробити?
Лука

@Luke Перегляньте оновлені правила.
Арнольд

Відповіді:


4

Желе , 29 31 байт

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

Монадійне посилання, яке повертає результат (N = 65536 займає менше двох секунд).

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

Як?

Для ретельного пояснення алгоритму дивіться фантастичний пост Мартіна Ендера .

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

Повнопрограмна програма, що базується на 29 байт, створена з описаного алгоритму, займає 4 хвилини 30 для N = 65536 на моєму ноутбуці, тому я вважаю, що це не враховується.

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

Використання циклу час для кожного кроку 3 та повторного використання його як кроку 1 по довжині дорівнює тому, що я можу керувати при ініціалізації списку, оскільки жодна перевірка на кроці 3 не означає створення списку, поки нічого не залишається, а потім знаходження першого індексу значення:

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i

25

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

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&

Пояснення

Мені не можна було заважати впроваджувати алгоритм у виклик, тому я хотів шукати ярлик до рішення. Хоча я знайшов його, на жаль, він не перемагає відповідь Mathematica, яка реалізує алгоритм. Це означає, що я впевнений, що це ще не оптимально для гравців, і можуть існувати інші мови, які можуть скористатися цим підходом або деякими знаннями, отриманими в процесі.

Тому я стверджую, що послідовність, яку ми повинні обчислити, така:

f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)

Крім того, це f (n) = 1, якщо n - трикутне число, а f (n) = 2 * ( A212652 (n) - A002024 (n) + 1) в іншому випадку.

У першому виразі A023532 просто кодує ці два різні випадки. Інші дві послідовності (плюс 1) - це різниця між найбільшим цілим числом k при найдовшому розкладі n на послідовні цілі числа (k-i + 1) + (k-i + 2) + ... + k = n і найбільше ціле число j, так що 1 + 2 + ... + j <n .

У кількох простих словах, ось як ми знаходимо відповідь на нетреугольние числа: перше, знайти найбільший трикутне число T J , який менше , ніж п . Тоді j - передостаннє ціле число, яке додається під час кроку 1 (оскільки після додавання j + 1 ми перевищили n ). Потім розкладіть n на якомога більше (або як малі) послідовних цілих чисел і назвіть максимум серед цих чисел k . Результат просто 2 * (kj) . Інтуїтивна причина цього полягає в тому, що максимум у розкладанні зростає на 1 кожен другий крок, і ми зупиняємось, коли досягаємок .

Нам потрібно показати чотири речі, щоб довести, що це працює:

  1. f (n) = 1 для трикутних чисел. Це тривіально так, адже перший крок просто проходить через усі трикутні числа. Якщо ми точно вдарили n під час цього процесу, то ми зробили лише один крок для обчислення.
  2. Для всіх інших чисел ми завжди закінчуємось після кроку видалення, а не після кроку вставки. Це означає, що всі інші f (n) парні.
  3. На кожному кроці вставки після першого додаємо лише одне число. Це гарантує, що ми дійдемо до розкладання, включаючи k після kj парних кроків.
  4. Остаточне розкладання n, яке ми отримуємо, - це завжди найдовший можливий розклад n на послідовні цілі числа, або іншими словами, це завжди розкладання n з найменшим максимумом серед підсумованих чисел. Іншими словами, останнє число, яке ми додаємо до суми, завжди є A212652 (n) .

Ми вже показали, чому (1) вірно. Далі ми доводимо, що на кроці вставки ми не можемо закінчитись, крім початкового (що не трапляється для нетрикутних чисел).

Припустимо, ми закінчили на кроці вставки, досягнувши n після додавання значення p до суми. Це означає, що перед цим кроком вставки значення було np ( або менше, якщо ми додавали відразу декілька значень). Але цьому кроці вставки передував етап видалення (оскільки ми не могли натиснути n під час кроку 1). Останнє значення q, яке ми видалили під час цього етапу видалення, було обов'язково меншим за p через спосіб роботи алгоритму. Але це означає, що перед тим, як ми видалили q, ми мали n-p + q ( або менше ), що менше n. Але це суперечність, адже нам довелося б припинити видалення цілих чисел, коли ми потрапляємо на n-p + q, а не видаляти інший q . Це доводить пункт (2) вище. Отже, тепер ми знаємо, що ми завжди закінчуємося на етапі видалення, і тому всі нетрикутні числа мають рівні виходи.

Далі ми доводимо (3), що кожен етап вставки може вставити лише одне значення. По суті це є наслідком (2). Ми показали, що після додавання одного значення ми не можемо точно досягти n , а оскільки в доказівці використовується нерівність, ми також не можемо опинитися нижче n (оскільки тоді n-p + q все ще буде менше n, і ми не повинні були видаляти що багато значень в першу чергу). Таким чином , всякий раз , коли ми додамо одне значення, ми гарантовано перевищить п , тому що ми пішли нижче п , видаляючи менше значення. Отже, ми знаємо, що верхній кінець суми зростає на 1 кожен другий крок. Ми знаємо початкове значення цього верхнього кінця (це найменше m таке, щоT m > n ). Тепер нам просто потрібно розібратися в цьому верхньому кінці, як тільки ми досягнемо остаточної суми. Тоді кількість кроків просто вдвічі більше (плюс 1).

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

Скажіть, що найбільш раннє / найдовше можливе розкладання n є деяким a + (a + 1) + ... (b-1) + b , a ≤ b , і скажімо, що алгоритм пропускає його. Це означає, що в момент, коли b додається, a більше не повинно бути частиною суми. Якби a була частиною суми s , тоді ми мали б n ≤ s у той момент. Отже, або сума містить лише значення від a до b , що дорівнює n, і ми зупиняємось (отже, ми не пропустили це розкладання), або є принаймні одне значення менше а в сумі, виграємо в якому випадку n <sі це значення буде видалено, поки ми не потрапимо в точну суму (знову ж таки, розкладання не було пропущено). Таким чином, нам доведеться позбутися a, перш ніж додавати b . Але це означає, що нам доведеться дійти до ситуації, коли а є найменшою складовою суми, а найбільшою ще не є b . Однак у цей момент ми не можемо видалити a , оскільки сума явно менша за n (оскільки b відсутня), тому нам потрібно додати значення спочатку, поки ми не додамо b і точно не натиснемо n . Це доводить (4).

Отже, поєднуючи ці речі разом: ми знаємо, що перша пара кроків дає нам максимальне значення A002024 (n) . Ми знаємо, що максимальне значення кінцевого розкладання дорівнює A212652 (n) . І ми знаємо, що цей максимум збільшується раз на кожну пару кроків. Отже, кінцевий вираз дорівнює 2 * ( A212652 (n) - A002024 (n) + 1) . Ця формула майже працює для трикутних чисел, за винятком того, що для тих, хто нам потрібен лише 1 крок замість 2, саме тому ми коригуємо результат за допомогою індикаторної функції трикутних чисел (або її зворотного, що б зручніше).

Нарешті, що стосується реалізації. Для попередньої послідовності я використовую формулу MIN (непарне d | n; n / d + (d-1) / 2) від OEIS. Виявляється, економте кілька байт, якщо взяти в цей вираз коефіцієнт 2, щоб отримати MIN (непарне d | n; 2n / d + d-1) , оскільки це -1 відміняє значення +1 у моїй першій версії з F (N) , яка безпосередньо кодує два випадки для трикутних і нетреугольних чисел. У коді це:

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]

Для останньої послідовності ( 1, 2, 2, 3, 3, 3, ...) ми можемо використовувати просту закриту форму:

⌊(2#)^.5+.5⌋

І нарешті, функція зворотного індикатора трикутних чисел дорівнює 0, коли 8n + 1 є ідеальним квадратом. Це може бути виражено в Mathematica як

⌈Sqrt[8#+1]~Mod~1⌉

Існує маса способів виразити ці дві останні послідовності та змінити постійне зміщення між ними, тому я впевнений, що це ще не оптимальна реалізація, але, сподіваюся, це може дати іншим вихідним моментом розглянути нові підходи в свої власні мови.

Оскільки я пішов на всю цю проблему, ось сюжет послідовності до n = 1000 (я також міг обчислити 100k за пару секунд, але це насправді не показує додаткових відомостей):

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

Це може бути цікаво розглянути варіанти цих дуже прямих ліній, але це я залишу комусь іншому ...


Нарешті я знайшов час, щоб детально прочитати вашу відповідь. Це геніально. Зауважимо, що (3) вже було припущено в алгоритмі (крок №3 - це якщо , а не час ), але доказ, звичайно, дуже вітається.
Арнольд

@Arnauld Дякую :) Я, мабуть, не помітив / неправильно зрозумів частину if / while. Добре, що це не має ніякого значення.
Мартін Ендер

7

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

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

Чиста функція, що приймає цілий аргумент.

Як це працює

For[ ... ]

ForЦикл.

l=u=c=k=0

Ініціалізація; встановити l(нижній), u(верхній), c(лічильник) та k(суму) 0.

k!=#

Стан; Повторити, поки kне дорівнює вводу.

c++

Приріст; приріст лічильника c.

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

Тіло

If[#>k, ... ]

Якщо вхід більше k:

While[#>k,k+=++u]

У той час як вхідний показник більший за k, приріст uі приріст kна u.

Якщо вхід не перевищує k:

While[#<k,k-=l++]

У той час як на вході менше k, декремента kшляхом lі збільшення l.

( ... ;c)

Повернення cпісля циклу.


1
For[,...]удари While[...].
Мартін Ендер


5

Haskell , 70 63 68 64 байт

Редагувати:

  • -7 байт: Вилучите пробіл, два знаки та деякі круглі дужки, нехтуючи сенсом a. Виправлені покрокові помилки в поясненні.
  • +5 байт: Argh, повністю пропустив цю вимогу 65536, і виявляється, що (1) потужність 2 особливо дорога, тому що вони потрапляють лише тоді, коли потрапляєш до самого числа (2), тому підсумовуючи довгі діапазони (що обертаються навколо нуль) весь час. Замінив суму математичною формулою.
  • -4 байти: скориговано a та bлінійно, щоб отримати терміни у формулі підсумовування для скасування.

1#1 це анонімна функція, яка приймає і повертає ціле число.

Використовувати як (1#1) 100 .

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

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

Як це працює

  • (a#b)n представляє поточний крок розрахунку. a, bє цифрами в 1, 3, 5, .., хоча nможуть бути як позитивними, так і негативними залежно від кроку.
    • Коли на кроці 1 або 3 він представляє список [(a+1)/2,(a+3)/2..(b-1)/2] та номер мети -n.
    • На кроці 2 він відображає список [(b+1)/2,(b+3)/2..(a-1)/2]та номер метиn .
  • Дивна переписка між a, b списками і списками полягає в тому, щоб можна було підсумовувати короткий вираз s=a*a-b*b.
    • На кроках 1 і 3 це те саме, що s= -8*sum[(a+1)/2..(b-1)/2] .
    • На кроці 2 це те саме, що s=8*sum[(b+1)/2..(a-1)/2].
  • Розгалуження проводиться шляхом списку розумінь, які створюють елементи лише в одному випадку, та підбиття підсумків.
    • Якщо s>8*n, тоb збільшується на 2, перш ніж повторюватись.
      • На кроках 1 і 3 це збільшує список, тоді як на етапі 2 це зменшує його.
    • Якщо s<8*n, тоді рекурсія змінює крок, замінюючи aі b, і відкидаючиn , і 1 додається до результату.
    • Якщо s==8*nтоді жодне з двох розумінь списку не дає жодних елементів, значить, сума є 0.
  • (1#1) nпредставляє манекен "етап 2" перед початком, який негайно змінюється на крок 1, будуючи список з [1..0]=[].

4

PHP> = 7,0, 74 байт

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

використовувати оператора космічного корабля

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

Розширено

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps

Що $argn?
chx

@chx Змінна, яка доступна під час отримання PHP з командного рядка за допомогою -R Option php.net/manual/en/features.commandline.options.php
Jörg Hülsermann

Ого. Я ніколи не чув про -Rнабагато менше argvабо argi. Я знав про arcc та argv звичайно. Дуже цікаво, спасибі
chx

4

C, 94 91 байт

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

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}

Широке використання на неініціалізованих змінних
oO

@YSC в C, неініціалізовані глобально оголошені цілі числа встановлюються на нуль під час компіляції. докладніше
Халед.К

Забули про це. Дякую за це нагадування.
ВАТ

FYI, я відправив інший C відповідь . Принаймні один із прийомів, які я використав, не буде працювати з іншими компіляторами (відсутні return), але для тих, хто це робить, не соромтеся включити їх у свою відповідь.
hvd

3

JavaScript (ES6), 82 байти

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

Тест-фрагмент


Вибачте, що сказати це, але кожен ↄ вважається 3 байтами. Я думаю, це не має значення, оскільки він є тривіально перейменованим.
Ørjan Johansen

@ ØrjanJohansen Дякую, що нагадали. Я дійсно повинен пам’ятати, щоб оцінювати свій код байтами, а не по довжині. Я не думаю, що існує консенсус спільноти щодо "тривіально перейменованих [змінних]", тому я відредагував публікацію. Ну добре.
Р. Кап

3
6553 працює в Node (6.9.1) локально, але 65536 не робить ("Максимальний розмір стека виклику перевищено").
eush77

3

постійний струм , 61 байт

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

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

Пояснення

Основний рекурсивний макрос:

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

Цей макрос:

  1. Знаходить мінімальне трикутне число, яке перевищує поточне число в стеці (використовуючи модифіковану формулу трикутного кореня ).
  2. Перевіряє, чи трикутна сума Sточно відображає поточне число. Виходить, якщо це робить.
  3. Переходить до кроку 1 з S+N(надмірне наближення) або S-N(недооцінка), вибір чергується між ітераціями.

Коли він виходить, слід, залишений на стеку, повідомляє головній програмі, скільки ітерацій пройшло.


3

Python 3, 150 138 байт

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

Журнал змін:

  • Змінено додавання до + =, видалено ще (спасибі musicman523, Loovjo; -12 байт)

1
Крок №2 може видалити один або кілька термінів одночасно зі списку (наприклад, 1, 2 і 3 у прикладі для N = 11), але рахується як один крок у будь-якому випадку.
Арнольд

@Arnauld пропустив це; фіксований.
L3viathan

1
Чи можете ви пояснити, чому elseце потрібно? Я вважаю, що elseпрогони виконуються кожен раз, тому що цикл завжди закінчується нормально (без break), і, здається, без нього добре працювати .
музикант523

Ви можете пропустити A=l.appendчастину і використовувати l+=[x]натомість.
Loovjo

3

Пакетна, 126 байт

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

Пояснення: lдорівнює нулю, якщо крок 2 ніколи не виконувався. Це дозволяє nвідстежувати кількість ітерацій кроку 3. Оскільки алгоритм ніколи не зупиняється на кроці 3, тому він повинен виконати крок 1 один раз і крок 2 n+1рази для загальної кількості n+n+2кроків. Однак якщо параметр є трикутним числом, тоді крок 2 ніколи не виконується, тому нам потрібно відняти один крок.


3

Python 2, 86 81 байт

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

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

Вираховує тестовий випадок 655360.183s на TIO.


Ця рекурсивна версія в 84 байти не в змозі обчислити всі значення до 65536:

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

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


2

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

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

Чиста функція, яка бере цілий аргумент і повертає ціле число.

Змінні aта bпозначають (постійно мінливі) номери початку та кінця в розглянутій сумі, тоді як qпозначають поточний загальний (чисел від a+1до b); tвідслідковує всі qзустрічаються досі значення. Після ініціалізації цих змінних Forцикл виконує виконання If[q<#,q+=++b,q-=++a], яке або додає нове число до кінця, або віднімає число в передній частині, як продиктовано специфікацією, поки не qдорівнює вводу.

Тепер нам залишається лише отримати кількість кроків із tсписку qзначень, що зустрічаються на цьому шляху. Наприклад, коли вхід є 11, Forцикл виходить з tрівним {0,1,3,6,10,15,14,12,9,15,11}. Найкращий спосіб, який я знайшов, щоб обчислити кількість кроків із цього - підрахувати, скільки разів різниці переходять від підйому до спуску; це те, що Length@Split@Sign@Differences@tробить багатослівна команда , але я підозрюю, що її можна вдосконалити.


2

C (tcc), 71 байт (61 + 10)

Аргументи командного рядка (включаючи пробіл):

-Dw=while

Джерело:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

Як це працює:

cпідраховує кількість кроків. mі Mзберігати мінімум і максимум асортименту, sсуму. Спочатку вони всі нульові.

Постійно cзбільшується і sпорівнюється з n. Поки вони нерівні:

  • Якщо cнепарне, тоді s<nдо кінця діапазону додайте ціле число: збільшити Mна одиницю і sна M.

  • Якщо cце парне число, тоді s>nдо початку діапазону видаліть ціле число: зменшіть sна mі збільшіть mна одиницю.

Коли цикл виходить, cйого занадто багато разів збільшують. Зменшення його дає правильний результат, і трапляється, щоб його обчислили у правильному регістрі, щоб діяти як повернене значення.

Кумедно трапляється використовувати ті самі імена змінних, що і відповідь на адресу Khaled.K . Вони не копіюються.


1

Perl 6 , 114 байт

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(натхненний більш ранньою реалізацією Haskell )

Спробуйте.
Він працює на вході 65536 за 45 секунд на моєму комп’ютері, але я не зміг змусити його запустити менше 60 секунд на TIO.run.
У мене є Rakudo v2017.04 +, де він має v2017.01 .
Rakudo / NQP / MoarVM отримує оптимізацію майже щодня, тому з тимчасового періоду може бути будь-яка їх кількість, яка потрібна для того, щоб її встигнути вчасно.


Розширено

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

Зауважте, що Ракудо має оптимізацію для Range.sumтого, щоб йому не довелося перебирати всі значення.

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