Який день Різдва це?


27

Передмова

У добре відомій колядці «Дванадцять днів Різдва» оповідачеві подають кілька подарунків щодня. Пісня є кумулятивною - у кожному вірші додається новий подарунок, на кількість на один більший, ніж подарунок перед ним. Один Партрідж, Два Голуби-черепахи, Три французькі кури тощо.

У будь-якому даному вірші, N , ми можемо обчислити кумулятивну суму подарунків на даний момент у пісні, знайшовши N -те тетраедричне число , яке дає результати:

Verse 1: 1
Verse 2: 4
Verse 3: 10
Verse 4: 20
Verse 5: 35
Verse 6: 56
Verse 7: 84
Verse 8: 120
Verse 9: 165
Verse 10: 220
Verse 11: 286
Verse 12: 364

Наприклад, після вірша 4 у нас було 4 * (1 куріпка) , 3 * (2 голуби-черепахи) , 2 * (3 французькі кури) та 1 * (4 птахи, що кличуть) . Підсумовуючи ці, ми отримуємо 4(1) + 3(2) + 2(3) + 1(4) = 20.

Змагання

Ваше завдання - написати програму або функцію, яка за заданим цілим числом, що представляє кількість подарунків 364 ≥ p ≥ 1 , визначає, який день (вірш) Різдва це.

Наприклад, якщо p = 286 , ми на 11 день Різдва. Однак якщо p = 287 , то наступне навантаження подарунків розпочалося, тобто це 12 день.

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

Правила:

  • Це , тому найкоротше рішення (в байтах) виграє.
  • Застосовуються стандартні лазівки для гольфу.
  • Що стосується днів, то ваша програма повинна бути індексованою 1.
  • Подання має бути повноцінною програмою або функцією, але не фрагментом.

Випробування

1   ->  1
5   ->  3
75  ->  7
100 ->  8
220 ->  10
221 ->  11
364 ->  12

5
На всякий випадок, коли це комусь допомагає, n-е чотиригранне число - це також сума перших n трикутних чисел.
DJMcMayhem

Це може допомогти: x=>{while(x>p)p+=r+=++i;return i}я впевнений, що його можна скоротити такою мовою, як JavaScript.
12Me21

1
Це найдавніший різдвяний виклик будь-коли, правда? :)
вставити користувач туди

Відповіді:


7

Желе , 7 6 байт

-1 байт завдяки Деннісу (використовуйте векторизований мінімум «та перший індекс i)

R+\⁺«i

TryItOnline

Як?

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

R+\⁺«i - main link: n
R      - range                          [1,2,3,4,...,n]
 +\    - cumulative reduce by addition  [1,3,6,10,...,sum([1,2,3,4,...n])] i.e. triangle numbers
   ⁺   - duplicate previous link - another cumulative reduce by addition
                                        [1,4,10,20,...,nth tetrahedral]
    «  - min(that, n)                   [1,4,10,20,...,n,n,n]
     i - first index of n (e.g. if n=12:[1,4,10,12,12,12,12,12,12,12,12,12] -> 4)

Попередній 7 byters з використанням зниженого діапазону [0,1,2,3,...,n-1]і підрахунком tetrahedrals менше п:
Ḷ+\⁺<µS,
Ḷ+\⁺<ḅ1,
Ḷ+\⁺<ċ1, і
Ḷ+\⁺<¹S


19

Пітон , 27 байт

lambda n:int((n*6)**.33359)

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

Пряма формула з деяким приляганням кривих, така сама, як і оригінальна, знайдена рівнем River St.

Зсунене рівняння i**3-i==n*6близьке до i**3==n*6великого i. Це вирішує i=(n*6)**(1/3). Знімаючи підлогу вниз, за ​​необхідності, компенсуючи вимикання.

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


Пітон , 38 байт

f=lambda n,i=1:i**3-i<n*6and-~f(n,i+1)

Формула n=i*(i+1)*(i+2)/6для чотиригранних чисел може бути красивіше записана i+1як n*6=(i+1)**3-(i+1). Отже, ми знаходимо найнижчу iдля якої i**3-i<n*6. Кожен раз, коли ми збільшуємо, iпочинаючи з 1, рекурсивні дзвінки додають 1до результату. Починаючи з, i=1а не i=0компенсуючи зміну.


