Somma di numeri interi consecutivi


27

Prima che qualcuno dica qualcosa, simile e simile . Ma questo non è un inganno.


Alcuni numeri interi positivi possono essere scritti come la somma di almeno due numeri interi positivi consecutivi. Ad esempio 9=2+3+4=4+5,. Scrivi una funzione che accetta un intero positivo come input e stampa come output la sequenza più lunga di numeri interi positivi consecutivi che lo sommano (qualsiasi formato è accettabile, sebbene -5 byte se l'output è la sequenza crescente separata da +come mostrato sopra Se non esiste una tale sequenza, è necessario stampare il numero stesso.

Questo è il codice golf. Si applicano le regole standard. Vince il codice più breve in byte.


Esempi (notare che la formattazione varia)

Input:   9
Output:  2,3,4

Input:   8
Output:  8

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

2
I numeri emessi devono essere in un ordine specifico (come aumentare)?
xnor

2
I numeri devono essere> 0: 6 = 0 + 1 + 2 + 3 o 6 = 1 + 2 + 3
Damien

5
Come nota a margine, se ci sono sfide strettamente correlate, dire "questo non è un inganno" farà poco per convincere la gente di questo se pensano che sia un imbroglione. Sarebbe più utile se spiegassi perché pensi che non lo sia.
Martin Ender,

1
@Damien "positivo" normalmente significa> 0. Se fosse incluso 0, si chiamerebbe "non negativo".
Martin Ender,

3
cc @Vixen ^ (anche se fossero ammessi numeri negativi, la soluzione ottimale sarebbe sempre la gamma da -n+1a n)
Martin Ender,

Risposte:


11

Python, 67 byte

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

Una strategia stranamente semplice: cerca l'intervallo R con la giusta somma.

  • Se la somma è troppo piccola, sposta l'endpoint destro dell'intervallo in alto di uno aggiungendo il numero più alto successivo.
  • Se la somma è troppo grande, sposta verso l'alto l'endpoint sinistro rimuovendo l'elemento più piccolo
  • Se la somma è corretta, emettere R.

Poiché l'estremità inferiore dell'intervallo aumenta solo, vengono trovati intervalli più lunghi prima di quelli più brevi.


Stranamente efficiente. Lo stack di ricorsione alla fine trabocca, ad es. N = 8192.
primo

7

Pyth, 12 10 byte

j\+hfqsTQ}M^SQ2

Il codice è lungo 15 byte e si qualifica per il bonus di -5 byte . Provalo online nel compilatore Pyth .

Grazie a @Jakube per giocare a golf con 2 byte!

Come funziona

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
Per quelli di noi non illuminati nell'area di Pyth, potresti aggiungere una spiegazione per favore? :)
ETHproductions

Ho modificato la mia risposta.
Dennis,

Fantastico, grazie! Mi piace la tua tecnica.
Produzioni ETH il

1
Input 1000: 30 minuti e conteggio ...
primo

3

Mathematica, 73 68 65 56 43 byte

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

1
+1 Ho finito con una soluzione simile ieri sera, ma la mia connessione a Internet è andata in fumo. Inoltre puoi creare Tuplesun'espressione infix.
LegionMammal978,

3

Haskell, 49 48 byte

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

1
1 byte da salvare: usare [...]!!0invece di head[...].
nimi,

2

MATLAB, 87 79 byte

So che esiste già una risposta MATLAB, ma questa ha un approccio significativamente diverso.

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)

Questo funziona anche su Octave . Puoi provare online qui . Ho già aggiunto il codice consecutiveSum.mnell'area di lavoro collegata, quindi inserisci consecutiveSumal prompt dei comandi, quindi inserisci il valore (ad es. 25).

Sto ancora lavorando per ridurlo verso il basso (forse aggiustando l'equazione usata un po '), ma fondamentalmente trova il valore più grande nper il quale mè un numero intero, quindi visualizza i primi mnumeri che iniziano con n.

Allora perché funziona? Bene, fondamentalmente esiste un'equazione matematica che governa tutti quei numeri. Se consideri che sono tutti consecutivi e iniziano da un certo punto, puoi sostanzialmente dire:

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

Ora, da questo diventa evidente che la sequenza è fondamentalmente solo i primi pnumeri del triangolo (incluso lo 0), aggiunti a p+1molti n. Ora se lo lasciamo m=p+1, possiamo dire:

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

Questo è in realtà abbastanza risolvibile. Sto ancora cercando il modo più breve per farlo, ho alcune idee per provare a ridurre il codice sopra.


Per un input di 25, l'output sarebbe:

3     4     5     6     7

2
Per quanto riguarda il tuo punto sui numeri dei triangoli, questa sfida sta essenzialmente cercando di trovare numeri triangolari con una differenza positiva dell'input in modo tale da 1,3,6,10,...massimizzare gli indici dei numeri triangolari nella sequenza .
Arcturus,

1

Python 2, 94 byte

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'input è preso dallo stdin. Questa soluzione è adatta per input molto grandi.

Ciò scorre sulle possibili lunghezze della soluzione, r , avendo r ≤ √ (2n) e verifica esplicitamente una soluzione. Affinché esista una soluzione, se r è dispari, n mod r deve essere zero e se r è pari, n mod r deve essere r / 2 .


Esempio di utilizzo

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

Ho deliberatamente scelto esempi con output relativamente piccoli.


1

Ottava, 89 byte

Questo è il meglio che potrei fare in Octave. L'algoritmo è lo stesso di 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)

