Quel jour de Noël est-ce?

27

Préface

Dans le célèbre chant des douze jours de Noël , le narrateur reçoit chaque jour plusieurs cadeaux. La chanson est cumulative - dans chaque verset, un nouveau cadeau est ajouté, avec une quantité supérieure au cadeau précédent. Une perdrix, deux tourterelles, trois poules françaises, etc.

À n'importe quel verset donné, N , nous pouvons calculer la somme cumulée des présents jusqu'à présent dans la chanson en trouvant le N ème nombre tétraédrique , qui donne les résultats:

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

Par exemple, après le verset 4, nous avons eu 4 * (1 perdrix) , 3 * (2 tourterelles) , 2 * (3 poules françaises) et 1 * (4 oiseaux chanteurs) . En les résumant, nous obtenons 4(1) + 3(2) + 2(3) + 1(4) = 20.

Le défi

Votre tâche consiste à écrire un programme ou une fonction qui, étant donné un entier positif représentant le nombre de cadeaux 364 ≥ p ≥ 1 , détermine de quel jour (verset) de Noël il s'agit.

Par exemple, si p = 286 , nous sommes le 11e jour de Noël. Cependant, si p = 287 , alors la prochaine charge de cadeaux a commencé, ce qui signifie que c'est le 12ème jour.

Mathématiquement, cela consiste à trouver le nombre tétraédrique suivant et à retourner sa position dans toute la séquence des nombres tétraédriques.

Règles:

  • Il s'agit de , donc la solution la plus courte (en octets) l'emporte.
  • Des échappatoires de golf standard s'appliquent.
  • En ce qui concerne les jours, votre programme doit être indexé 1.
  • Votre soumission doit être un programme complet ou une fonction - mais pas un extrait.

Cas de test

1   ->  1
5   ->  3
75  ->  7
100 ->  8
220 ->  10
221 ->  11
364 ->  12
FlipTack
la source
5
Juste au cas où cela aiderait quelqu'un, le nième nombre tétraédrique est également la somme des n premiers nombres triangulaires.
DJMcMayhem
Cela pourrait aider: x=>{while(x>p)p+=r+=++i;return i}je suis sûr qu'il peut être raccourci dans un langage comme JavaScript.
12Me21
1
Ceci est le premier défi de Noël jamais, non? :)
insertusernamehere

Réponses:

7

Gelée , 7 6 octets

-1 octet grâce à Dennis (utilisez un minimum vectorisé,, «et le premier index, i)

R+\⁺«i

TryItOnline

Comment?

Pas tout à fait efficace - calcule le 1er au nième nombre tétraédriques dans l'ordre dans une liste et renvoie l'index basé sur 1 du premier qui est égal ou supérieur.

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)

Précédent 7 byters utilisant intervalle réduit [0,1,2,3,...,n-1]et de comptage tétraèdres inférieur à n:
Ḷ+\⁺<µS,
Ḷ+\⁺<ḅ1,
Ḷ+\⁺<ċ1, et
Ḷ+\⁺<¹S

Jonathan Allan
la source
19

Python , 27 octets

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

Essayez-le en ligne!

Une formule directe avec un ajustement de courbe, identique à celle trouvée par Level River St.

L'équation décalée i**3-i==n*6est proche de i**3==n*6grande i. Il résout i=(n*6)**(1/3). Prendre la parole les rondes au besoin, compensant le coup par coup.

Mais, il y a 6 entrées sur les limites où l'erreur le prend en dessous d'un entier qu'il devrait être au-dessus. Tout cela peut être corrigé en augmentant légèrement l'exposant sans introduire d'autres erreurs.


Python , 38 octets

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

La formule n=i*(i+1)*(i+2)/6des nombres tétraédriques peut être plus facilement écrite sous la i+1forme n*6=(i+1)**3-(i+1). Donc, nous trouvons le plus bas ipour lequel i**3-i<n*6. Chaque fois que nous incrémentons à ipartir de 1, les appels récursifs s'ajoutent 1à la sortie. Partir de i=1plutôt que i=0compenser le changement.

xnor
la source
Agréable. J'ai pensé à jouer au mien de cette façon, mais je ne l'ai pas fait. Néanmoins, je vais essayer de changer; nos réponses seront toujours différentes.
0WJYxW9FMN
1
Woah. Votre nouveau est incroyable.
0WJYxW9FMN
1
La version 26 octets échoue pour 364, ce qui est exclu de la plage de test. **.33359fonctionne pour un octet supplémentaire.
Dennis
@Dennis Merci. Les gammes exclusives Python frappent à nouveau!
xnor
1
lambda n:n**.3336//.5501enregistre quelques octets.
Dennis
10

J , 12 octets

2>.@-~3!inv]

Il peut y avoir une façon plus golfique de le faire, mais c'est une belle occasion d'utiliser l'inversion de fonction intégrée de J.

