Somme d'entiers consécutifs

27

Avant que quelqu'un ne dise quoi que ce soit, similaire et similaire . Mais ce n'est pas dupe.


Certains entiers positifs peuvent être écrits comme la somme d'au moins deux entiers positifs consécutifs. Par exemple 9=2+3+4=4+5,. Écrire une fonction qui prend un entier positif comme entrée et imprime comme sortie la plus longue séquence d'entiers positifs consécutifs croissants qui la résume (tout format est acceptable, bien que -5 octets si la sortie est la séquence croissante séparée par +comme indiqué ci-dessus) S'il n'existe aucune séquence de ce type, le numéro lui-même doit être imprimé.

C'est le golf de code. Des règles standard s'appliquent. Le code le plus court en octets gagne.


Échantillons (notez que le formatage varie)

Input:   9
Output:  2,3,4

Input:   8
Output:  8

Input:   25
Output:  [3,4,5,6,7]
Arcturus
la source
2
Les nombres sortis doivent-ils être dans un ordre spécifique (comme augmenter)?
2015
2
Les nombres doivent-ils être> 0: 6 = 0 + 1 + 2 + 3 ou 6 = 1 + 2 + 3
Damien
5
En passant, s'il y a des défis étroitement liés, dire "ce n'est pas un dupe" ne fera pas grand-chose pour convaincre les gens s'ils pensent que c'est un dupe. Il serait plus utile d'expliquer pourquoi vous pensez que ce n'est pas le cas.
Martin Ender
1
@Damien "positif" signifie normalement> 0. Si 0 était inclus, il serait appelé "non négatif".
Martin Ender
3
cc @Vixen ^ (même si des nombres négatifs étaient autorisés, la solution optimale serait toujours la plage de -n+1à n)
Martin Ender

Réponses:

11

Python, 67 octets

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

Une stratégie étrangement simple: recherchez l'intervalle R avec la bonne somme.

  • Si la somme est trop petite, déplacez le point d'extrémité droit de l'intervalle vers le haut d'un en ajoutant le nombre le plus élevé suivant.
  • Si la somme est trop grande, déplacez le point d'extrémité gauche vers le haut en supprimant le plus petit élément
  • Si la somme est correcte, sortez R.

Étant donné que l'extrémité inférieure de l'intervalle ne fait qu'augmenter, des intervalles plus longs sont trouvés avant des intervalles plus courts.

xnor
la source
Étrangement efficace aussi. La pile de récursivité finit par déborder, par exemple n = 8192.
primo
7

Pyth, 12 10 octets

j\+hfqsTQ}M^SQ2

Le code est long de 15 octets et se qualifie pour le bonus de -5 octets . Essayez-le en ligne dans le compilateur Pyth .

Merci à @Jakube d'avoir joué au golf sur 2 octets!

Comment ça marche

j\+hfqsTQ}M^SQ2    (implicit) Store evaluated input in Q.

            S      Compute [1, ..., Q].
           ^  2    Get all pairs of elements of [1, ..., Q].
         }M        Reduce each pair by inclusive range. Maps [a, b] to [a, ..., b].
    f              Filter; for each pair T:
      sT             Add the integers in T.
     q  Q            Check if the sum equals Q.
                   Keep the pair if it does.
   h               Retrieve the first match.
                   Since the ranges [a, ..., b] are sorted by the value of a,
                   the first will be the longest, in ascending order.
j\+                Join, using '+' as separator.
Dennis
la source
1
Pour ceux d'entre nous qui ne sont pas éclairés dans le domaine de Pyth, pourriez-vous ajouter une explication s'il vous plaît? :)
ETHproductions
J'ai édité ma réponse.
Dennis
Super merci! J'aime ta technique.
ETHproductions
1
Entrée 1000: 30 minutes et comptage ...
primo
3

Mathematica, 73 68 65 56 43 octets

