La somme des nombres impairs consécutifs


24

Bien que des défis connexes aient été posés , celui-ci est différent pour justifier sa propre question.


Défi

Étant donné un entier positif, retournez la plus longue séquence d'entiers impairs positifs consécutifs dont la somme est l'entier donné. Si aucune séquence de ce type n'existe, vous pouvez signaler une erreur de la manière qui convient à votre langue, notamment en renvoyant une valeur fausse ou en lançant une exception.

Cas de test

  1 -> [1]
  2 -> []
  3 -> [3]
  4 -> [1, 3]
  5 -> [5]
  6 -> []
  9 -> [1, 3, 5] (notez que [9] n'est pas une réponse valide)
 15 -> [3, 5, 7]
104 -> [23, 25, 27, 29] (notez que [51, 53] n'est pas une réponse valide)

Notation

C'est le , donc la réponse la plus courte dans chaque langue l'emporte.


2
Mon programme peut-il fonctionner pour toujours s'il n'y a pas de solution?
Dennis

Très lié . Le fait que certains nombres pairs ne puissent pas être représentés dans celui-ci pourrait cependant l'empêcher d'être dupe.
ETHproductions

6
15 ne peuvent-ils pas donner [-1, 1, 3, 5, 7]? Si seules des valeurs positives sont autorisées, vous devez le dire.
xnor

2
@ ЕвгенийНовиков vous avez sauté 17
kalsowerus

1
@kalsowerus oui. J'ai mal compris le mot "consécutif"
Евгений Новиков

Réponses:


11

Haskell, 67 65 63 62 58 octets

4 octets enregistrés grâce à Julian Wolf

f x=[[2*n+1,2*n+3..2*m]|n<-[0..x],m<-[n..x],m^2-n^2==x]!!0

Essayez-le en ligne!

Je vérifie si le nombre peut être exprimé comme il différence de deux places: m^2-n^2. Je peux alors construire la liste des numéros impairs consécutifs: [2n+1,2n+3...2m-1]. Notez que parce que le minimum nest choisi, la liste la plus longue sera sortie


7
Votant: Il serait à la fois plus convivial et plus constructif d'ajouter un commentaire donnant votre raison, en particulier lorsque vous votez contre un nouvel utilisateur.
Jonathan Allan

1
Sauf si je manque quelque chose, vous pouvez économiser 4 octets en ne montant que xpour les deux netm
Julian Wolf

Juste pour que vous le sachiez, le downvote a été automatiquement casté par l'utilisateur de la communauté lorsque vous avez modifié votre réponse. Je considère cela comme un bug . (CC @JonathanAllan)
Dennis

Ahh, c'était l'un d'eux.
Jonathan Allan

9

Python 2 , 66 62 octets

f=lambda n,k=0,*r:n-sum(r)and f(n,k+1,*range(k%n|1,k/n,2))or r

Quitte avec un RuntimeError (profondeur de récursivité maximale dépassée) s'il n'y a pas de solution.

Essayez-le en ligne!


1
Si les valeurs d'entrée sont suffisamment élevées, mais qu'il existe une solution, cela entraînera-t-il une erreur d'exécution ?
Okx

Si la limite de récursivité n'est pas assez élevée et / ou la pile n'est pas assez grande, oui. Cependant, il est courant d'ignorer les limitations physiques (par exemple, une réponse C ne doit fonctionner que pour des entiers 32 bits), et l'OP a explicitement déclaré que l'exécution pour toujours est acceptable s'il n'y a pas de solution.
Dennis

9

Gelée ,  11  10 octets

-1 octet grâce à Dennis (utilisez la construction implicite de la plage de - remplacer Rm2Ẇpar ẆḤ’)

ẆḤ’S_¥Ðḟ⁸Ṫ

Un lien monadique renvoyant une liste des sommets si possible, ou 0sinon.

Essayez-le en ligne!

Comment?

ẆḤ’S_¥Ðḟ⁸Ṫ - Link: number, n
Ẇ          - all sublists (implicit range of input) note: ordered by increasing length
           -                i.e. [[1], [2], [3], ..., [1,2], [2,3], ..., [1,2,3], ...]]
 Ḥ         - double              [[2], [4], [6], ..., [2,4], [4,6], ..., [2,4,6], ...]]
  ’        - decrement           [[1], [3], [5], ..., [1,3], [3,5], ..., [1,2,5], ...]]
        ⁸  - link's left argument, n
      Ðḟ   - filter out items for which the following yields a truthy value:
     ¥     -   last two links as a dyad:
   S       -     sum
    _      -     subtract the right from the left = sum - n
         Ṫ - tail (last and hence longest such run)