Essayez-le en ligne!

Comment ça marche

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.
Dennis
la source
7

Gelée , 7 octets

R‘c3<¹S

Essayez-le en ligne!

Comment ça marche

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.
Dennis
la source
2
Parfois, je me demande ce que Jelly ne peut pas faire?
Sombrero Chicken
1
Un de ces jours, quelqu'un sera comme "Code Golf un MMO complet" et Dennis va publier "Jelly, 29 octets" ou quelque chose de stupide comme ça.
corsiKa
6

JavaScript (ES6), 33 octets

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

Basé sur la formule récursive:

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

La deuxième expression peut également s'écrire ...

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

... qui est celui que nous utilisons ici.

a(i - 1)est en fait stocké dans la kvariable et passé à l'itération suivante jusqu'au k >= n.

Cas de test

Arnauld
la source
C'est sournoisement court! Bon travail.
FlipTack
@FlipTack Ma première tentative a été basée sur la formule que vous avez utilisée. J'ai dû changer mes plans. ;-)
Arnauld
6

Rubis, 26 octets

Edit: version alternative, toujours 26 octets

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

Version originale

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

Utilise le fait T(x) = x(x+1)(x+2)/6 = ((x+1)**3-(x+1))/6qui est très proche de (x+1)**3/6.

La fonction multiplie simplement par 6, trouve une version légèrement modifiée de la racine du cube (oui, 5 décimales sont requises) et renvoie le résultat tronqué à un entier.

Programme de test et sortie

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]
Level River St
la source
0.3336semble fonctionner pour la version originale. (Edit: ça ne fait rien, Dennis souligne que
j'oubliais
5

JavaScript, 36 33 octets

-3 octets grâce à Luke (rendant la fonction curry)

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

Il s'agit d'une fonction lambda sans nom qui peut être affectée à funcet appelée avec func(220)(), comme décrit dans cette publication . Ma fonction d'origine, non curry, ressemble à ceci:

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

Cette réponse utilise le fait que le x ème nombre tétraédrique peut être trouvé avec la fonction suivante:

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

La soumission fonctionne en augmentant iet en trouvant récursivement tetrahedral(i), jusqu'à ce qu'elle soit supérieure ou égale à n(le nombre de cadeaux donnés).

Lorsqu'il est appelé avec un argument comme prévu i = undefined, et n'est donc pas plus grand que n. Ce moyen f(n,-~i)est exécuté et -~undefinedévalué à 1, ce qui déclenche la récursivité.


Extrait de test:

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)()));

FlipTack
la source
J'étais sur le point de poster exactement la même réponse. Battez-moi de 2 minutes. Bon travail!
Luke
Vous pouvez enregistrer 3 octets par curryfication: n=>g=i=>n<=i/6*++i*++i?i-2:g(~-i). Vous appelleriez ça comme f(2)().
Luke
@Luke bon endroit, ma fonction au curry n'était pas si courte. Êtes-vous sûr de ne pas vouloir publier cela comme votre propre réponse?
FlipTack
Non, je le ferais si nous utilisions une formule différente, mais maintenant nos solutions sont presque identiques. Je préfère vous aider à atteindre le même niveau qu'Arnauld. ;-)
Luke
3
i=>n<=iBeautiful ;-)
ETHproductions
3

MATL , 12 11 octets

`G@H+IXn>}@

Essayez-le en ligne!

Explication

`       % 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)
Luis Mendo
la source
2

05AB1E , 10 octets

XµNÌ3c¹‹_½

Essayez-le en ligne!

Explication

Xµ          # loop until counter equals 1
  NÌ3c      # binomial_coefficient(iteration_index+2,3)
      ¹     # push input
       ‹_   # not less than
         ½  # if true, increment counter
            # output last iteration index