Cases[Range~Array~{#,#},i_/;Tr@i==#,{2},1]&
alephalpha
la source
1
+1 Je me suis retrouvé avec une solution similaire hier soir, mais mon Internet est tombé en panne. Vous pouvez également créer Tuplesune expression d'infixe.
LegionMammal978
3

Haskell, 49 48 octets

f n=[[a..b]|a<-[1..n],b<-[a..n],sum[a..b]==n]!!0
Damien
la source
1
1 octet à enregistrer: utilisez [...]!!0au lieu de head[...].
nimi
2

MATLAB, 87 79 octets

Je sais qu'il existe déjà une réponse MATLAB, mais celle-ci est sensiblement différente dans son approche.

x=input('');m=1:x;n=.5-m/2+x./m;l=max(find(~mod(n(n>0),1)));disp(m(1:l)+n(l)-1)

Cela fonctionne également sur Octave . Vous pouvez essayer en ligne ici . J'ai déjà ajouté le code consecutiveSum.mdans l'espace de travail lié, alors entrez simplement consecutiveSumà l'invite de commande, puis entrez la valeur (par exemple 25).

Je travaille toujours à le réduire (peut-être en ajustant un peu l'équation utilisée), mais en gros, il trouve la plus grande valeur npour laquelle mest un entier, puis affiche les premiers mnombres commençant par n.

Alors pourquoi ça marche? Eh bien, fondamentalement, il existe une équation mathématique régissant tous ces nombres. Si vous considérez qu'ils sont tous consécutifs et que vous partez d'un certain point, vous pouvez essentiellement dire:

n+(n+1)+(n+2)+(n+3)+...+(n+p)=x

Maintenant, à partir de cela, il devient évident que la séquence n'est fondamentalement que les premiers pnombres triangulaires (y compris le 0e), ajoutés à p+1beaucoup de n. Maintenant, si nous le laissons m=p+1, nous pouvons dire:

m*(n+(m-1)/2)==x

C'est en fait assez résoluble. Je suis toujours à la recherche de la manière la plus courte de le faire, j'ai quelques idées pour essayer de réduire le code ci-dessus.


Pour une entrée de 25, la sortie serait:

3     4     5     6     7
Tom Carpenter
la source
2
En ce qui concerne votre point sur les nombres triangulaires, ce défi essaie essentiellement de trouver des nombres triangulaires avec une différence positive de l'entrée de sorte que les indices des nombres triangulaires dans la séquence 1,3,6,10,...soient maximisés.
Arcturus
1

Python 2, 94 octets

n=input()
r=int((2*n)**.5)
while r:
 if~r%2*r/2==n%r:print range(n/r-~-r/2,n/r-~r/2);r=1
 r-=1

L'entrée provient de stdin. Cette solution convient aux très grandes entrées.

Cela itère sur les longueurs de solution possibles, r , ayant r ≤ √ (2n) , et vérifie explicitement une solution. Pour qu'une solution existe, si r est impair, n mod r doit être nul, et si r est pair, n mod r doit être r / 2 .


Exemple d'utilisation

$ echo 8192 | python sum-con-int.py
[8192]

$ echo 1000002 | python sum-con-int.py
[83328, 83329, 83330, 83331, 83332, 83333, 83334, 83335, 83336, 83337, 83338, 83339]

$ echo 1000000006 | python sum-con-int.py
[250000000, 250000001, 250000002, 250000003]

J'ai délibérément choisi des exemples avec des sorties relativement petites.

primo
la source
1

Octave, 89 octets

C'est le meilleur que j'ai pu faire à Octave. L'algorithme est le même que celui de xnor.

x=input('');k=i=1;while x;s=sum(k:i);if s<x;i++;elseif s>x;k++;else;x=0;end;end;disp(k:1)

Dans MATLAB, ce serait 95 octets:

x=input('');k=1;i=1;while x;s=sum(k:i);if s<x;i=i+1;elseif s>x;k=k+1;else x=0;end;end;disp(k:i)

Dans MATLAB, cela fonctionne en environ 0,1 seconde pour l'entrée 2000000et 1 seconde pour l'entrée 1000002.

Stewie Griffin
la source
1

awk, 51 octets

{while($0!=s+=s<$0?++j:-++i);while(++i-j)r=r i"+"}$0=r j

Le code est de 56 octets, moins 5 octets pour le format de sortie. J'ai dû utiliser 4 octets supplémentaires pour produire ce format, j'ai donc effectivement enregistré 1 octet. Hourra! ;)

Il fait en fait le travail difficile de résumer à partir de 1 jusqu'à ce que la somme soit plus grande que l'entrée. Ensuite, il commence à soustraire des nombres à partir de 1 jusqu'à ce que le nombre soit plus petit que l'entrée. Il continue de changer le numéro de début et de fin de cette façon jusqu'à ce qu'il trouve un résultat, qu'il imprime ensuite.

Exemple d'utilisation

echo 303 | awk '{while($0!=s+=s<$0?++j:-++i);while(++i-j)r=r i"+"}$0=r j'

Sortie d'exemple

48 + 49 + 50 + 51 + 52 + 53

J'ai essayé ceci pour une entrée de 1e12et cela a donné le résultat correct ( 464562+...+1488562) presque immédiatement. Bien qu'il ait fallu un certain temps pour l'imprimer bien sûr ...

Cabbie407
la source
J'adore l'approche Awk. J'ai du mal à déterminer l'ordre de priorité dans les liaisons. Pourriez-vous s'il vous plaît inclure une version avec plus de parenthèses ajoutées pour la rendre un peu plus évidente? :)
Wildcard
1
J'espère que cela aide: {while($0!=s)s+=(s<$0) ? (++j) : -(++i); while(++i<j)r=r i"+"}$0=r j i est toujours le dernier entier qui a été soustrait depuis le début de la chaîne, j est toujours le dernier entier ajouté à la fin de la chaîne
Cabbie407
0

Japt , 33 octets

Cela utilise la technique Pyth de Dennis , bien qu'elle soit considérablement plus longue ...

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU

Essayez-le en ligne! Avertissement: pour les entrées plus grandes (<= 20), il faut un certain temps pour terminer et gèle votre navigateur jusqu'à ce qu'il le fasse.

Non golfé et explication

1oU à2 £    W=Xg o1+Xg1¹ x ¥ U© W} rª  ª U
1oU à2 mXYZ{W=Xg o1+Xg1) x ==U&&W} r|| ||U

          // Implicit: U = input integer
