A soma dos números ímpares consecutivos


24

Embora tenham sido feitos desafios relacionados , este é diferente para justificar sua própria pergunta.


Desafio

Dado um número inteiro positivo, retorne a sequência mais longa de números inteiros positivos consecutivos cuja soma é o número inteiro fornecido. Se essa sequência não existir, você poderá relatar um erro da maneira que for mais apropriada para o seu idioma, inclusive retornando um valor falso ou lançando uma exceção.

Casos de teste

  1 -> [1]
  2 -> []
  3 -> [3]
  4 -> [1, 3]
  5 -> [5]
  6 -> []
  9 -> [1, 3, 5] (observe que [9] não é uma resposta válida)
 15 -> [3, 5, 7]
104 -> [23, 25, 27, 29] (observe que [51, 53] não é uma resposta válida)

Pontuação

Isso é , então a resposta mais curta em cada idioma vence.


2
Meu programa pode ser executado para sempre se não houver solução?
Dennis

Muito relacionado . O fato de que alguns números pares não possam ser representados neste número pode evitar que seja um engodo.
ETHproductions

6
15 não pode dar [-1, 1, 3, 5, 7]? Se apenas valores positivos forem permitidos, você deve dizer isso.
Xnor

2
@ ЕвгенийНовиков você pulou 17
kalsowerus 07/07

11
@kalsowerus yes. Eu entendi errado a palavra "consecutivo"
Евгений Новиков

Respostas:


11

Haskell, 67 65 63 62 58 bytes

Guardado 4 bytes graças a Julian Wolf

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

Experimente online!

I verificar se o número pode ser expresso como ele diferença de dois quadrados: m^2-n^2. Posso, então, construir a lista de números ímpares consecutivos: [2n+1,2n+3...2m-1]. Observe que, como o mínimo né escolhido, a lista mais longa será exibida


7
Eleitor que recusou: Seria mais amigável e mais construtivo adicionar um comentário com o seu motivo, especialmente ao votar com um novo usuário.
Jonathan Allan

11
A menos que eu esteja perdendo alguma coisa, você pode salvar 4 bytes, subindo apenas xpara os dois nem
Julian Wolf

Para que você saiba, o voto negativo foi convertido automaticamente pelo usuário da Comunidade quando você editou sua resposta. Eu considero isso um bug . (CC @JonathanAllan)
Dennis

Ahh, foi um desses.
Jonathan Allan

9

Python 2 , 66 62 bytes

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

Sai com um RuntimeError (profundidade máxima de recursão excedida) se não houver solução.

Experimente online!


11
Se os valores de entrada forem altos o suficiente, mas houver uma solução, isso resultará em um RuntimeError ?
Okx 07/07

Se o limite de recursão não for alto o suficiente e / ou a pilha não for grande o suficiente, sim. No entanto, é comum ignorar limitações físicas (por exemplo, uma resposta C precisa funcionar apenas para ints de 32 bits), e o OP disse explicitamente que rodar para sempre é aceitável se não houver solução.
Dennis

9

Geléia ,  11  10 bytes

-1 byte graças a Dennis (use o intervalo implícito de - substitua Rm2Ẇpor ẆḤ’)

ẆḤ’S_¥Ðḟ⁸Ṫ

Um link monádico retornando uma lista dos summands, se possível, ou 0não.

Experimente online!

Quão?

ẆḤ’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)

11
ẆḤ’salva um byte.
Dennis

8

JavaScript (ES7), 87 86 85 81 bytes

Retorna uma lista delimitada por vírgulas de números inteiros ou 0se não houver solução.

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)

Quão?

Primeiro, procuramos o menor quadrado perfeito s de modo que x = n + s seja outro quadrado perfeito.

Se s existir, n é a diferença x - s de 2 quadrados perfeitos, que pode ser escrita como a diferença de 2 seqüências de números ímpares consecutivos. Em seguida, criamos a lista resultante.

Exemplo:

Para n = 104 :

Encontramos s = 11² = 121 que satisfaz x = n + s = 225 = 15²

Então:

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
Espere, você está me dizendo que n^2sempre é igual à soma dos primeiros nnúmeros ímpares?
Ah

2
@Mayube Indeed !
Arnauld 07/07


7

05AB1E , 9 8 bytes

-1 byte graças a Emigna

ÅÉŒʒOQ}н

Explicação:

ÅÉ           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

Na entrada inválida, não gera nada.

Experimente online!


ʒOQ}em vez de DO¹QÏsalvar um byte.
Emigna

@JonathanAllan Docs dizer "irregular" de modo que poderia ter sido confundido ...
Erik o Outgolfer

11
@JonathanAllan Small error. Fixo.
Okx 07/07

6

Haskell , 61 60 bytes

Graças a @maple_shaft por cortar 1 byte

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

