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


35

Avec un entier positif N , votre tâche consiste à renvoyer le nombre d'étapes requis par l'algorithme suivant pour atteindre N :

  1. Trouvez le nombre le plus petit triangle T i tel que T i  ≥ N . Construisez la liste correspondante L = [1, 2, ..., i] .

  2. Bien que la somme des termes de L soit supérieure à N , supprimez le premier terme de la liste.

  3. Si la somme des termes de L est maintenant inférieure à N , incrémentez i et ajoutez-le à la liste. Continuez avec l'étape # 2.

Nous nous arrêtons dès que N est atteint. Seule la première étape est systématiquement exécutée. Les étapes 2 et 3 peuvent ne pas être traitées du tout.

Exemples

Voici un exemple pour N = 11 :

Exemple

La sortie attendue pour N = 11 est donc 4 .

Autres exemples:

  • N = 5 - On commence avec T 3 = 1 + 2 + 3 = 6 , suivi de 2 + 3 = 5 . Résultats attendus: 2 .
  • N = 10 - Seule la première étape est requise car 10 est un nombre triangulaire: T 4 = 1 + 2 + 3 + 4 = 10 . Résultats attendus: 1 .

100 premières valeurs

Voici les résultats pour 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

Règles

  • Vous pouvez écrire un programme complet ou une fonction qui imprime ou renvoie le résultat.
  • Vous devez traiter une N ≤ 65536 en moins d'une minute sur le matériel de milieu de gamme.
  • Avec suffisamment de temps, votre programme / fonction devrait théoriquement fonctionner pour toute valeur de N supportée nativement par votre langue. Si ce n'est pas le cas, veuillez expliquer pourquoi dans votre réponse.
  • C'est le code de golf, donc la réponse la plus courte en octets gagne!