Приємно. Я думав про те, щоб пройти шахту для гольфу таким чином, але цього не зробив. Тим не менш, я спробую змінити; наші відповіді все одно будуть іншими.
0WJYxW9FMN

1
Вуа. Ваш новий дивовижний.
0WJYxW9FMN

1
26-байтна версія не відповідає 364, що виключається з тестового діапазону. **.33359працює на один зайвий байт.
Денніс

@ Денніс Дякую Ексклюзивні діапазони Python знову вражають!
xnor

1
lambda n:n**.3336//.5501економить кілька байт.
Денніс

10

J , 12 байт

2>.@-~3!inv]

Можливо, це є спосіб, коли це можна зробити, але це прекрасна можливість використовувати вбудовану функцію інверсії J.

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

Як це працює

2>.@-~3!inv]  Monadic verb. Argument: n

           ]  Right argument; yield n.
      3       Yield 3.
       !inv   Apply the inverse of the ! verb to n and 3. This yields a real number.
              x!y computes Π(y)/(Π(y-x)Π(x)), where Π is the extnsion of the 
              factorial function to the real numbers. When x and y are non-negative
              integers, this equals yCx, the x-combinations of a set of order y.
 >.@-~        Combine the ceil verb (>.) atop (@) the subtraction verb (-) with
              swapped arguments (~).
2             Call it the combined verbs on the previous result and 2.


7

Желе , 7 байт

R‘c3<¹S

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

Як це працює

R‘c3<¹S  Main link. Argument: n

R        Range; yield [1, ..., n].
 ‘       Increment; yield [2, ..., n+1].
  c3     Combinations; yield [C(2,3), ..., C(n+1,3)].
    <¹   Yield [C(2,3) < n, ..., C(n+1,3) < n].
      S  Sum; count the non-negative values of k for which C(k+2,3) < n.

2
Іноді я замислююся, що желі не може зробити?
Курка Сомбреро

1
Днями хтось стане схожим на "Code Golf - повнофункціональний MMO", і Денніс збирається розмістити "Желе, 29 байт" або щось таке дурне.
corsiKa

6

JavaScript (ES6), 33 байти

n=>(F=k=>k<n?F(k+3*k/i++):i)(i=1)

На основі рекурсивної формули:

a(1) = 1
a(i) = (i + 3) * a(i - 1) / i

Другий вираз також можна записати як ...

a(i) = a(i - 1) + 3 * a(i - 1) / i

... що саме ми тут використовуємо.

a(i - 1)насправді зберігається у kзмінній і передається до наступної ітерації до k >= n.

Тестові справи


Це підступно коротко! Хороша робота.
FlipTack

@FlipTack Моя перша спроба була заснована на використаній вами формулі. Мені довелося змінити свої плани. ;-)
Арнольд

6

Рубін, 26 байт

Редагувати: альтернативна версія, ще 26 байт

->n{(n**0.3333*1.82).to_i}

Оригінальна версія

->n{((n*6)**0.33355).to_i}

Використовує той факт, T(x) = x(x+1)(x+2)/6 = ((x+1)**3-(x+1))/6що дуже близький (x+1)**3/6.

Функція просто множиться на 6, знаходить злегка підправлену версію кореня куба (так, потрібно 5 знаків після коми) і повертає результат, урізаний у ціле число.

Тестова програма та вихід

f=->n{((n*6)**0.33355).to_i}
[1,4,10,20,35,56,84,120,165,220,286,364].map{|i|p [i,f[i],f[i+1]]}

[1, 1, 2]
[4, 2, 3]
[10, 3, 4]
[20, 4, 5]
[35, 5, 6]
[56, 6, 7]
[84, 7, 8]
[120, 8, 9]
[165, 9, 10]
[220, 10, 11]
[286, 11, 12]
[364, 12, 13]

0.3336здається, працює для оригінальної версії. (Редагувати: Неважливо, Денніс зазначає, що я забував про 364.)
xnor

5

JavaScript, 36 33 байт

-3 байти завдяки Лука (що робить функцію викривленою)

n=>f=i=>n<=i/6*-~i*(i+2)?i:f(-~i)