1oU à2    // Generate a range from 1 to U, and take all combinations of length 2.
mXYZ{     // Map each item X in this range to:
W=Xg o    //  Set variable W to the range of integers starting at the first item in X,
1+Xg1)    //  and ending at 1 + the second item in X.
x ==U&&W  //  If the sum of this range equals U, return W; otherwise, return false.
r||       // Reduce the result with the || operator, returning the first non-false value.
||U       // If this is still false, there are no consecutive ranges that sum to U,
          // so resort to U itself.
          // Implicit: output last expression

Version bonus: (38 octets - 5 = 33)

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU² q'+
ETHproductions
la source
0

Julia, 92 octets

x->(t=filter(i->all(j->j==1,diff(sort(i))),partitions(x));collect(t)[indmax(map(length,t))])

Il s'agit d'une fonction anonyme qui accepte un entier et renvoie un tableau. Pour l'appeler, donnez-lui un nom, par exemple f=x->....

Non golfé:

function f(x::Integer)
    # Get all arrays of integers that sum to x
    p = partitions(x)

    # Filter these down to only consecutive runs by checking whether
    # all differences are 1
    t = filter(i -> all(j -> j == 1, diff(sort(i))), p)

    # Find the index of the longest element of t
    i = indmax(map(length, t))

    return collect(t)[i]
end
Alex A.
la source
0

Rubis, 94 octets

->n{([*1..n].permutation(2).map{|i,j|[*i..j]if(i..j).reduce(:+)==n}-[p]).max_by{|k|k.size}||n}

Non golfé:

-> n {
  ([*1..n].permutation(2).map { |i,j|   # Finds all the possible sets of size 2
     [*i..j] if(i..j).reduce(:+) == n   # Adds a set to an array if sum of the set is n.
   }-[p]                                # Removes nil from the array
  ).max_by { |k|                        # Finds the longest sequence
    k.size
  } || n                                # Returns n if no sequence found.
}

Usage:

->n{([*1..n].permutation(2).map{|i,j|[*i..j]if(i..j).reduce(:+)==n}-[p]).max_by{|k|k.size}||n}[25]
=> [3, 4, 5, 6, 7]
Vasu Adari
la source
0

Sérieusement, 53 - 5 = 48 octets