En relation. (Je suppose que vous connaissez déjà celui-ci, mais que
vous

Quelle est la valeur maximale de N que nous devons gérer?
Luc

@ Luke S'il vous plaît voir les règles mises à jour.
Arnauld

Réponses:


4

Gelée , 29 à 31 octets

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

Un lien monadique qui renvoie le résultat (N = 65536 prend moins de deux secondes).

Essayez-le en ligne!

Comment?

Pour une explication détaillée de l'algorithme, voir l'article fantastique de Martin Ender .

Æ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

L’implémentation de programme complet de 29 octets que j’ai créée de l’algorithme décrit prend 4 min 30 pour N = 65536 sur mon ordinateur portable; je suppose donc que cela ne compte pas.

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

Utiliser une boucle while pour chaque étape 3 et la réutiliser en tant qu'étape 1 a la même longueur que ce que je peux gérer avec l'initialisation de la liste car l'absence de vérification à l'étape 3 signifie construire une liste jusqu'à ce qu'il ne reste plus rien, puis trouver le premier index de la valeur:

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

25

Mathematica, 79 octets

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

Explication

Je ne pouvais pas être dérangé pour implémenter l'algorithme dans le défi, alors je voulais chercher un raccourci vers la solution. Bien que j'en ai trouvé un, malheureusement, il ne bat pas la réponse de Mathematica qui implémente l'algorithme. Cela dit, je suis sûr que le jeu n’est pas encore optimal et que d’autres langues pourraient bénéficier de cette approche ou de certaines des connaissances acquises au cours du processus.

Je prétends donc que la séquence que nous sommes supposés calculer est la suivante:

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

Sinon, c'est f (n) = 1 si n est un nombre triangulaire et f (n) = 2 * ( A212652 (n) - A002024 (n) + 1) sinon.

Dans la première expression, A023532 code simplement ces deux cas différents. Les deux autres séquences (plus 1) représentent la différence entre le plus grand entier k de la plus longue décomposition de n en entiers consécutifs (k-i + 1) + (k-i + 2) + ... + k = n et le plus grand entier j tel que 1 + 2 + ... + j <n .

En termes plus simples, voici comment trouver la réponse aux nombres non triangulaires: premièrement, trouvez le plus grand nombre triangulaire T j qui est inférieur à n . Alors j est l’avant-dernier nombre entier ajouté lors de l’étape 1 (car après avoir ajouté j + 1, nous aurons dépassé n ). Décomposez ensuite n en autant d’entiers consécutifs que possible (ou le plus petit possible) et appelez le maximum parmi ces nombres k . Le résultat est simplement 2 * (kj) . La raison intuitive en est que le maximum dans la décomposition augmente de 1 à chaque étape et nous nous arrêtons lorsque nous atteignons.k .

Nous devons montrer quatre choses pour prouver que cela fonctionne:

  1. f (n) = 1 pour les nombres triangulaires. C’est trivialement le cas, car la première étape consiste simplement à parcourir tous les nombres triangulaires. Si nous touchons n exactement pendant ce processus, nous avons terminé et il n'y avait qu'une seule étape pour calculer.
  2. Pour tous les autres numéros, nous finissons toujours après une étape de suppression, jamais après une étape d’insertion. Cela signifie que tous les autres f (n) sont pairs.
  3. A chaque étape d'insertion après la première, nous ajoutons un seul numéro. Cela garantit que nous arriverons à une décomposition comprenant k après kj paires de pas.
  4. La décomposition finale de n que nous obtenons est toujours la plus longue décomposition possible de n en nombres entiers consécutifs, ou, en d'autres termes, c'est toujours la décomposition de n avec le maximum le plus bas parmi les nombres additionnés. En d'autres termes, le dernier nombre ajouté à la somme est toujours A212652 (n) .

Nous avons déjà montré pourquoi (1) est vrai. Ensuite, nous prouvons que nous ne pouvons pas terminer sur une étape d’insertion à l’exception de la première (ce qui n’arrive pas pour les nombres non triangulaires).

Supposons que nous terminions sur une étape d'insertion, atteignant n après avoir ajouté une valeur p à la somme. Cela signifie qu'avant cette étape d'insertion, la valeur était np ( ou inférieure si nous ajoutions plusieurs valeurs à la fois). Mais cette étape d’insertion a été précédée d’une étape de suppression (nous n’aurions pas pu toucher n lors de l’étape 1). La dernière valeur q que nous avons supprimée au cours de cette étape de suppression était nécessairement inférieure à p en raison du fonctionnement de l'algorithme. Mais cela signifie que, avant de retirer q, nous avions n-p + q ( ou moins ), ce qui est inférieur à n. Mais ce qui est une contradiction, parce que nous aurions dû arrêter la suppression des entiers lorsque nous avons atteint n-p + q au lieu d'enlever une autre q . Cela prouve le point (2) ci-dessus. Nous savons donc maintenant que nous terminons toujours par une étape de suppression et que, par conséquent, tous les nombres non triangulaires ont des sorties paires.

Ensuite, nous prouvons (3) que chaque étape d’insertion ne peut insérer qu’une valeur. Ceci est essentiellement un corollaire de (2). Nous avons montré qu'après avoir ajouté une valeur, nous ne pouvions pas atteindre n exactement et puisque la preuve utilisait une inégalité, nous ne pouvions pas non plus nous retrouver sous n (depuis lors, n-p + q serait toujours inférieur à n et nous n'aurions pas dû être supprimés). autant de valeurs en premier lieu). Donc, chaque fois que nous ajoutons une seule valeur, nous sommes assurés de dépasser n parce que nous sommes passés en dessous de n en supprimant une valeur plus petite. Par conséquent, nous savons que la partie supérieure de la somme augmente de 1 à chaque étape. Nous connaissons la valeur initiale de cette extrémité supérieure (c’est le plus petit m tel queT m > n ). Maintenant, il ne nous reste plus qu'à déterminer cette limite supérieure une fois que nous aurons atteint la somme finale. Ensuite, le nombre d'étapes est simplement le double de la différence (plus 1).

