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.

musicman523
la source
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

H.PWiz
la source
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!

Dennis
la source
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)
Jonathan Allan
la source
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

Arnauld
la source
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!

Okx
la source
ʒ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.

Julian Wolf
la source
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.

xnor
la source
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:

Rick Hitchcock
la source
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.

dark32
la source
@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

Simon
la source
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)
steenbergh
la source
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.

MickyT
la source
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].

Jonathan Allan
la source
1

Python 2 , 91 90 octets

-1 octet grâce à @CMcAvoy

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

Essayez-le en ligne!

ovs
la source
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!

Jörg Hülsermann
la source
ne parvient pas à détecter une entrée insoluble
Titus
@Titus fixed ...
Jörg Hülsermann
0

Python 2 , 122 121 119 119 115 octets

-1 octet grâce à musicman523. -4 octets grâce à Step Hen. haha

def f(n,R=range):r=R(1,n,2);print[i for w in R(1,len(r)+1)for i in[r[j:j+w]for j in R(len(r)-w+1)]if sum(i)==n][-1]

Essayez-le en ligne!

totalement humain
la source
1
C'est un octet plus court en fonction. Essayez-le en ligne!
musicman523
Économisez des octets si vous redéfinissez range, essayez-le en ligne!
Stephen
Cela échoue pour 1 .
Dennis
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.

C McAvoy
la source
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.

Chase Vogeli
la source
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.

ngenisis
la source
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é.

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

Titus
la source
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
Kamil Drakari
la source
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 ^^

SeeSoftware
la source
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;
            }

        }
    }
}
Евгений Новиков
la source
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
Taylor Scott
la source