1
ẆḤ’enregistre un octet.
Dennis

8

JavaScript (ES7), 87 86 85 81 octets

Renvoie une liste d'entiers délimités par des virgules, ou 0s'il n'existe aucune solution.

n=>(g=(s,k,x=n+s)=>(x**.5|0)**2-x?k>n?0:g(s+k,k+2):(n-=k)?k+','+g(-n,k+2):k)(0,1)

Comment?

Nous recherchons d'abord le plus petit carré parfait s tel que x = n + s soit un autre carré parfait.

Si s existe, n est la différence x - s de 2 carrés parfaits, qui peut être écrite comme la différence de 2 séquences de nombres impairs consécutifs. Nous construisons ensuite la liste résultante.

Exemple:

Pour n = 104 :

On trouve s = 11² = 121 qui satisfait x = n + s = 225 = 15²

Ensuite:

15² = 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21 + 23 + 25 + 27 + 29
11² = 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21
104 = 15² - 11² = 23 + 25 + 27 + 29


3
Attendez, vous me dites que n^2c'est toujours égal à la somme des premiers nnombres impairs? Huh, intéressant
Skidsdev

2
@Mayube En effet !
Arnauld


7

05AB1E , 9 8 octets

-1 octet grâce à Emigna

ÅÉŒʒOQ}н

Explication:

ÅÉ           Generate a list of odd numbers up to, and including, the input
  Œ          Substrings
   ʒ         Only keep values
    O          where the sum
     Q         equals the input
       }     End
             For 9, the result would look like this:
             [[1, 3, 5], [9]]
        н    Get the first value

Sur une entrée invalide, ne produit rien.

Essayez-le en ligne!


ʒOQ}au lieu d' DO¹QÏenregistrer un octet.
Emigna

@JonathanAllan Docs dit "inégal", donc ça pourrait être confus ...
Erik the Outgolfer

1
@JonathanAllan Petite erreur. Fixé.
Okx

6

Haskell , 61 60 octets

Merci à @maple_shaft pour avoir rasé 1 octet

f n=[k|r<-[1,3..],s<-[r,r+2..n],k<-[[r,r+2..s]],sum k==n]!!0

Essayez-le en ligne!

Utilise le fait que la course la plus longue sera toujours celle qui commence par le plus petit nombre.

Je voulais faire quelque chose avec l'arithmétique au lieu du forçage brutal k, mais fromIntegersemble le tuer.


Vous pouvez vous épargner un octet en changeant [1,3..n]à[1,3..]
maple_shaft

1
Vous pouvez enregistrer 7 octets avec une fonction d'assistance r?n=[r,r+2..n]. Essayez-le en ligne!
Ørjan Johansen

4

Python , 67 octets

f=lambda n,R=[1]:n-sum(R)and f(n,[R+[R[-1]+2],R[1:]][sum(R)>n])or R

Essayez-le en ligne!

J'ai copié ma réponse du défi de somme consécutif précédent et changé la +1en +2. Qui savait que le code du golf pouvait être si modulaire?

Une stratégie étrangement simple: recherchez l'intervalle Ravec la somme souhaitée.

  • Si la somme est trop petite, déplacez l'extrémité droite de l'intervalle vers le haut de 2 en ajoutant le numéro 2 suivant au-dessus.
  • Si la somme est trop grande, déplacez l'extrémité gauche vers le haut en supprimant le plus petit élément
  • Si la somme est correcte, sortez R.

Comme l'extrémité inférieure de l'intervalle ne fait qu'augmenter, des intervalles plus longs sont trouvés avant des intervalles plus courts. Si aucun intervalle possible ne peut être trouvé, se termine par IndexError.


4

JavaScript (ES6), 65 64 octets

f=(a,i=1)=>a>i?(c=f(a-i,i+=2))[0]==i?[i-2,...c]:f(a,i):a<i?0:[i]

Renvoie un tableau s'il y a une solution, ou 0 pour aucune solution.

Il s'agit d'une solution très inefficace mais golfique au problème.

Il recherche la première solution en utilisant a-iet i=1, même s'il ne fonctionne pas sur la pile récursive. Si cette solution ne commence pas i+2, alors nous recherchons récursivement la première solution en utilisant aet i+2.

Non golfé

f=(a,i=1)=>
  a > i ? 
    (c = f(a - i, i += 2))[0] == i ? 
      [i-2, ...c] : 
      f(a, i) :
  a < i ? 
    0 :
    [i]

Cas de test:

