11 = (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3) + (6) - (4)


35

Dato un numero intero positivo N , il tuo compito è di restituire il numero di passaggi richiesti dal seguente algoritmo per raggiungere N :

  1. Trova il più piccolo numero triangolare T i tale che T i  ≥ N . Crea l'elenco corrispondente L = [1, 2, ..., i] .

  2. Mentre la somma dei termini di L è maggiore di N , rimuovi il primo termine dall'elenco.

  3. Se la somma dei termini di L ora è inferiore a N , incrementa i e aggiungila all'elenco. Procedere con il passaggio 2.

Ci fermiamo, non appena N è raggiunto. Solo il primo passo viene eseguito sistematicamente. I passaggi 2 e 3 potrebbero non essere elaborati affatto.

Esempi

Di seguito è riportato un esempio per N = 11 :

Esempio

Quindi l'output previsto per N = 11 è 4 .

Altri esempi:

  • N = 5 - Iniziamo con T 3 = 1 + 2 + 3 = 6 , seguito da 2 + 3 = 5 . Uscita prevista: 2 .
  • N = 10 - È richiesto solo il primo passaggio perché 10 è un numero triangolare: T 4 = 1 + 2 + 3 + 4 = 10 . Uscita prevista: 1 .

Primi 100 valori

Di seguito sono riportati i risultati per 1 ≤ N ≤ 100 :

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

Regole

  • È possibile scrivere un programma completo o una funzione, che stampa o restituisce il risultato.
  • È necessario elaborare qualsiasi N ≤ 65536 in meno di un minuto su hardware di fascia media.
  • Dato abbastanza tempo, il tuo programma / funzione dovrebbe teoricamente funzionare per qualsiasi valore di N supportato nativamente dalla tua lingua. In caso contrario, spiega perché nella tua risposta.
  • Questo è il codice golf, quindi vince la risposta più breve in byte!

Relazionato. (Sospetto che tu lo sappia già, ma lo
pubblichi

Qual è il valore massimo di N che dobbiamo gestire?
Luca,

@Luke Consulta le regole aggiornate.
Arnauld,

Risposte:


4

Gelatina , 29 31 byte

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

Un collegamento monadico che restituisce il risultato (N = 65536 richiede meno di due secondi).

Provalo online!

Come?

Per una spiegazione approfondita dell'algoritmo vedi il fantastico post di Martin Ender .

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

L'implementazione del programma completo da 29 byte che ho creato dell'algoritmo descritto richiede 4 minuti e 30 per N = 65536 sul mio laptop, quindi suppongo che non conti.

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

Usare un ciclo while per ogni passaggio 3 e riutilizzarlo come passaggio 1 è uguale in lunghezza a quello che posso gestire con l'inizializzazione dell'elenco poiché nessun controllo sul passaggio 3 significa costruire un elenco fino a quando non rimane nulla e quindi trovare il primo indice del valore:

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i

25

Mathematica, 79 byte

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&

Spiegazione

Non potevo preoccuparmi di implementare l'algoritmo nella sfida, quindi volevo cercare una scorciatoia per la soluzione. Mentre ne ho trovato uno, purtroppo non batte la risposta di Mathematica che implementa l'algoritmo. Detto questo, sono sicuro che questo non è ancora ottimizzato, e potrebbero esserci altre lingue che possono beneficiare di questo approccio o di alcune delle intuizioni acquisite nel processo.

Quindi sostengo che la sequenza che dovremmo calcolare è:

f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)

In alternativa, è f (n) = 1 se n è un numero triangolare e f (n) = 2 * ( A212652 (n) - A002024 (n) + 1) altrimenti.

Nella prima espressione, A023532 codifica semplicemente questi due diversi casi. Le altre due sequenze (più 1) sono la differenza tra il numero intero più grande k nella decomposizione più lunga di n in numeri interi consecutivi (k-i + 1) + (k-i + 2) + ... + k = n e il numero intero più grande j in modo che 1 + 2 + ... + j <n .

In parole un po 'più semplici, ecco come troviamo la risposta per i numeri non triangolari: in primo luogo, troviamo il numero triangolare più grande T j che è inferiore a n . Quindi j è il penultimo numero intero che viene aggiunto durante il passaggio 1 (perché dopo aver aggiunto j + 1 avremo superato n ). Quindi decomponi n nel numero massimo (o più piccolo) di numeri interi consecutivi possibile e chiama il massimo tra questi numeri k . Il risultato è semplicemente 2 * (kj) . La ragione intuitiva di ciò è che il massimo nella decomposizione cresce di 1 ogni altro passo e ci fermiamo quando raggiungiamok .