Emigna
la source
1
Wow, binom est beaucoup plus intelligent que [N2Ý+P6÷¹Q#N>, gentil.
Magic Octopus Urn
2

Pyke, 11 octets

#3RL+B6f)lt

Essayez-le ici!

#3RL+B6f)   -  while rtn <= input as i:
 3RL+       -     i+j for j in range(3)
     B      -    product(^)
      6f    -   ^/6
         lt - len(^)-1
Bleu
la source
2

Mathematica, 26 octets

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

Fonction sans nom prenant un argument entier non négatif et retournant un entier non négatif (ouais, ça marche aussi pour le jour 0). Nous voulons trouver le plus petit entier ipour lequel l'entrée #est au maximum i(i+1)(i+2)/6, qui est la formule du nombre de cadeaux offerts les premiers ijours. Grâce à une légère ruse algébrique, l'inégalité # ≤ i(i+1)(i+2)/6est équivalente à (i+1) + 6# ≤ (i+1)^3. La structure 0//.i_/;i+6#>i^3:>i+1commence donc par un 0et continue à s'ajouter 1tant que le test i+6#>i^3est satisfait; puis (...)-1&soustrait 1à la fin (plutôt que de dépenser des octets avec des parenthèses à l'intérieur de l'inégalité).

Si nous laissons les 12 jours de Noël continuer, nous pouvons gérer environ 65536 jours avant que la limite de récursivité intégrée pour //.arrête le processus ... c'est environ 4,7 * 10 ^ 13 jours, soit environ dix fois l'âge de l'univers jusqu'à présent ....

Greg Martin
la source
2

J , 9 octets

I.~3!2+i.

Essayez-le en ligne!

C'est plus inefficace que d'utiliser l'inverse de factorielle mais s'avère plus court.

Par exemple, si l'entier d'entrée est n = 5, définissez la plage [2, n+1].

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

Ce sont les 5 premiers nombres tétraédriques. L'étape suivante consiste à déterminer à quel intervalle (jour) n appartient. Il y a n +1 = 6 intervalles.

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

Alors n = 5 appartient à l'intervalle 3 qui est (4, 10]et le résultat est 3.

Explication

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
miles
la source
2

Python, 43 octets

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

5 octets enregistrés grâce à @FlipTack et 3 autres grâce à @xnor !

Loovjo
la source
Cela donne f(220)=11, ce qui devrait être f(220)=10.
xnor
Oh, j'utilisais Python 2. Cela nécessite Python 3 pour éviter la division du sol, bien que vous puissiez peut-être vous multiplier de l'autre côté pour le rendre indépendant de la version.
xnor
Je pense que vous pouvez faire and-~f(n,i+1)pour and f(n,i+1)or i. Étrangement, il est généralement plus court lorsque vous comptez une variable récursivement pour ne pas la renvoyer, mais pour incrémenter la sortie de manière récursive.
xnor
2

Japt , 12 octets

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

Testez-le en ligne! ou Vérifiez tous les cas de test à la fois

Comment ça marche

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

Il s'agit d'une simplification de la formule tétraédrique que plusieurs autres réponses utilisent:

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

En substituant x - 1pour x, nous pouvons simplifier considérablement:

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

Par conséquent, le résultat correct est un de moins que le plus petit entier xtel que (x^3 - x) / 6est supérieure ou égale à l'entrée.

Solution de 13 octets, inspirée de la réponse de @ xnor :

p.3335 /.55 f

Quelques autres solutions @ETHproductions et j'ai joué avec

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:ß

Testez-le ici .

Oliver
la source
1

SmileBASIC, 43 octets

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

Iest le jour, Rle inuméro triangulaire et Ple inuméro tétraédrique (nombre de cadeaux).

Je pense qu'une réponse similaire dans une autre langue, peut-être: x=>{while(x>p)p+=r+=++i;return i}pourrait être assez bonne.

12Me21
la source
Vous voulez ?Ià la fin, non?
Nick Matteo
1

Python 3, 48 46 octets

f=lambda x,i=1:f(x,i+1)if(i+3)*i+2<x/i*6else i
0WJYxW9FMN
la source
@FlipTack Argh! Je vais le réparer dans une seconde ... personne ne dévalorise, s'il vous plaît.
0WJYxW9FMN du
6
Vous pouvez empêcher tout vote en aval en supprimant votre réponse. Vous pourrez ensuite modifier la réponse et la supprimer une fois qu'elle sera corrigée.
Laikoni
De plus, cela ne fait toujours pas ce que le défi demande. Une entrée de 221le plantera.
FlipTack
J'ai testé cela sur TIO et ça plante sur toutes les entrées. Est-ce mon problème ou cela arrive-t-il à quelqu'un d'autre?
Ça a marché pour moi. Je vais le tester à nouveau.
0WJYxW9FMN
1

Mathematica, 31 25 octets

Floor@Root[x^3-x-6#+6,1]&
Martin
la source
1

Haskell, 21 23 octets

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

Edit: Comme l'a souligné xnor, la solution originale ( floor.(/0.82).(**0.4)) n'a pas fonctionné entre les jours de Noël

Joshua David
la source
Cela donne la mauvaise réponse sur de nombreuses entrées, par exemple 221.
xnor
0

Lot, 69 octets

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

Calcule manuellement les nombres tétraèdres.

Neil
la source
0

R, 19 caractères

floor((n*6)^.33359)

basé sur la réponse de xnor dans Python.

Mark Miller
la source
0

QBIC , 19 octets

Cela vole la formule de @xnor:

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

J'ai essayé de réduire la résolution à .3336 pour enregistrer un octet, mais cela échoue sur le testcase final.

steenbergh
la source
0

Bash + bc, 44 octets

bc -l <<< "f=e(.33359*l($1*6));scale=0;f/1"
Dani_l
la source