Pour avoir une idée de son inefficacité, la solution à f(104)nécessite 69 535 appels récursifs. La pile n'a jamais plus de 51 niveaux de profondeur, donc aucun problème de débordement de pile.

La solution f(200)nécessite 8,6 millions d' appels récursifs, avec une pile de 99 niveaux de profondeur. (Sa solution est [11,13,15,17,19,21,23,25,27,29].)

Voici une représentation visuelle du programme en cours d'exécution:


3

Python 2.7, 109 108 97 octets

11 octets vers le bas, Merci à Erik l'Outgolfer.

Ceci est mon premier golf de code!

def f(N):
 for n in range(N):
    x=(n*n+N)**.5-n
    if x%1==0:return[2*(k+n)+1for k in range(int(x))]

Comment ça marche

J'ai utilisé l'identité bien connue 1 + 3 + 5 + ... + (2n - 1) = n²

Prenons le cas de 15

15 = 3 + 5 + 7 = (1 + 2) + (3 + 2) + (5 + 2) = (1 + 3 + 5) + 3×2 = 3² + 3×2

En général, s'il y a x termes commençant par 2n + 1, comme

(2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))


C'est égal à 2nx + x²

Si Nest l'entier en entrée, le problème se réduit à trouver un maximum xtel que

x² + 2nx - N = 0

C'est une équation quadratique avec solution

x = sqrt(n² + N) - n

La séquence la plus longue est celle avec la plus grande x. Le programme itère nde 0à Net lorsqu'il trouve qu'il xs'agit d'un entier, il crée une liste de (2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))et la renvoie.