Pour ce faire, nous prouvons (4) que la somme finale est toujours la décomposition de n en autant d’entiers que possible, ou la décomposition où le maximum de cette décomposition est minimal (c’est-à-dire la décomposition la plus précoce possible). Nous le ferons à nouveau par contradiction (le libellé de cette partie pourrait être un peu plus rigoureux, mais j'ai déjà passé beaucoup trop de temps à ce sujet ...).

Disons que la décomposition la plus ancienne / la plus longue possible de n est un peu a + (a + 1) + ... (b-1) + b , a ≤ b , et que l'algorithme la saute. Cela signifie qu'au moment où b est ajouté, a ne doit plus faire partie de la somme. Si a faisait partie de la somme s , alors nous aurions n ≤ s à ce moment. Donc soit la somme ne contient que les valeurs de a à b , ce qui équivaut à n et nous nous arrêtons (par conséquent, nous n'avons pas ignoré cette décomposition), ou bien il existe au moins une valeur inférieure à a dans la somme, gagner auquel cas n <set cette valeur serait supprimée jusqu'à ce que nous atteignions la somme exacte (encore une fois, la décomposition n'a pas été ignorée). Il faudrait donc nous débarrasser de a avant d’ajouter b . Mais cela signifie que nous devrions atteindre une situation dans laquelle a est la plus petite composante de la somme, et la plus grande n'est pas encore b . Cependant, à ce stade, nous ne pouvons pas supprimer a , car la somme est clairement inférieure à n (puisque b est manquant), nous devons donc ajouter des valeurs en premier jusqu'à ce que nous ajoutions b et n exactement. Cela prouve (4).

Donc, en prenant ces choses ensemble: nous savons que la première paire d’étapes nous donne une valeur maximale de A002024 (n) . Nous savons que la valeur maximale de la décomposition finale est A212652 (n) . Et nous savons que ce maximum est incrémenté une fois par paire. Par conséquent, l'expression finale est 2 * ( A212652 (n) - A002024 (n) + 1) . Cette formule fonctionne presque pour les nombres triangulaires, sauf que pour ceux-ci nous avons seulement besoin d'un pas, c'est pourquoi nous corrigeons le résultat avec la fonction indicatrice des nombres triangulaires (ou son inverse, selon ce qui convient le mieux).

Enfin, quant à la mise en œuvre. Pour la première séquence, j'utilise la formule MIN (impaire d | n; n / d + (d-1) / 2) d'OEIS. Il s'avère économiser quelques octets si nous prenons le facteur 2 dans cette expression pour obtenir MIN (impair d | n; 2n / j + d-1) , car -1 s'annule alors avec le +1 dans ma première version de f (n) qui code directement les deux cas pour les nombres triangulaires et non triangulaires. Dans le code, c'est:

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

Pour cette dernière séquence ( 1, 2, 2, 3, 3, 3, ...), nous pouvons utiliser un formulaire fermé simple:

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

Enfin, la fonction indicatrice inverse des nombres triangulaires est 0 lorsque 8n + 1 est un carré parfait. Ceci peut être exprimé dans Mathematica comme

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

Il y a beaucoup de façons d'exprimer ces deux dernières séquences et de décaler un décalage constant entre elles. Je suis donc certain que cette implémentation n'est pas encore optimale, mais j'espère que cela pourrait donner à d'autres un point de départ pour explorer de nouvelles approches. leurs propres langues.

Depuis que je suis allé à tous ces problèmes, voici un graphique de la séquence allant jusqu'à n = 1000 (je pourrais aussi calculer 100k en quelques secondes, mais cela ne montre pas vraiment d'informations supplémentaires):

entrez la description de l'image ici

Il serait peut-être intéressant d'examiner les variations à propos de ces lignes très droites, mais je laisserai cela à quelqu'un d'autre ...


J'ai finalement pris le temps de lire attentivement votre réponse. C'est génial. Notez que (3) a déjà été supposé dans l'algorithme (l'étape n ° 3 est un if , pas un instant ), mais la preuve est - bien sûr - très appréciée.
Arnauld

@Arnauld Merci. :) Je dois avoir négligé / mal compris la partie si / tout. C'est une bonne chose que cela ne fasse aucune différence alors.
Martin Ender

7

Mathematica, 72 octets

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

Fonction pure prenant un argument entier.

Comment ça marche

For[ ... ]

Une Forboucle

l=u=c=k=0

Initialisation; définir l(inférieur), u(supérieur), c(compteur) et k(somme) sur 0.

k!=#

État; répéter tant que kn'est pas égal à l'entrée.

c++

Incrément; incrémenter le compteur c.

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

Corps