In MATLAB questo sarebbe 95 byte:

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)

In MATLAB questo funziona in circa 0,1 secondi per l'ingresso 2000000e 1 secondo per l'ingresso 1000002.


1

awk, 51 byte

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

Il codice è di 56 byte, meno 5 byte per il formato di output. Ho dovuto usare 4 byte extra per produrre quel formato, quindi ho effettivamente salvato 1 byte. Evviva! ;)

In realtà sta facendo il duro lavoro di riassumere a partire da 1 fino a quando la somma è più grande dell'input. Quindi inizia a sottrarre numeri a partire da 1 fino a quando il numero è più piccolo dell'input. Continua a modificare il numero di inizio e fine in questo modo fino a quando non trova un risultato, che viene quindi stampato.

Esempio di utilizzo

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

Uscita di esempio

49 + 48 + 50 + 51 + 52 + 53

Ho provato questo per un input di 1e12e ha dato il risultato corretto ( 464562+...+1488562) quasi immediatamente. Anche se ci è voluto un po 'per stamparlo ovviamente ...


Adoro l'approccio Awk. Ho problemi a stabilire l'ordine di precedenza nei binding. Ti dispiacerebbe includere una versione con più parentesi aggiunte per renderla un po 'più ovvia? :)
Wildcard

1
Spero che questo aiuti: {while($0!=s)s+=(s<$0) ? (++j) : -(++i); while(++i<j)r=r i"+"}$0=r j io sono sempre l'ultimo numero intero che è stato sottratto dall'inizio della catena, j è sempre l'ultimo numero intero aggiunto alla fine della catena
Cabbie407,

0

Japt , 33 byte

Questo utilizza la tecnica Pyth di Dennis , anche se è considerevolmente più lunga ...

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

Provalo online! Avviso: per input più grandi (<= 20), ci vuole un po 'di tempo per terminare e blocca il browser fino a quando non lo fa.

Ungolfed e spiegazione

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

Versione con guadagno bonus: (38 byte - 5 = 33)

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

0

Julia, 92 byte

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

Questa è una funzione anonima che accetta un numero intero e restituisce un array. Per chiamarlo, dagli un nome, ad es f=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

Rubino, 94 byte

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

Scherzi a parte, 53-5 = 48 byte

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

Dump esadecimale

2c3b3b3bbc603b75406ec728443b29606e2858586b60697540754
0783be4be3d5b5d29496960bb60a4bd4d604d3bb0704058272b6a

Provalo online!

È l'approccio della forza bruta, simile al Pyth di Dennis.

Tutto fino a quando klegge l'input nnel registro 1 e quindi crea l'elenco [[1],[2,2],[3,3,3],[4,4,4,4],...]fino a n n"s".

Il prossimo bit fino a è una funzione memorizzata nel registro 0 che accetta una coppia, incrementa entrambi gli elementi, li converte in un intervallo, trova la somma dell'intervallo e controlla se tale somma è il valore nel registro 1. Se lo è, restituisce l'intervallo corrispondente e, in caso contrario, restituisce un elenco vuoto.

La parte fino all'ultima occorrenza delle Mmappe è una funzione sull'elenco di fantasia degli elenchi sopra descritti, facendo enumeratesu ogni elenco, quindi mappando la funzione memorizzata su di esso. Al termine, abbiamo un elenco di elenchi ognuno dei quali è vuoto o un intervallo che si somma a n.

;░rimuove le liste vuote. p@Xprende il primo elenco che rimane ( 0@Efunzionerebbe anche). '+jmette +tra ciascun numero mentre converte l'elenco in una stringa per il bonus.


0

ES6, 72 byte

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

Porta diretta della soluzione awk di @ Cabbie407, ma senza il bonus di formattazione, poiché qui è una penalità.


0

Python 3, 239 236 215 203 byte

Questo è un po 'ingombrante. Dovrò giocare a golf più tardi.

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]

Questo kperché se si controlla t[0]un vuoto t, Python emette rumori maleducati. Ancora una volta, questo ha bisogno di golf. Grazie a t[:1], non più rumori maleducati! Devi solo verificare un altro array.


0

Gelatina , 8 byte (non competitiva)

ẆS⁼¥Ðf⁸Ṫ

Provalo online!

Se ho capito bene, questa potrebbe essere una versione (11-5 = 6) -byte:

ẆS⁼¥Ðf⁸Ṫj”+

Per motivi di interesse, esistono 12 soluzioni simili (compresa questa) scambiando gli uguali non vettorializzandoli con gli uguali vettorializzanti, cambiando argomento sinistro in primo argomento o identità, e scambiando uguali con non uguali e filtrando per filtro per vettorializzare e non vettorializzare. : O
HyperNeutrino,

Diciamo che ho pubblicato quello che ha più senso, ma con l'ottimizzazione della velocità.
Erik the Outgolfer,

0

05AB1E , 11-5 = 6 byte (non concorrenti)

Prendendo quel bonus ovviamente :)

LŒʒOQ}é¤'+ý

Provalo 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 byte

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

Esegui come pipe -nRo provalo online .

aumenta pfino a trovare una soluzione intera per argument==(p+q)*(q-p+1)/2,
quindi stampa l'intervallo da pa q.


0

Excel VBA, 119-5 = 114 byte

Subroutine che accetta l'input ndell'intero tipo previsto e restituisce la sequenza più lunga di numeri consecutivi che la sommano alla cella[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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.