Soma de Inteiros Consecutivos


27

Antes que alguém diga alguma coisa, semelhante e semelhante . Mas isso não é uma bobagem.


Alguns números inteiros positivos podem ser escritos como a soma de pelo menos dois números inteiros positivos consecutivos. Por exemplo 9=2+3+4=4+5,. Escreva uma função que use um número inteiro positivo como entrada e imprima como saída a sequência mais longa de números inteiros positivos consecutivos crescentes que somarem a ela (qualquer formato é aceitável, embora -5 bytes se a saída for a sequência crescente separada por, +como mostrado acima Se não existir essa sequência, o próprio número deverá ser impresso.

Isso é código de golfe. Aplicam-se regras padrão. O menor código em bytes vence.


Amostras (observe que a formatação varia)

Input:   9
Output:  2,3,4

Input:   8
Output:  8

Input:   25
Output:  [3,4,5,6,7]

2
Os números emitidos precisam estar em uma ordem específica (como aumentar)?
Xnor

2
Os números devem ser> 0: 6 = 0 + 1 + 2 + 3 ou 6 = 1 + 2 + 3
Damien

5
Como uma observação lateral, se houver desafios intimamente relacionados, dizer "isso não é um tolo" pouco ajudará a convencer as pessoas disso se eles acharem que é um tolo. Seria mais útil se você explicasse por que acha que não é.
Martin Ender

1
@ Damien "positivo" normalmente significa> 0. Se 0 fosse incluído, seria chamado de "não negativo".
Martin Ender

3
cc @Vixen ^ (também se números negativos fossem permitidos, a solução ideal seria sempre o intervalo de -n+1até n) #
4500 Martin Ender

Respostas:


11

Python, 67 bytes

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

Uma estratégia estranhamente direta: procure o intervalo R com a soma certa.

  • Se a soma for muito pequena, mude o ponto final direito do intervalo para cima um acrescentando o próximo número mais alto.
  • Se a soma for muito grande, mova o ponto final esquerdo removendo o menor elemento
  • Se a soma estiver correta, faça a saída R.

Como a extremidade inferior do intervalo apenas aumenta, intervalos maiores são encontrados antes dos menores.


Estranhamente eficiente também. A pilha de recursão acaba transbordando, por exemplo, n = 8192.
Primo

7

Pitão, 12 10 bytes

j\+hfqsTQ}M^SQ2

O código tem 15 bytes e se qualifica para o bônus de -5 bytes . Experimente online no Pyth Compiler .

Graças a @Jakube por jogar fora 2 bytes!

Como funciona

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.

1
Para aqueles de nós não esclarecidos na área de Pyth, você poderia adicionar uma explicação, por favor? :)
ETHproductions

Eu editei minha resposta.
Dennis

Incrível, obrigado! Eu gosto da sua técnica.
ETHproductions

1
Entrada 1000: 30 minutos e contando ...
primo

3

Mathematica, 73 68 65 56 43 bytes

Cases[Range~Array~{#,#},i_/;Tr@i==#,{2},1]&

1
+1 Acabei com uma solução semelhante ontem à noite, mas minha internet caiu. Você também pode criar Tuplesuma expressão infix.
usar o seguinte

3

Haskell, 49 48 bytes

f n=[[a..b]|a<-[1..n],b<-[a..n],sum[a..b]==n]!!0

1
1 byte para salvar: use em [...]!!0vez de head[...].
nimi

2

MATLAB, 87 79 bytes

Eu sei que já existe uma resposta do MATLAB, mas essa é uma abordagem significativamente diferente.

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)

Isso também funciona no Octave . Você pode tentar online aqui . Eu já adicionei o código consecutiveSum.mno espaço de trabalho vinculado; portanto, basta digitar consecutiveSumno prompt de comando e inserir o valor (por exemplo, 25).

Ainda estou trabalhando para reduzi-lo (talvez ajustando a equação usada um pouco), mas basicamente ele encontra o maior valor npara o qual mé um número inteiro e exibe os primeiros mnúmeros começando com n.

Então, por que isso funciona? Bem, basicamente existe uma equação matemática que governa todos esses números. Se você considera que todos são consecutivos e começa a partir de algum ponto, você pode basicamente dizer:

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

Agora, a partir disso, torna-se aparente que a sequência é basicamente apenas o primeiro pnúmero do triângulo (incluindo o 0'th), adicionado a p+1muitos n. Agora, se deixarmos m=p+1, podemos dizer:

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

Isso é realmente bastante solucionável. Ainda estou procurando a maneira mais curta de fazer isso, tenho algumas idéias para tentar reduzir o código acima.


Para uma entrada de 25, a saída seria:

3     4     5     6     7

2
No que diz respeito ao seu ponto de vista sobre os números dos triângulos, esse desafio está essencialmente tentando encontrar números triangulares com uma diferença positiva da entrada, de modo que os índices dos números triangulares na sequência 1,3,6,10,...sejam maximizados.
quer

1

Python 2, 94 bytes

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

A entrada é retirada do stdin. Esta solução é adequada para entradas muito grandes.

Isso itera sobre os possíveis comprimentos da solução, r , com r ≤ √ (2n) , e verifica explicitamente a solução. Para que uma solução exista, se r for ímpar, n mod r deve ser zero e se r for par, n mod r deve ser r / 2 .


Uso da amostra

$ 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]

Escolhi deliberadamente exemplos com resultados relativamente pequenos.


1

Oitava, 89 bytes

Este é o melhor que eu poderia fazer na oitava. O algoritmo é o mesmo que o 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)