,;;;╝`;u@n╟(D;)`n(XXk`iu@u@x;Σ╛=[])Ii`╗`ñ╜M`M;░p@X'+j

Vidage hexadécimal

2c3b3b3bbc603b75406ec728443b29606e2858586b60697540754
0783be4be3d5b5d29496960bb60a4bd4d604d3bb0704058272b6a

Essayez-le en ligne!

C'est l'approche de la force brute, similaire au Pyth de Dennis.

Tout jusqu'à l' kentrée lit simplement ndans le registre 1, puis crée la liste [[1],[2,2],[3,3,3],[4,4,4,4],...]jusqu'à n n.

Le bit suivant est une fonction stockée dans le registre 0 qui prend une paire, incrémente les deux éléments, les convertit en une plage, recherche la somme de la plage et vérifie si cette somme est la valeur du registre 1. Si c'est le cas, il renvoie la plage correspondante, et si ce n'est pas le cas, il renvoie une liste vide.

La partie jusqu'à la dernière occurrence de Mmappe une fonction sur la liste de fantaisie des listes décrites ci-dessus, en faisant enumeratesur chaque liste, puis en mappant la fonction stockée sur elle. Quand c'est fait, nous avons une liste de listes dont chacune est vide ou une plage qui résume àn .

;░supprime les listes vides. p@Xprend la première liste qui reste ( 0@Efonctionnerait également). '+jplace +entre chaque nombre car il convertit la liste en une chaîne pour le bonus.

quintopie
la source
0

ES6, 72 octets

n=>{for(l=u=1;n;)n>0?n-=u++:n+=l++;return[...Array(u).keys()].slice(l);}

Port droit de la solution awk de @ Cabbie407, mais sans le bonus de formatage, car c'est une pénalité ici.

Neil
la source
0

Python 3, 239 236 215 203 octets

C'est un peu lourd. Je vais devoir jouer au golf plus tard.

def x(n):
 r=[n]
 for i in range(2,n):
  t=[]
  if i%2*(n%i<1):t=[j+n//i-i//2for j in range(i)]
  elif i%2<1and n%i==i//2:t=[j+n//i-i//2+1for j in range(i)]
  if t[:1]>[0]*(sum(t)==n):r+=t,
 return r[-1]

C'est kparce que si vous vérifiez t[0]sur un vide t, Python vous fait des bruits grossiers. Encore une fois, cela a besoin de jouer au golf. Merci à t[:1], plus de bruits grossiers! Il vous suffit de vérifier par rapport à un autre tableau.

Sherlock9
la source
0

Gelée , 8 octets (non concurrent)

ẆS⁼¥Ðf⁸Ṫ

Essayez-le en ligne!

Si je comprends bien, cela pourrait être une version (11-5 = 6) octets:

ẆS⁼¥Ðf⁸Ṫj”+
Erik le Outgolfer
la source
Par souci d'intérêt, il existe 12 solutions similaires (y compris celle-ci) en échangeant les égaux non vectorisables pour les égaux vectorisateurs, en changeant l'argument de gauche en premier argument ou en identité, et en échangeant les égaux avec des non égaux et en filtrant pour filtrage pour vectorisation et non vectorisation. : O
HyperNeutrino
Disons que j'ai publié celui qui a le plus de sens, mais avec une optimisation de la vitesse.
Erik the Outgolfer
0

05AB1E , 11 - 5 = 6 octets (non concurrent)

Prendre ce bonus bien sûr :)

LŒʒOQ}é¤'+ý

Essayez-le en ligne!

LŒʒOQ}é¤'+ý  Argument: n
LŒ           Sublists of range 1 to n
  ʒOQ}       Filter by total sum equals n
      é¤     Get longest element
        '+ý  Join on '+'
kalsowerus
la source
0

PHP, 70 octets

while(fmod($q=sqrt(2*$argn+(++$p-.5)**2)-.5,1));print_r(range($p,$q));

Exécuter en tant que pipe avec -nRou l' essayer en ligne .

incrémente pjusqu'à ce qu'il trouve une solution entière pour argument==(p+q)*(q-p+1)/2,
puis imprime la plage de pà q.

Titus
la source
0

Excel VBA, 119 - 5 = 114 octets

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

Sub a(n)
For i=1To n
s=0
For j=i To n
s=s+j
If s=n Then:For k=i To j-1:r=r &k &"+":Next:[A1]=r &j:End
Next
Next
End Sub
Taylor Scott
la source