Dobbiamo mostrare quattro cose per dimostrare che funziona:

  1. f (n) = 1 per i numeri triangolari. Questo è banalmente il caso, perché il primo passo scorre semplicemente attraverso tutti i numeri triangolari. Se abbiamo colpito n esattamente durante questo processo, abbiamo finito e c'era solo un passo da calcolare.
  2. Per tutti gli altri numeri, finiamo sempre dopo una fase di eliminazione, mai dopo una fase di inserimento. Ciò significa che tutte le altre f (n) sono pari.
  3. In ogni passaggio di inserimento dopo il primo, aggiungiamo solo un singolo numero. Questo garantisce che raggiungeremo una decomposizione includendo k dopo kj coppie di passi.
  4. La decomposizione finale di n che otteniamo è sempre la decomposizione più lunga possibile di n in numeri interi consecutivi, ovvero è sempre la decomposizione di n con il massimo più basso tra i numeri sommati. In altre parole, l'ultimo numero che aggiungiamo alla somma è sempre A212652 (n) .

Abbiamo già mostrato perché (1) è vero. Successivamente, dimostriamo che non possiamo terminare con un passaggio di inserimento tranne quello iniziale (che non accade per i numeri non triangolari).

Supponiamo che siamo finiti in una fase di inserimento, raggiungendo n dopo aver aggiunto un valore p alla somma. Ciò significa che prima di questo passaggio di inserimento, il valore era np ( o inferiore se aggiungessimo più valori contemporaneamente). Ma questo passaggio di inserimento è stato preceduto da un passaggio di eliminazione (dal momento che non avremmo potuto premere n durante il passaggio 1). L'ultimo valore q che abbiamo rimosso durante questo passaggio di eliminazione era necessariamente inferiore a p a causa del modo in cui l'algoritmo funziona. Ciò significa che prima di rimuovere q avevamo n-p + q ( o meno ) che è inferiore a n. Ma questa è una contraddizione, perché avremmo dovuto smettere di rimuovere numeri interi quando avessimo premuto n-p + q invece di rimuovere un altro q . Ciò dimostra il punto (2) sopra. Quindi ora sappiamo che finiamo sempre in una fase di eliminazione e che quindi tutti i numeri non triangolari hanno persino output.

Successivamente dimostriamo (3) che ogni passaggio di inserimento può inserire solo un valore. Questo è essenzialmente un corollario di (2). Abbiamo dimostrato che dopo aver aggiunto un valore non possiamo toccare n esattamente e poiché la dimostrazione utilizzava una disuguaglianza, non possiamo nemmeno finire sotto n (poiché allora n-p + q sarebbe comunque inferiore a n e non avremmo dovuto rimuovere che molti valori in primo luogo). Pertanto, ogni volta che aggiungiamo un singolo valore, siamo garantiti per superare n perché siamo andati sotto n rimuovendo un valore più piccolo. Quindi, sappiamo che l'estremità superiore della somma cresce di 1 ogni altro passaggio. Conosciamo il valore iniziale di questa fascia superiore (è la m più piccola taleT m > n ). Ora abbiamo solo bisogno di capire questa fascia alta una volta raggiunta la somma finale. Quindi il numero di passaggi è semplicemente il doppio della differenza (più 1).