No MATLAB, isso seria 95 bytes:

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)

No MATLAB, isso é executado em aproximadamente 0,1 segundos para entrada 2000000e 1 segundo para entrada 1000002.


1

awk, 51 bytes

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

O código é 56 bytes, menos 5 bytes para o formato de saída. Eu tive que usar 4 bytes extras para produzir esse formato, então eu realmente salvei 1 byte. Viva! ;)

Na verdade, está fazendo o trabalho duro de resumir, começando de 1 até que a soma seja maior que a entrada. Em seguida, começa a subtrair números começando de 1 até que o número seja menor que a entrada. Ele continua alterando o número inicial e final dessa maneira até encontrar um resultado, que é impresso.

Exemplo de uso

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

Saída do exemplo

48 + 49 + 50 + 51 + 52 + 53

Eu tentei isso para uma entrada de 1e12e deu o resultado correto ( 464562+...+1488562) quase imediatamente. Embora demorou um pouco para imprimi-lo, é claro ...


Adoro a abordagem Awk. Estou com problemas para determinar a ordem de precedência nas ligações. Você se importaria em incluir uma versão com mais parênteses para torná-la um pouco mais óbvia? :)
Curinga

1
Espero que ajude: {while($0!=s)s+=(s<$0) ? (++j) : -(++i); while(++i<j)r=r i"+"}$0=r j i é sempre o último número inteiro que foi subtraído do início da cadeia, j é sempre o último número inteiro adicionado no final da cadeia
Cabbie407

0

Japonês , 33 bytes

Isso usa a técnica Pyth de Dennis , embora seja consideravelmente mais longa ...

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

Experimente online! Atenção: para entradas maiores (<= 20), leva um tempo para terminar e congela o navegador até que isso aconteça.

Ungolfed e explicação

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

Versão ganha-bônus: (38 bytes - 5 = 33)

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

0

Julia, 92 bytes

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

Esta é uma função anônima que aceita um número inteiro e retorna uma matriz. Para chamá-lo, dê um nome, por exemplof=x->... .

Ungolfed:

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

0

Ruby, 94 bytes

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

Ungolfed:

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

Uso:

->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]

0

Sério, 53 - 5 = 48 bytes

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

Hex Dump

2c3b3b3bbc603b75406ec728443b29606e2858586b60697540754
0783be4be3d5b5d29496960bb60a4bd4d604d3bb0704058272b6a

Experimente Online!

É a abordagem da força bruta, semelhante ao Pyth de Dennis.

Tudo até o kmomento lê a entrada nno registro 1 e cria a lista [[1],[2,2],[3,3,3],[4,4,4,4],...]até n n's.

A próxima parte é uma função armazenada no registro 0 que leva um par, incrementa os dois elementos, os converte em um intervalo, localiza a soma do intervalo e verifica se essa soma é o valor no registro 1. Se for, retorna o intervalo correspondente e, se não estiver, retorna uma lista vazia.

A parte até a última ocorrência de Mmapeia uma função sobre a sofisticada lista de listas descrita acima, executando enumerateem cada lista e, em seguida, mapeando a função armazenada sobre ela. Quando estiver pronto, temos uma lista de listas, cada uma delas vazia ou um intervalo ao qual soma n.

;░remove as listas vazias. p@Xpega a primeira lista que permanece ( 0@Etambém funcionaria). '+jcoloca +entre cada número à medida que converte a lista em uma sequência de caracteres para o bônus.


0

ES6, 72 bytes

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

Porta direta da solução awk do @ Cabbie407, mas sem o bônus de formatação, pois é uma penalidade aqui.


0

Python 3, 239 236 215 203 bytes

Isso é um pouco complicado. Vou ter que jogar mais tarde.

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]

Isso kocorre porque, se você verificar t[0]um vazio t, o Python faz barulhos rudes com você. Novamente, isso precisa de golfe. Graças a t[:1], não há mais rudes rudes! Você só precisa verificar contra outra matriz.


0

Gelatina , 8 bytes (não concorrente)

ẆS⁼¥Ðf⁸Ṫ

Experimente online!

Se eu entendi corretamente, isso pode ser uma versão de (11-5 = 6) bytes:

ẆS⁼¥Ðf⁸Ṫj”+

Por uma questão de interesse, existem 12 soluções semelhantes (incluindo esta) trocando os iguais não-vetorizáveis ​​pelos iguais, vetorizando, alterando o argumento esquerdo para primeiro argumento ou identidade e trocando iguais por não-iguais e filtro por filtro para vetorização e não-vetorização. : O
HyperNeutrino

Digamos que eu postei o que faz mais sentido, mas com otimização de velocidade.
Erik the Outgolfer

0

05AB1E , 11 - 5 = 6 bytes (não concorrente)

Tomando esse bônus, é claro :)

LŒʒOQ}é¤'+ý

Experimente online!

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

0

PHP, 70 bytes

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

Execute como pipe -nRou experimente online .

incrementos paté encontrar uma solução para o número inteiro argument==(p+q)*(q-p+1)/2,
em seguida, imprime o intervalo entre pa q.


0

Excel VBA, 119 - 5 = 114 bytes

Subrotina que recebe a entrada ndo tipo inteiro esperado e gera a sequência mais longa de números consecutivos que somam à célula[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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.