Experimente online!

Usa o fato de que a execução mais longa será sempre a que começa com o número mais baixo.

Eu queria fazer algo com aritmética em vez de força bruta k, mas fromIntegerparece matá-lo.


Você pode salvar um byte mudando [1,3..n]para[1,3..]
maple_shaft

11
Você pode salvar 7 bytes com uma função auxiliar r?n=[r,r+2..n]. Experimente online!
Ørjan Johansen

4

Python , 67 bytes

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

Experimente online!

Copiei minha resposta do desafio de soma consecutivo anterior e mudei +1para +2. Quem sabia que o código do golfe poderia ser tão modular?

Uma estratégia estranhamente direta: procure o intervalo Rcom a soma desejada.

  • Se a soma for muito pequena, mude o ponto final direito do intervalo para cima 2, acrescentando o próximo número 2 acima dele.
  • 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. Se nenhum intervalo possível puder ser encontrado, termina com IndexError.


4

JavaScript (ES6), 65 64 bytes

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

Retorna uma matriz se houver uma solução ou 0 para nenhuma solução.

Esta é uma solução altamente ineficiente e eficaz para o problema.

Ele procura a primeira solução usando a-ie i=1, mesmo que não funcione na pilha recursiva. Se essa solução não começar i+2, procuraremos recursivamente a primeira solução usando ae i+2.

Ungolfed

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

Casos de teste:

Para ter uma idéia de como isso é ineficiente, a solução f(104)requer 69.535 chamadas recursivas. A pilha nunca tem mais de 51 níveis de profundidade, portanto não há problema com o estouro da pilha.

A solução f(200)requer 8,6 milhões de chamadas recursivas, com uma pilha de 99 níveis de profundidade. (Sua solução é [11,13,15,17,19,21,23,25,27,29].)

Aqui está uma representação visual do programa em execução:


3

Python 2.7, 109 108 97 bytes

11 bytes abaixo, Graças a Erik, o Outgolfer.

Este é o meu primeiro código de golfe!

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

Como funciona

Eu usei a identidade bem conhecida que 1 + 3 + 5 + ... + (2n - 1) = n²

Veja o caso de 15

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

Em geral, se houver x termos a partir de 2n + 1, como

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


É igual a 2nx + x²

Se Nfor o número inteiro de entrada, o problema reduz para encontrar o máximo, de xmodo que

x² + 2nx - N = 0

É uma equação quadrática com solução

x = sqrt(n² + N) - n

A sequência mais longa é aquela com a maior x. O programa itera nde 0para Ne, quando descobre que xé um número inteiro, cria uma lista (2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))e a retorna.



@EriktheOutgolfer, Obrigado, esqueci-me de usar guias (=
dark32 7/17

3

Python 3, 190 81 bytes

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

Obrigado a @ovs e @ musicman523


4
Você pode reduzir para 122 bytes apenas removendo algum recuo . Se você quiser diminuir ainda mais o seu código, consulte Dicas para jogar golfe no Python .
ovs 6/07

3
Esta não é executado no Python 3, porque a chamada para printestá faltando parênteses
musicman523

2
Você pode remover l.append(i)usando simplesmente l+[i]a chamada recursiva. Você pode remover l.pop(0)usando l[1:]a chamada recursiva. Você pode remover a chamada para ca parte inferior usando argumentos de palavra-chave. Você pode remover >0na linha 2. Finalmente, você pode alterar suas instruções ife elseem expressões, usando o formato ternário, que reduz a 92 bytes como uma expressão lambda. Experimente online!
musicman523

11
Com base nas sugestões do @ musicman523, ainda podemos reduzir as condições e diminuir ipara chegar a um total de 81 bytes .
ovs 07/07

Eu acho que você poderia mudar sum(l)>q elsepara q<sum(l)elsesalvar 1 byte.
Zacharý

2

QBIC , 47 bytes

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

Isso tenta contar todos os números ímpares de um até sua soma ser n. Se passar n, redefina o loop, aumente 1 para 3 e tente novamente. Saia, imprima 0, se, no início do loop, nosso número > n.

Explicação

{       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 bytes

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

Experimente online!

Usa uma função recursiva que testa a soma acumulada da sequência de y: x convertida em uma sequência numérica ímpar. y é incrementado em cada recursão até exceder x. A primeira sequência que somar ao destino será retornada.


1

Python 2 , 89 bytes

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]

Uma função sem nome que pega um número inteiro positivo n, e retorna o resultado, se existir, e gera um valor IndexErrordiferente.

Experimente online!

Cria uma lista de todos os números ímpares relevantes com os r(1,n+1,2)quais é range(start=1, stop=n+1, step=2); cria todas as sub-fatias relevantes (mais algumas vazias) cortando que de iinclusivo a jexclusivo com [i:j]entre iem [0, n) usando r(n)e jem [0, n] usando r(n+1)(os vazios quando i>=jou iestão fora dos limites); filtros para aqueles com a soma correta com if sum(v)==n; retorna o primeiro (e, portanto, o mais longo) tal fatia usando [0].






0

Python 3 , 93 bytes

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]