Per fare ciò, dimostriamo (4) che la somma finale è sempre la decomposizione di n nel maggior numero possibile di numeri interi, o la decomposizione in cui il massimo in quella decomposizione è minimo (cioè è la prima decomposizione possibile). Lo faremo di nuovo per contraddizione (la formulazione in questa parte potrebbe essere un po 'più rigorosa, ma ho già trascorso troppo tempo su questo ...).

Supponiamo che la prima / più lunga decomposizione possibile di n sia qualche a + (a + 1) + ... (b-1) + b , a ≤ b , e dire che l'algoritmo lo salta. Ciò significa che nel momento in cui b viene aggiunto, a non deve più far parte della somma. Se a fosse parte della somma s , allora avremmo n ≤ s in quel momento. Quindi o la somma contiene solo i valori da a a b , che equivale a n e ci fermiamo (quindi non abbiamo saltato questa decomposizione), oppure c'è almeno un valore in meno di a nella somma, vinci quale caso n <se quel valore verrebbe rimosso fino a quando non avremo raggiunto la somma esatta (di nuovo, la decomposizione non è stata saltata). Quindi dovremmo sbarazzarci di a prima di aggiungere b . Ciò significa che dovremmo raggiungere una situazione in cui a è il componente più piccolo della somma e il più grande non è ancora b . Tuttavia, a quel punto non possiamo rimuovere a , poiché la somma è chiaramente inferiore a n (poiché manca b ), quindi dobbiamo prima aggiungere valori fino a quando non aggiungiamo b e premiamo n esattamente. Questo dimostra (4).

Quindi, tenendo insieme queste cose: sappiamo che la prima coppia di passaggi ci dà un valore massimo di A002024 (n) . Sappiamo che il valore massimo della decomposizione finale è A212652 (n) . E sappiamo che questo massimo viene incrementato una volta in ogni coppia di passaggi. Quindi, l'espressione finale è 2 * ( A212652 (n) - A002024 (n) + 1) . Questa formula funziona quasi per i numeri triangolari, ad eccezione del fatto che per quelli abbiamo bisogno solo di 1 passaggio invece di 2, motivo per cui correggiamo il risultato con la funzione indicatore dei numeri triangolari (o il suo contrario, a seconda di quale sia più conveniente).

Infine, per quanto riguarda l'implementazione. Per la prima sequenza, sto usando la formula MIN (dispari d | n; n / d + (d-1) / 2) da OEIS. Risulta per salvare alcuni byte se prendiamo il fattore 2 in questa espressione per ottenere MIN (dispari d | n; 2n / d + d-1) , perché -1 quindi si annulla con +1 nella mia prima versione di f (n) che codifica direttamente i due casi per numeri triangolari e non triangolari. Nel codice, questo è:

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]

Per quest'ultima sequenza ( 1, 2, 2, 3, 3, 3, ...), possiamo usare un semplice modulo chiuso:

⌊(2#)^.5+.5⌋

E infine, la funzione dell'indicatore inverso dei numeri triangolari è 0 ogni volta che 8n + 1 è un quadrato perfetto. Questo può essere espresso in Mathematica come

⌈Sqrt[8#+1]~Mod~1⌉

Esistono molti modi per esprimere queste ultime due sequenze e spostare un offset costante tra loro, quindi sono sicuro che questa non sia ancora un'implementazione ottimale, ma spero che ciò possa dare ad altri un punto di partenza per esaminare nuovi approcci in le loro lingue.

Da quando ho affrontato tutti questi problemi, ecco un diagramma della sequenza fino a n = 1000 (potrei anche calcolare 100k in un paio di secondi, ma in realtà non mostra ulteriori approfondimenti):

inserisci qui la descrizione dell'immagine

Potrebbe essere interessante esaminare le variazioni di quelle linee molto dritte, ma lo lascerò a qualcun altro ...


Alla fine mi sono preso il tempo di leggere attentamente la tua risposta. È brillante. Si noti che (3) è già stato assunto dall'algoritmo (il passaggio n. 3 è un if , non un po ' ), ma la dimostrazione è - ovviamente - molto apprezzata.
Arnauld,

@Arnauld Grazie. :) Devo aver trascurato / frainteso la parte if / while. Meno male che non fa differenza allora.
Martin Ender,

7

Mathematica, 72 byte

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

Funzione pura che accetta un argomento intero.

Come funziona

For[ ... ]

Un Forciclo.

l=u=c=k=0

Inizializzazione; impostare l(inferiore), u(superiore), c(contatore) e k(somma) su 0.

k!=#

Condizione; ripetere mentre knon è uguale all'input.

c++

Incremento; incrementare il contatore c.

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

Corpo