Це неназвана лямбда-функція, якій можна призначити funcта викликати func(220)(), як описано в цьому мета-пості . Моя оригінальна функція, яка не має вибору, виглядає так:

f=(n,i)=>n<=-~i*i/6*(i+2)?i:f(n,-~i)

У цій відповіді використовується той факт, що x- й чотиригранний номер можна знайти за допомогою наступної функції:

f (x) = x / 6 (x + 1) (x + 2)

Подання працює шляхом рекурсивного збільшення iі знаходження tetrahedral(i), поки воно не буде більшим або рівним n(кількість подарункових подарунків).

Коли викликається з одним аргументом, як очікувалося i = undefined, а тому не більше, ніж n. Цей засіб f(n,-~i)виконується і -~undefinedоцінюється 1, що запускає рекурсію.


Фрагмент тесту:

func = n=>f=i=>n<=i/6*-~i*(i+2)?i:f(-~i)

var tests = [1, 5, 75, 100, 220, 221, 364];
tests.forEach(n => console.log(n + ' => ' + func(n)()));


Я збирався розмістити таку саму відповідь. Бийте мене на 2 хвилини. Хороша робота!
Лука

Ви можете зберегти 3 байта від вичинки: n=>g=i=>n<=i/6*++i*++i?i-2:g(~-i). Ви б так називали f(2)().
Лука

@Luke гарне місце, моя вибаглива функція була не така коротка. Ви впевнені, що не хочете розмістити це як власну відповідь?
FlipTack

Ні, я би зробив це, якби ми використовували іншу формулу, але зараз наші рішення майже однакові. Я вважаю за краще допомогти вам стати на тому ж рівні, що і Арнольд. ;-)
Лука

3
i=>n<=iКрасиво ;-)
ETHproductions

3

MATL , 12 11 байт

`G@H+IXn>}@

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

Пояснення

`       % Do...while
  G     %   Push input, n
  @     %   Push iteration index (1-based), say m
  H     %   Push 2
  +     %   Add
  I     %   Push 3
  Xn    %   Binomial coefficient with inputs m+2, 3
  >     %   Is n greater than the binomial coefficient? If so: next iteration
}       %   Finally (execute after last iteration, before exiting the loop)
  @     %   Push last iteration index. This is the desired result
        % End (implicit)
        % Display (implicit)



2

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

(0//.i_/;i+6#>i^3:>i+1)-1&

Безіменна функція, яка приймає невід'ємний цілий аргумент і повертає негативне ціле число (так, воно працює і за день 0). Ми хочемо знайти найменше ціле число, iдля якого вхід #не більше i(i+1)(i+2)/6, що є формулою кількості подарунків, поданих у перші iдні. Через легку алгебраїчну хитрість нерівність # ≤ i(i+1)(i+2)/6еквівалентна (i+1) + 6# ≤ (i+1)^3. Таким чином, структура 0//.i_/;i+6#>i^3:>i+1починається з а 0і продовжує додавати 1, доки тест i+6#>i^3буде задоволений; потім(...)-1& віднімаємо 1в кінці (а не витрачаємо байти з дужками всередині нерівності).

Якщо ми продовжимо тривалість Різдва 12, ми можемо обробити приблизно 65536 днів до вбудованого обмеження рекурсії для //.зупинки процесу ... це приблизно 4,7 * 10 ^ 13 днів, або приблизно в десять разів перевищує вік Всесвіту до цих пір ….


2

J , 9 байт

I.~3!2+i.

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

Це неефективніше, ніж використання зворотного факторного, але, здається, коротше.

Наприклад, якщо вхідне ціле число n = 5, зробіть діапазон [2, n+1].

2 3 4 5 6 choose 3
0 1 4 10 20

Це перші 5 тетраедричних чисел. Наступним кроком є ​​визначення, до якого інтервалу (дня) належить n . Є n +1 = 6 інтервалів.

0 (-∞, 0]
1 (0, 1]
2 (1, 4]
3 (4, 10]
4 (10, 20]
5 (20, ∞)

Тоді n = 5 належить до інтервалу 3, який є(4, 10] а результат 3.

Пояснення

I.~3!2+i.  Input: integer n
       i.  Range [0, n)
     2+    Add 2 to each
   3!      Combinations nCr with r = 3
I.~        Interval index of n

2

Пітон, 43 байти

f=lambda n,i=0:n*6>-~i*i*(i+2)and-~f(n,i+1)

Збережено 5 байт завдяки @FlipTack та ще 3 завдяки @xnor !


Це дає f(220)=11, що має бути f(220)=10.
xnor

О, я використовував Python 2. Для цього потрібно Python 3, щоб уникнути поділу підлоги, хоча, можливо, ви можете помножити на іншій стороні замість цього, щоб зробити його версійно-агностичним.
xnor

Я думаю , що ви можете зробити and-~f(n,i+1)для and f(n,i+1)or i. Як не дивно, це зазвичай коротше, коли ви підраховуєте змінну рекурсивно не для її повернення, а для того, щоб натомість збільшувати вихід рекурсивно.
xnor

2

Japt , 12 байт

1n@*6§X³-X}a