If[#>k, ... ]

Si l'entrée est supérieure à k:

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

Tant que l'entrée est supérieure à k, incrémenter uet incrémenter kde u.

Si l'entrée n'est pas supérieure à k:

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

Alors que l'entrée est inférieure k, décrément kpar let incrément l.

( ... ;c)

Retour caprès la boucle.


1
For[,...]beats While[...].
Martin Ender

5

Python 2 , 104 octets

N=input();i=s=0;l=()
while N!=sum(l):exec'while sum(l)'+['<N:i+=1;l+=i,','>N:l=l[1:]'][s%2];s+=1
print s

Essayez-le en ligne!

Alterner entre l'ajout de termes à la fin de la liste et la suppression de termes au début.


5

Haskell , 70 63 68 64 octets

MODIFIER:

  • -7 octets: Supprimez un espace, deux signes et des parenthèses en annulant le sens de a. Correction des erreurs par une dans l'explication.
  • +5 octets: Argh, complètement manqué cette exigence 65536, et il se trouve (1) des puissances de 2 sont particulièrement chers, parce qu'ils obtiennent seulement frappé quand vous obtenez le nombre lui - même (2), est la somme des plages longues (qui enroulent autour zéro) tout le temps. Remplacé la somme par une formule mathématique.
  • -4 octets: ajusté aet blinéairement pour que les termes de la formule de sommation soient annulés.

1#1 est une fonction anonyme prenant et renvoyant un entier.

Utiliser comme (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]

Essayez-le en ligne!

Comment ça marche

  • (a#b)nreprésente l'étape actuelle du calcul. a, bsont des nombres 1, 3, 5, .., alors que npeuvent être positifs ou négatifs selon l’étape.
    • Aux étapes 1 ou 3, il représente la liste [(a+1)/2,(a+3)/2..(b-1)/2]et le numéro d'objectif -n.
    • À l'étape 2, il représente la liste [(b+1)/2,(b+3)/2..(a-1)/2]et le numéro d'objectif n.
  • La correspondance étrange entre a, bet les listes permet de faire la somme avec l'expression courte s=a*a-b*b.
    • Aux étapes 1 et 3, il en va de même s= -8*sum[(a+1)/2..(b-1)/2].
    • À l'étape 2, c'est la même chose que s=8*sum[(b+1)/2..(a-1)/2].
  • La création de branches se fait en ayant une compréhension de liste qui ne produit des éléments que dans un cas chacun et en résumant les résultats.
    • Si s>8*n, alors best incrémenté de 2 avant la récursivité.
      • Aux étapes 1 et 3, la liste s’allonge, alors qu’à l’étape 2, elle est réduite.
    • Si s<8*n, puis récursion change l'étape en échangeant aet b, et la négation n, et 1 est ajouté au résultat.
    • Si s==8*n, alors aucune des deux compréhensions de liste ne donne d’éléments, la somme est donc 0.
  • (1#1) nreprésente une "étape 2" factice avant de commencer, qui passe immédiatement à l’étape 1, qui construit la liste [1..0]=[].

4

PHP> = 7.0, 74 octets

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

utiliser l' opérateur du vaisseau spatial

Essayez-le en ligne!

Étendu

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

C'est quoi $argn?
Chx

@chx Une variable qui est disponible lorsque vous utilisez PHP depuis la ligne de commande avec l'option -R php.net/manual/fr/features.commandline.options.php
Jörg Hülsermann

Sensationnel. Je n'ai jamais entendu parler de -Rbeaucoup moins argvou argi. Je connaissais argc et argv bien sûr. Très intéressant, merci.
chx

4

C, 94 91 octets

Essayez en ligne

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;}

Utilisation intensive sur les variables non initialisées oO
YSC

@YSC en C, les entiers déclarés globalement non initialisés sont mis à zéro lors de la compilation. lire plus
Khaled.K

Oublié à ce sujet. Merci pour ce rappel.
YSC

Pour votre information, j'ai posté une autre réponse C . Au moins un des trucs que j'ai utilisés ne fonctionnera pas avec les autres compilateurs (les disparus return), mais pour ceux qui le font, n'hésitez pas à les intégrer à votre réponse.
17h à 20h42

3

JavaScript (ES6), 82 octets

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

Test Snippet


Désolé de le dire, mais chaque compte pour 3 octets. Je suppose que ça n'a pas d'importance, car c'est trivialement renommable.
Ørjan Johansen

@ ØrjanJohansen Merci de me le rappeler. Je ne devrais vraiment pas oublier de noter mon code par octets plutôt que par longueur. Je ne pense pas qu'il y ait un consensus de la communauté sur les "[variables] trivialement renommables" alors j'ai édité le post. Tant pis.
R. Kap

3
L'extrait de code échoue avec “Trop de récursivité” sur 6553. 6553 fonctionne localement dans le nœud (6.9.1), mais pas avec 65536 (“Taille maximale de la pile d'appels dépassée”).
eush77

3

dc , 61 octets

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

Essayez-le en ligne!

Explication

Macro récursive principale:

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

Cette macro:

  1. Recherche le nombre minimum triangulaire qui dépasse le nombre actuel sur la pile (à l'aide de la formule racine triangulaire modifiée ).
  2. Vérifie si la somme triangulaire Sreprésente le nombre actuel exactement. Quitte si c'est le cas.
  3. Passe à l'étape 1 avec S+N(sur-approximation) ou S-N(sous-approximation), le choix alterne entre les itérations.

Quand il sort, la trace laissée sur la pile indique au programme principal le nombre d’itérations qu’il a pris.


3

Python 3, 150 138 octets

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)

Changelog:

  • Modification ajoutée à + =, supprimée (merci musicman523, Loovjo; -12 octets)

1
L'étape 2 peut supprimer un ou plusieurs termes à la fois de la liste (comme 1, 2 et 3 dans l'exemple pour N = 11), mais est comptée comme une étape dans les deux sens.
Arnauld