If[#>k, ... ]

Se l'input è maggiore di k:

While[#>k,k+=++u]

Mentre l'input è maggiore di k, incrementa ue incrementa kdi u.

Se l'ingresso non è maggiore di k:

While[#<k,k-=l++]

Mentre l'input è inferiore a k, diminuisce kdi le incrementa l.

( ... ;c)

Ritorna cdopo il ciclo.


1
For[,...]battiti While[...].
Martin Ender,

5

Python 2 , 104 byte

N=input();i=s=0;l=()
while N!=sum(l):exec'while sum(l)'+['<N:i+=1;l+=i,','>N:l=l[1:]'][s%2];s+=1
print s

Provalo online!

Si alterna tra l'aggiunta di termini alla fine dell'elenco e la rimozione dei termini dall'inizio.


5

Haskell , 70 63 68 64 byte

MODIFICARE:

  • -7 byte: sbarazzarsi di uno spazio, due segni e alcune parentesi negando il senso di a. Risolti errori off-by-one nella spiegazione.
  • +5 byte: Argh, completamente perso che 65536 esigenza, e si scopre (1) potenze di 2 sono particolarmente costosi, perché solo ottenere successo quando si arriva al numero stesso (2) così sta sommando lunghe distanze (che avvolgono intorno zero) per tutto il tempo. Sostituito la somma con una formula matematica.
  • -4 byte: rettificato ae blinearmente per ottenere i termini nella formula di somma da annullare.

1#1 è una funzione anonima che accetta e restituisce un numero intero.

Usa come (1#1) 100.

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

Provalo online!

Come funziona

  • (a#b)nrappresenta la fase di calcolo corrente. a, bsono numeri in 1, 3, 5, .., mentre npossono essere positivi o negativi a seconda del passo.
    • Nel passaggio 1 o 3, rappresenta l'elenco [(a+1)/2,(a+3)/2..(b-1)/2]e il numero obiettivo -n.
    • Nel passaggio 2, rappresenta l'elenco [(b+1)/2,(b+3)/2..(a-1)/2]e il numero obiettivo n.
  • La strana corrispondenza tra a, be le liste è per poter fare la somma con la breve espressione s=a*a-b*b.
    • Nei passaggi 1 e 3, è uguale a s= -8*sum[(a+1)/2..(b-1)/2].
    • Nel passaggio 2, questo è lo stesso di s=8*sum[(b+1)/2..(a-1)/2].
  • La ramificazione si ottiene avendo una comprensione dell'elenco che produce elementi in un solo caso ciascuno e sommando i risultati.
    • Se s>8*n, quindi bviene incrementato di 2 prima di ricorrere.
      • Nei passaggi 1 e 3, questo aumenta l'elenco, mentre nel passaggio 2, questo si restringe.
    • Se s<8*n, quindi la ricorsione cambia il passaggio scambiando ae b, e negando n, e 1 viene aggiunto al risultato.
    • Se s==8*n, nessuna delle due comprensioni dell'elenco fornisce alcun elemento, quindi la somma è 0.
  • (1#1) nrappresenta una "fase 2" fittizia prima di iniziare, che viene immediatamente modificata al passaggio 1, creando l'elenco da [1..0]=[].

4

PHP> = 7.0, 74 byte

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

usa l' operatore dell'astronave

Provalo online!

allargato

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps

Cosa $argn?
chx,

@chx Una variabile che è disponibile quando si si PHP da linea di comando con l'opzione -R php.net/manual/en/features.commandline.options.php
Jörg Hülsermann

Wow. Non ho mai sentito parlare di -Rmolto meno argvo argi. Conoscevo argc e argv ovviamente. Molto interessante, grazie.
chx,

4

C, 94 91 byte

Prova online

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}

Ampio uso su variabili non inizializzate oO
YSC

@YSC in C, gli interi dichiarati globalmente non inizializzati sono impostati a zero al momento della compilazione. leggi di più
Khaled.K,

Dimenticato questo. Grazie per questo promemoria.
YSC,

Cordiali saluti, ho postato un'altra risposta C . Almeno uno dei trucchi che ho usato non funzionerà con altri compilatori (quelli mancanti return), ma per quelli che lo fanno, sentiti libero di incorporarli nella tua risposta.
hvd,

3

JavaScript (ES6), 82 byte

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

Test dello snippet


Mi dispiace dirlo, ma ogni ↄ conta come 3 byte. Immagino che non abbia importanza dato che è banalmente rinominabile.
Ørjan Johansen

@ ØrjanJohansen Grazie per avermelo ricordato. Dovrei davvero ricordare di segnare il mio codice per byte piuttosto che per lunghezza. Non credo che ci sia un consenso della comunità su "variabili banalmente rinominabili", quindi ho modificato il post. Oh bene.
R. Kap

3
Lo snippet fallisce con "Troppa ricorsione" su 6553. 6553 funziona nel nodo (6.9.1) localmente, ma 65536 no ("Dimensione massima dello stack di chiamate superata").
eush77,

3

dc , 61 byte

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

Provalo online!

Spiegazione

Principale macro ricorsiva:

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

Questa macro:

  1. Trova il numero triangolare minimo che supera il numero corrente nella pila (usando la formula della radice triangolare modificata ).
  2. Verifica se la somma triangolare Srappresenta esattamente il numero corrente. Esce se lo fa.
  3. Passa al punto 1 con S+N(eccessiva approssimazione) o S-N(insufficiente approssimazione), la scelta si alterna tra iterazioni.

Quando esce, la traccia lasciata in pila indica al programma principale quante iterazioni ha preso.


3

Python 3, 150 138 byte

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

changelog:

  • Modificato append in + =, rimosso altro (grazie musicman523, Loovjo; -12 byte)

1
Il passaggio 2 può rimuovere uno o più termini contemporaneamente dall'elenco (come 1, 2 e 3 nell'esempio per N = 11) ma viene conteggiato come un passaggio in entrambi i modi.
Arnauld,

@Arnauld l'ha trascurato; fisso.
L3viathan,

1
Puoi spiegare perché elseè necessario? Credo che le elseesecuzioni ogni volta, perché il ciclo termina sempre normalmente (senza break) e sembra funzionare bene senza di esso .
musicman523

È possibile saltare la A=l.appendparte e utilizzare l+=[x]invece.
Loovjo,

3

Lotto, 126 byte

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

Spiegazione: lè zero se il passaggio 2 non è mai stato eseguito. Ciò consente ndi tenere traccia del numero di iterazioni del passaggio 3. Poiché l'algoritmo non si ferma mai al passaggio 3, deve quindi aver eseguito il passaggio 1 una volta e il passaggio 2 n+1volte per un totale di n+n+2passaggi. Tuttavia, se il parametro è un numero triangolare, il passaggio 2 non viene mai eseguito, quindi è necessario sottrarre un passaggio.


3

Python 2, 86 81 byte

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

Provalo online!

Calcola il caso di prova 655360.183s su TIO.


Questa versione ricorsiva a 84 byte non è in grado di calcolare tutti i valori fino a 65536:

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

Provalo online!


2

Mathematica, 92 byte

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

Funzione pura che accetta un argomento intero e restituisce un intero.

Le variabili ae brappresentano i numeri di inizio e fine (in costante cambiamento) nella somma considerata, mentre qrappresenta il totale parziale (dei numeri da a+1a b); ttiene traccia di tutti i valori qrilevati finora. Dopo aver inizializzato queste variabili, il Forciclo continua l'esecuzione If[q<#,q+=++b,q-=++a], che aggiunge un nuovo numero alla fine o sottrae il numero nella parte anteriore come dettato dalle specifiche, fino a quando non è quguale all'input.

Ora non ci resta che estrarre il numero di passaggi tdall'elenco dei qvalori rilevati lungo il percorso. Ad esempio, quando l'ingresso è 11, il Forloop termina con tequaling {0,1,3,6,10,15,14,12,9,15,11}. Il modo migliore che ho trovato per calcolare il numero di passaggi da questo è contare quante volte le differenze passano da salire a scendere; questo è ciò che fa il comando dettagliato Length@Split@Sign@Differences@t, ma sospetto che possa essere migliorato.


2

C (tcc), 71 byte (61 + 10)

Argomenti della riga di comando (incluso uno spazio):

-Dw=while

Fonte:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

Come funziona:

cconta il numero di passaggi. me Mmemorizza il minimo e il massimo dell'intervallo, sla somma. Inizialmente, sono tutti zero.

Continuamente, cviene aumentato e sconfrontato con n. Finché sono ineguali:

  • Se cè dispari, quindi fino a quando s<naggiungi un numero intero alla fine dell'intervallo: aumenta Mdi uno e sdi M.

  • Se cè pari, quindi fino a quando s>n, rimuovi un numero intero dall'inizio dell'intervallo: diminuisci sdi me aumenta mdi uno.

Quando il loop termina, cè stato aumentato una volta troppe volte. Decrementandolo produce il risultato corretto e si verifica che sia calcolato nel registro corretto per fungere da valore di ritorno.

Divertentemente capita di usare gli stessi identici nomi di variabili della risposta C di Khaled.K . Non vengono copiati.


1

Perl 6 , 114 byte

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(ispirato a un'implementazione precedente di Haskell )

Provalo
Funziona con un input di 65536 in meno di 45 secondi sul mio computer, ma non sono riuscito a farlo funzionare in meno di 60 secondi con TIO.run.
Ho Rakudo v2017.04 +, dove ha v2017.01 .
Rakudo / NQP / MoarVM ottiene ottimizzazioni quasi quotidianamente, quindi potrebbero esserci un numero illimitato di esse nel frattempo necessarie per ottenerle in tempo.


allargato

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

Nota che Rakudo ha un'ottimizzazione per Range.sumnon dover iterare tutti i valori.

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.