@EriktheOutgolfer, Merci, j'ai oublié d'utiliser des onglets (=
dark32

3

Python 3, 190 81 octets

def c(q,l,i):
    if sum(l)0:
        l.append(i)
        return c(q,l,i+2)
    elif sum(l)>q:
        l.pop(0)
        return c(q,l,i)
    else:
        print(l)
c(q,[1],1)

c=lambda q,l=[1]:c(q,l+[l[-1]+2])if(sum(l)<q)*l else c(q,l[1:])if sum(l)>q else l

Merci à @ovs et @ musicman523


4
Vous pouvez le réduire à 122 octets simplement en supprimant une indentation . Si vous souhaitez raccourcir davantage votre code, consultez les conseils pour jouer au golf en Python .
2017

3
Cela ne fonctionne pas dans Python 3, car il printmanque des parenthèses à l'appel à
musicman523

2
Vous pouvez supprimer l.append(i)en utilisant simplement l+[i]dans l'appel récursif. Vous pouvez supprimer l.pop(0)en utilisant l[1:]dans l'appel récursif. Vous pouvez supprimer l'appel à ctout en bas en utilisant des arguments de mots clés à la place. Vous pouvez supprimer >0à la ligne 2. Enfin, vous pouvez changer vos instructions ifet elseen expressions, en utilisant la forme ternaire, qui vous ramène à 92 octets comme expression lambda. Essayez-le en ligne!
musicman523

1
Sur la base des suggestions de @ musicman523, nous pouvons toujours raccourcir les conditions et réduire ipour atteindre un total de 81 octets .
ovs

Je pense que vous pouvez changer sum(l)>q elsepour q<sum(l)elsesauver 1 octet.
Zacharý

2

QBIC , 47 octets

{_Cg=q┘q=q+2~g>:|_Xp\?g,[q,a,2|?b,┘g=g+b~g=a|_X

Cela essaie de compter tous les nombres impairs de un jusqu'à ce que sa somme soit n. S'il passe n, réinitialisez la boucle, augmentez de 1 à 3 et réessayez. Quittez, en imprimant 0, si au début de la boucle notre numéro > n.

Explication

{       Do infinitely
_C      Clear the screen (we basically print every run of odd numbers, but clear out everything that doesn't sum up to n)
g=q     Set g to the first num of this cycle (q starts as 1 in QBIC)    
┘       (Syntatcic linebreak)
q=q+2   Raise q to the next odd number, this sets up both the next outer loop as well as a coming FOR loop
~g>:|   If we start out with a number > n (read as 'a' from the cmd line)
_Xp     THEN quit, printing 0 (the value of the number var 'p')
\       ELSE
[q,a,2| FOR b = q, b <= n, b+=2
?b,┘    PRINT b followed by a tab
g=g+b   Add 'b' to running total 'g'
~g=a|   and if that lands us on 'n'
_X      QUIT (printing nothing: everything is already printed)

1

R , 90 octets

f=function(x,y=1)'if'(length(w<-which(cumsum(r<-y:x*2-1)==x)),r[1:w],'if'(y>x,0,f(x,y+1)))

Essayez-le en ligne!

Utilise une fonction récursive qui teste la somme cumulée de la séquence de y: x convertie en une séquence de nombres impairs. y est incrémenté à chaque récursivité jusqu'à ce qu'il dépasse x. La première séquence qui résume la cible sera retournée.


1

Python 2 , 89 octets

lambda n,r=range:[v for v in[r(1,n+1,2)[i:j]for i in r(n)for j in r(n+1)]if sum(v)==n][0]

Une fonction sans nom prenant un entier positif n, et renvoyant le résultat s'il existe et levant un IndexErrorsinon.

Essayez-le en ligne!

Crée une liste de tous les nombres impairs pertinents avec r(1,n+1,2)lesquels est range(start=1, stop=n+1, step=2); crée toutes les sous-tranches pertinentes (plus quelques-unes vides) en découpant cela d' iinclusif à jexclusif avec [i:j]travers idans [0, n) en utilisant r(n)et jdans [0, n] en utilisant r(n+1)(les vides lorsque i>=jou ihors limites); filtres pour ceux avec la somme correcte avec if sum(v)==n; renvoie la première (et donc la plus longue) tranche de ce type en utilisant [0].




1

PHP , 73 octets

aucune solution n'est une boucle infinie

for($e=-1;$s-$i=$argn;)$s+=$s<$i?$n[]=$e+=2:-array_shift($n);print_r($n);

Essayez-le en ligne!

PHP , 83 octets

imprime rien pour aucune solution

chaque mod d'entrée 4 == 2 n'a pas de solution

for($e=-1;($i=$argn)%4-2&&$s-$i;)$s+=$s<$i?$n[]=$e+=2:-array_shift($n);print_r($n);

Essayez-le en ligne!


ne parvient pas à détecter une entrée insoluble
Titus

@Titus fixed ...
Jörg Hülsermann


0

Python 3 , 93 octets

lambda n,r=range:[[*r(s,e+1,2)]for s in r(1,n+1,2)for e in r(s,n+1,2)if(s+e)*(2+e-s)==4*n][0]

Essayez-le en ligne!

La seule chose spéciale que j'ai faite était de noter que cela (s+e)*(2+e-s)==4*néquivaut à sum(range(s,e+1,2))==n, et bien qu'ils soient de la même taille quand r=range, les premiers peuvent être placés plus près de la ifdéclaration.


0

Python 3 , 185 octets

def f(s):
  d={k:v for k,v in{a:(1-a+((a-1)**2+4*s)**(.5))/2 for a in range(1,s,2)}.items()if int(v)==v};m=max(d.keys(), key=(lambda k: d[k]));return list(range(int(m),int(m+2*d[m]),2))

Essayez-le en ligne!


Quant à la façon dont cela fonctionne, j'ai essayé d'opter pour une solution un peu plus élégante qu'une simple recherche par force brute. J'ai réorganisé la formule pour la somme d'une séquence arithmétique et appliqué la formule quadratique pour obtenir l'expression (1-a+((a-1)**2+4*s)**(.5))/2, qui apparaît dans le code. Ce que l'expression calcule est, étant donné une somme souhaitée set un premier terme pour une séquence arithmétique a, la longueur de la séquence. Ces longueurs sont stockées dans un dictionnaire sous forme de valeurs pour les premiers termes sous forme de clés.

Ensuite, toutes les valeurs non entières sont supprimées du dictionnaire, car celles-ci représentent des séquences non valides. De là, la plus grande valeur est identifiée avec max(d.keys(), key=(lambda k: d[k]))et la séquence de nombres impairs à cette position et à cette longueur est faite avec list(range(int(m),int(m+2*d[m]),2)).


Je cherche de l'aide pour jouer au golf si vous voyez quelque chose. J'étais plus intéressé à voir dans quelle mesure je pouvais faire avec un algorithme non trivial; ma réponse est presque deux fois plus longue que la meilleure solution Python.


Est-ce que cela fonctionnerait? repl.it/JTt7 (177 octets)
Zacharý

0

Mathematica, 56 octets

Last@Cases[Subsequences@Table[n,{n,1,#,2}],x_/;Tr@x==#]&

Functionavec le premier argument #. Table[n,{n,1,#,2}]calcule la liste des nombres impairs positifs inférieurs ou égaux à #. Subsequencesrenvoie toutes les sous-séquences de cette liste triées par longueur croissante. Nous prenons ensuite les séquences Casesqui correspondent x_/;Tr@x==#, c'est-à-dire xtelles que leur somme Tr@xest égale à l'entrée #. Nous prenons ensuite Lastcette séquence.


0

JavaScript (ES6), 72 octets

n=>(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?l+' '+g(s,l+=2):u)(n-1,l=u=1)

Renvoie une chaîne séparée par des espaces de nombres impairs ou renvoie une entrée non valide. Version de 84 octets qui renvoie un tableau (vide le cas échéant):

n=>n%4-2?(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?[l,...g(s,l+=2)]:[u])(n-1,l=u=1):[]

Explication: Librement basé sur la solution awk de @ Cabbie407 à Sums of Integers consécutifs, sauf que j'ai pu enregistrer certains octets en utilisant la récursivité.


0

PHP, 78 octets

for($b=-1;$s-$argn;)for($n=[$s=$x=$b+=2];$s<$argn;)$s+=$n[]=$x+=2;print_r($n);

boucle infinie si aucune solution. insérez ?$b>$argn+2?$n=[]:1:0après $s-$argnpour imprimer un tableau vide à la place.

Courez avec -nRou essayez-le en ligne .


0

C # (.NET Core) , 129 octets

(i)=>{int s,j,b=1,e=3;for(;;){var o="";s=0;for(j=b;j<e;j+=2){s+=j;o+=j+" ";}if(s==i)return o;s=s<i?e+=2:b+=2;if(b==e)return"";}};

Affiche les nombres dans une chaîne, séparés par des espaces (tout autre caractère nécessiterait simplement de changer le " "). L'entrée sans solution renvoie une chaîne vide (bien que si elle s'exécute indéfiniment sans erreur soit un moyen valide d'indiquer aucune solution, 17 octets peuvent être enregistrés en les supprimant if(b==e)return"";).

L'algorithme est:

  1. Commencez par [1]
  2. Si la somme est égale à la cible, renvoyez la liste
  3. Si la somme est inférieure à la cible, ajoutez le prochain nombre impair
  4. Si la somme est supérieure à la cible, supprimez le premier élément
  5. Si la liste est vide, renvoyez-la
  6. Répéter à partir de 2

Vous pouvez écrire (i)=>commei=>
aloisdg dit Reinstate Monica

0

C ++, 157 -> 147 octets


-10 octets grâce à DJMcMayhem

renverra 0 s'il n'y a pas de réponse, 1 sinon

la dernière ligne imprimée est la réponse

int f(int n){for(int i=1;;i+=2){int v=0;for(int k=i;;k+=2){v+=k;std::cout<<k<<" ";if(v==n)return 1;if(v>n)break;}if(i>n)return 0;std::cout<<"\n";}}

non golfé:

int f(int n)
{
    for (int i = 1;; i += 2)
    {
        int v = 0;
        for (int k = i;; k += 2)
        {
            v += k;
            std::cout << k << " ";
            if (v == n)
                return 1;
            if (v > n)
                break;

        }
        if (i > n)
            return 0;
        std::cout << "\n";
    }
}

c'est mon premier code golf ^^


Vous pouvez enregistrer quelques octets si vous en faites une fonction int et renvoyez 0 ou 1. En outre, vous pouvez le faire à la int v=0;place de int v;....v=0;et si vous avez délimité votre sortie Newline, vous pouvez le faire std::cout<<k<<"\n";, puis supprimer complètement le deuxième Newline
DJMcMayhem

si je faisais la dernière recommandation, il imprimerait une nouvelle ligne sur chaque numéro mais je veux séparer les groupes de numéros, mais merci quand même pour -10 octets
SeeSoftware

0

Kotlin, 152 octets

fun f(a:Double){var n=Math.sqrt(a).toInt()+1;var x=0;while(n-->0){if(((a/n)-n)%2==0.0){x=((a/n)-n).toInt()+1;while(n-->0){println(x.toString());x+=2}}}}

Essayez-le en ligne (attendez 4-5 secondes, le compilateur est lent)

Non golfé

fun f(a: Double){
    var n=Math.sqrt(a).toInt()+1;
    var x=0;

    while(n-->0){
        if(((a/n)-n)%2==0.0){
            x=((a/n)-n).toInt()+1;

            while(n-->0){
                println(x.toString());
                x+=2;
            }

        }
    }
}

0

Excel VBA, 139 octets

Subroutine qui prend l'entrée ndu type entier attendu et signale la plus longue séquence de nombres impairs consécutifs à la cellule[A1]

Sub a(n)
For i=1To n Step 2
s=0
For j=i To n Step 2
s=s+j
If s=n Then:For k=i To j-1 Step 2:r=r &k &"+":Next:[A1]=r &j:End
Next j,i
End Sub
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.