@Arnauld a négligé cela; fixé.
L3viathan

1
Pouvez-vous expliquer pourquoi le elseest nécessaire? Je crois que les elseexécutions à chaque fois, parce que la boucle se termine toujours normalement (sans break), et elle semble fonctionner correctement sans cela .
musicman523

Vous pouvez ignorer la A=l.appendpièce et l'utiliser à la l+=[x]place.
Loovjo,

3

Lot, 126 octets

@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

Explication: lest zéro si l'étape 2 n'a jamais été exécutée. Cela permet nde suivre le nombre d'itérations de l'étape 3. Etant donné que l'algorithme ne s'arrête jamais à l'étape 3, il doit donc avoir exécuté l'étape 1 une fois et l'étape 2 n+1fois pour un total d' n+n+2étapes. Toutefois, si le paramètre est un nombre triangulaire, l’étape 2 ne s’exécutant jamais, il faut soustraire une étape.


3

Python 2, 86 81 octets

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

Essayez-le en ligne!

Calcule le scénario de test 65536 dans 0.183sTIO.


Cette version récursive à 84 octets ne permet pas de calculer toutes les valeurs jusqu'à 65 536:

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)

Essayez-le en ligne!


2

Mathematica, 92 octets

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

Fonction pure prenant un argument entier et renvoyant un entier.

Les variables aet breprésentent les nombres de début et de fin (en constante évolution) dans la somme considérée, tandis que qreprésente le total cumulé (des nombres de a+1à b); tgarde la trace de toutes les valeurs qrencontrées jusqu'à présent. Après l’initialisation de ces variables, la Forboucle continue de s’exécuter If[q<#,q+=++b,q-=++a], ce qui ajoute un nouveau nombre à la fin ou soustrait le nombre situé au premier rang, comme le spécifie la spécification, jusqu’à ce que ql’entrée soit égale.

Il ne reste plus qu’à extraire le nombre d’étapes t, la liste des qvaleurs rencontrées. Par exemple, lorsque l'entrée est 11, la Forboucle se termine avec tégalisation {0,1,3,6,10,15,14,12,9,15,11}. Le meilleur moyen que j’ai trouvé de calculer le nombre d’étapes à partir de ceci est de compter combien de fois les différences passent d’une baisse à une autre; c'est ce que la commande verbeuse Length@Split@Sign@Differences@tfait, mais je suppose que cela peut être amélioré.


2

C (tcc), 71 octets (61 + 10)

Arguments en ligne de commande (y compris un espace):

-Dw=while

La source:

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

Comment ça marche:

ccompte le nombre d'étapes. met Mstocker le minimum et le maximum de la plage, sla somme. Au départ, ils sont tous nuls.

Continue, cest augmenté, et sest comparé à n. Tant qu'ils sont inégaux:

  • Si cest impair, alors tant que s<n, ajoutez un entier à la fin de la plage: augmentez Mde un et sde M.

  • Si cest encore, alors tant que s>n, supprimer un nombre entier depuis le début de la plage: diminution sde m, et d' augmenter mpar un.

Lorsque la boucle sort, ca été augmentée une fois de trop. La décrémentation produit le résultat correct et elle est calculée dans le registre correct pour servir de valeur de retour.

Il arrive de façon amusante d’utiliser exactement le même nom de variable que la réponse C de Khaled.K . Ils ne sont pas copiés.


1

Perl 6 , 114 octets

{((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}

(inspiré d'une implémentation antérieure de Haskell )

Essayez-le
Il fonctionne avec une entrée de 65 536 en moins de 45 secondes sur mon ordinateur, mais je n'ai pas réussi à le faire fonctionner en moins de 60 secondes avec TIO.run.
J'ai Rakudo v2017.04 +, où il a v2017.01 .
Rakudo / NQP / MoarVM étant optimisé presque tous les jours, un nombre quelconque d'entre elles pourraient être nécessaires entre-temps pour l'intégrer plus rapidement.


Étendu

{
  (

    # 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
}

Notez que Rakudo a une optimisation pour Range.sumne pas avoir à parcourir toutes les valeurs.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.