Experimente online!

A única coisa especial que fiz foi notar que isso (s+e)*(2+e-s)==4*né equivalente e sum(range(s,e+1,2))==n, embora tenham o mesmo tamanho quando r=range, o primeiro pode ser colocado mais perto da ifafirmação.


0

Python 3 , 185 bytes

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

Experimente online!


Quanto a como isso funciona, tentei buscar uma solução um pouco mais elegante do que uma simples pesquisa de força bruta. Reorganizei a fórmula para a soma de uma sequência aritmética e apliquei a fórmula quadrática para obter a expressão (1-a+((a-1)**2+4*s)**(.5))/2, que aparece no código. O que a expressão calcula é, dada a soma desejada se o primeiro termo da sequência aritméticaa , o comprimento da sequência. Esses comprimentos são armazenados em um dicionário como valores para os primeiros termos como chaves.

Em seguida, todos os valores não inteiros são removidos do dicionário, pois representam sequências inválidas. A partir daí, o maior valor é identificado com max(d.keys(), key=(lambda k: d[k]))e a sequência de números ímpares nessa posição e nesse comprimento é feita com list(range(int(m),int(m+2*d[m]),2)).


Estou procurando ajuda para jogar golfe, se você vir alguma coisa. Eu estava mais interessado em ver o quão bem eu poderia fazer com um algoritmo não trivial; minha resposta é quase o dobro da melhor solução Python.


Isso funcionaria? repl.it/JTt7 (177 bytes)
Zacharý

0

Mathematica, 56 bytes

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

Functioncom o primeiro argumento #. Table[n,{n,1,#,2}]calcula a lista de números ímpares positivos menores ou iguais a #. Subsequencesretorna todas as subsequências dessa lista ordenadas pelo aumento do tamanho. Em seguida, tomamos a Casesque correspondência x_/;Tr@x==#, isto é, sequências de xmodo que sua soma Tr@xseja igual à entrada #. Em seguida, tomamos Lastessa sequência.


0

JavaScript (ES6), 72 bytes

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)

Retorna uma sequência de números ímpares ou lançada em espaço inválido. Versão de 84 bytes que retorna uma matriz (vazia quando apropriada):

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):[]

Explicação: Basicamente baseada na solução awk do @ Cabbie407 para Soma de números consecutivos consecutivos, exceto que eu consegui salvar alguns bytes usando recursão.


0

PHP, 78 bytes

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

loop infinito se não houver solução. inserir?$b>$argn+2?$n=[]:1:0 depois $s-$argnpara imprimir a matriz vazia.

Corra com -nRou experimente online .


0

C # (.NET Core) , 129 bytes

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

Emite números em uma sequência, delimitado por espaço (qualquer outro caractere exigiria apenas a alteração de " "). A entrada sem solução retorna uma sequência vazia (embora se a execução sem erros for uma maneira válida de indicar nenhuma solução, 17 bytes podem ser salvos removendo-seif(b==e)return""; ).

O algoritmo é:

  1. Comece com [1]
  2. Se a soma for igual ao destino, retorne a lista
  3. Se a soma for menor que a meta, adicione o próximo número ímpar
  4. Se a soma for maior que a meta, remova o primeiro item
  5. Se a lista estiver vazia, retorne-a
  6. Repita a partir de 2

Você pode escrever (i)=>comoi=>
aloisdg diz Reinstate Monica

0

C ++, 157 -> 147 bytes


-10 Bytes graças a DJMcMayhem

retornará 0 se não houver resposta, 1 caso contrário

a última linha impressa é a resposta

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

ungolfed:

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

este é o meu primeiro código de golfe ^^


Você poderia salvar alguns bytes se a tornasse uma função int e retornasse 0 ou 1. Além disso, você poderia fazer em int v=0;vez de int v;....v=0;e se você delimitasse a saída Newline, poderia fazer std::cout<<k<<"\n";e remover a segunda linha completamente
DJMcMayhem

o que eu fiz a última recomendação, então seria imprimir uma nova linha em cada número único, mas eu quero grupos de números separados, mas graças qualquer maneira para -10 Bytes
SeeSoftware

0

Kotlin, 152 bytes

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

Experimente online (aguarde 4-5 segundos, o compilador está lento)

Ungolfed

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 bytes

Subrotina que recebe a entrada ndo tipo inteiro esperado e relata a sequência mais longa de números ímpares consecutivos para a célula[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
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.