Перевірте це в Інтернеті! або Перевірте всі тестові випадки одразу

Як це працює

1n@*6§X³-X}a  // Implicit: U = input integer
  @       }a  // Find the smallest non-negative integer X which satisfies this condition:
      X³-X    //   (X ^ 3) - X
     §        //   is greater than or equal to
   *6         //   U * 6.
1n            // Subtract 1 from the result.
              // Implicit: output result of last expression

Це спрощення тетраедричної формули, яку використовують кілька інших відповідей:

f(x) = (x)(x + 1)(x + 2)/6

Підставляючи x - 1в x, ми можемо спростити це значно:

f(x) = (x - 1)(x)(x + 1) / 6
f(x) = (x - 1)(x + 1)(x) / 6
f(x) = (x^2 - 1)(x) / 6
f(x) = (x^3 - x) / 6

Тому правильний результат на один менший, ніж найменше ціле число, xтаке(x^3 - x) / 6 більше або дорівнює вхідному.

13-байтовое рішення, натхнена @ XNOR в відповіді :

p.3335 /.55 f

Ще кілька рішень @ETHproductions, і я розігрувався

J+@*6§X³-X}a 
@*6§X³-X}a -1
@§X/6*°X*°X}a 
_³-V /6¨U}a -1
§(°V nV³ /6?´V:ß
§(°VV³-V /6?´V:ß

Перевірте це тут .


1

SmileBASIC, 43 байти

INPUT X
WHILE X>P
I=I+1
R=R+I
P=P+R
WEND?I

I- це день, Rє iтретім трикутним числом і Pє iчетвертим чотиригранним числом (кількість подарунків).

Я думаю, схожа відповідь на іншій мові, мабуть: x=>{while(x>p)p+=r+=++i;return i}могла б бути досить хорошою.


Ти хочеш ?Iнаприкінці, чи не так?
Нік Маттео

1

Python 3, 48 46 байт

f=lambda x,i=1:f(x,i+1)if(i+3)*i+2<x/i*6else i

@FlipTack Argh! Я виправлю це через секунду ... нікого не зволікайте, будь ласка.
0WJYxW9FMN

6
Ви можете попередити будь-яке запозичення, видаливши свою відповідь. Потім ви все ще зможете відредагувати відповідь та відновити її після її виправлення.
Лайконі

Крім того, це все ще не робить те, що задається завданням. Вхід 221волі розбить його.
FlipTack

Я перевірив це на TIO, і він виходить з ладу на всіх входах. Це моя проблема чи це трапляється з кимось іншим?

Це працювало для мене. Я тестую його ще раз.
0WJYxW9FMN


1

Haskell, 21 23 байт

floor.(**(1/3)).(*6.03)

Редагувати: Як зазначав xnor, оригінальне рішення ( floor.(/0.82).(**0.4)) не працювало між різдвяними днями


Це дає неправильну відповідь на багато входів, наприклад 221.
xnor

0

Пакет, 69 байт

@set/an=d=t=0
:l
@set/at+=d+=n+=1
@if %t% lss %1 goto l
@echo %n%

Вручну обчислює чотиригранні числа.




0

QBIC , 19 байт

Це краде формулу @xnor:

:?int((a*6)^.33359)

Я спробував набрати роздільну здатність до .3336, щоб зберегти байт, але це не вдається на остаточному тесті.


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