Somma parziale esatta della serie armonica


15

Sfida

Dato un numero intero positivo N, genera la somma dei primi Nreciproci come una frazione esatta, che è rappresentata come una coppia di numeri interi in un ordine coerente che rappresenta numeratore e denominatore.

Regole

  • L'output deve essere esatto.

  • L'output dovrebbe essere una coppia di numeri interi in un ordine coerente che rappresenta numeratore e denominatore.

  • L'uso di tipi numerici non interi (built-in o libreria) è vietato.

    • Chiarimento / eccezione: i tipi numerici non interi vanno bene se e solo se tutti i valori utilizzati, calcolati e restituiti sono numeri interi (ovvero la tua lingua utilizza numeri razionali per impostazione predefinita, ma nella tua risposta usi solo l'aritmetica dei numeri interi)
  • L'output dovrebbe essere il più ridotto possibile. ( 3/2va bene, 6/4no)

  • Scappatoie standardSono vietate le .

  • Gli invii dovrebbero funzionare per input almeno fino a 20, o questa meta , a seconda di quale sia maggiore.

Casi test

1: 1/1
2: 3/2 (1/1 + 1/2)
3: 11/6 (1/1 + 1/2 + 1/3)
4: 25/12 etc.
5: 137/60
6: 49/20
20: 55835135/15519504
56: 252476961434436524654789/54749786241679275146400
226: 31741146384418617995319820836410246588253008380307063166243468230254437801429301078323028997161/5290225078451893176693594241665890914638817631063334447389979640757204083936351078274058192000

Generazione di test-case (Python 3)

import fractions
def f(x):
    return sum(fractions.Fraction(1,i) for i in range(1,x+1))

Simile a questa sfida e questa sfida .

I numeratori sono OEIS A001008 e i denominatori sono OEIS A002805 .




È gcduna "funzione integrata" se la tua lingua lo fornisce?
Chas Brown,

@ChasBrown gcde altre funzioni integrate vanno bene. I tipi razionali / frazionari non sono ammessi.
pizzapants184,

1
@JoKing Va bene se i numeri sono di tipo razionale purché vengano utilizzati solo numeri interi. Aggiornerò la domanda.
pizzapants184,

Risposte:


8

Python 2 , 80 79 byte

D=1;N=n=0;exec"n+=1;y=N=N*n+D;x=D=D*n;"*input()
while y:x,y=y,x%y
print N/x,D/x

Provalo online!

Stampa il numeratore e il denominatore.

Sìì! Supporto per MathJax !!!! Si osserva:

i=1n1i=i=1nn!n!i=i=1nn!in!

Quindi, pensando alla ricorsione, per positivo, nell'umeratore:nN

i=1n+1(n+1)!i=(n+1)i=1nn!i+(n+1)!n+1=(n+1)i=1nn!i+n!

e non si può fare a meno di pensare Dall'enominatore anche ricorsivamente; quindi il .n!exec

Dobbiamo pagare il Piper a frazione ridotta con un calcolo GCD nel whileloop; e poi abbiamo finito.


7

Gelatina , 10 byte

!:RS,!:g/$

Provalo online!

Come funziona

!:RS,!:g/$  Main link. Argument: n

!           Compute n!.
  R         Range; yield [1, ..., n].
 :          Divide n! by each k in [1, ..., n].
   S        Take the sum. Let's call it s.
     !      Compute n! again.
    ,       Pair; yield [s, n!].
      :g/$  Divide [s, n!] by their GCD.

5

J , 16 byte

!(,%+.)1#.!%1+i.

Provalo online!

Esegui esempi

f =: !(,%+.)1#.!%1+i.
f 6x
   20 49
f 20x
   15519504 55835135
f 56x
   54749786241679275146400 252476961434436524654789

Come funziona

!(,%+.)1#.!%1+i.    NB. Tacit verb
            1+i.    NB. 1 to n inclusive
          !%        NB. Divide factorial by 1 to n
       1#.          NB. Sum i.e. numerator (not reduced)
!                   NB. Factorial i.e. denominator (not reduced)
 (,%+.)             NB. Divide both by GCD

J , 9 byte, usando il tipo di frazione

1#.1%1+i.

Provalo online!

J dà le frazioni per la divisione int-int se non divisibile.




Conterrebbe 2 x:1#.1%1+i.come una risposta valida o è un uso non valido di un tipo razionale?
Cole

5

05AB1E , 10 byte

!DIL÷O)D¿÷

Provalo online!

Utilizza lo stesso metodo di tutte le altre voci. L'output è nella forma [denominator, numerator].

!DIL÷O)D¿÷   Full program. Let's call the input I.
!D           Push the factorial twice to the stack. STACK: [I!, I!]
  IL         Range from 1 to I. STACK: [I!, I!, [1 ... I]]
    ÷        Vectorized integer division. STACK: [I!, [I! / 1, I! / 2, ..., I! / I]]
     O       Sum. STACK: [I!, I! / 1 + I! / 2 + ... + I! / I]
      )      Wrap stack. STACK: [[I!, I! / 1 + I! / 2 + ... + I! / I]]
       D     Duplicate. STACK: [[I!, I! / 1 + ... + I! / I], [I!, I! / 1 +... + I! / I]]
        ¿    GCD. STACK: [[I!, I! / 1 + ... + I! / I], gcd(I!, I! / 1 +... + I! / I)]
         ÷   Vectorized integer division. 


3

JavaScript (ES6), 60 byte

Ritorni [numerator, denominator].

f=(n,a=0,b=1)=>n?f(n-1,p=a*n+b,q=b*n):b?f(0,b,a%b):[p/a,q/a]

Provalo online!

Come?

Il metodo è simile alla risposta Python di @ ChasBrown .

aba=0b=1

aan+bbbnnn-1

n=0 .

(un',B)(p,q)un'GCD(un',B)

un'BBun'modB

b=0 .

p/aq/un'


3

Perl 6 , 57 53 byte

{+($!=[*] 1..$_)/($!=($/=sum $! X/1..$_)gcd$!),$//$!}

Provalo online!

Un blocco di codice anonimo che accetta un numero intero e restituisce una tupla di denominator, numerator .

Se ci fosse permesso di usare tipi frazionari, sarebbe il 32 byte molto più semplice:

{sum(map 1/*.FatRat,1..$_).nude}

Provalo online!



2

C ++ 17 (gcc) , 108 byte

Usa solo l'aritmetica dei numeri interi:

#import<random>
int f(int x,long&n,long&d){n=0;d=1;int
a;while(n=n*x+d,d*=x,a=std::gcd(n,d),n/=a,d/=a,--x);}

Provalo online!


C ++ 17 (gcc) , 108 byte

#import<random>
int f(long&n){double a=0;long
d=1;while(d*=n,a+=1./n,--n);n=a*d+.5;n/=a=std::gcd(n,d);d/=a;}

Provalo online!

Come sotto, ma usa C ++ 17 std::gcd.


C ++ (gcc) , 109 byte

#import<regex>
int f(long&n){double a=0;long
d=1;while(d*=n,a+=1./n,--n);n=a*d+.5;n/=a=std::__gcd(n,d);d/=a;}

Provalo online!

Poiché C ++ non ha il supporto nativo per bigint, questo sicuramente trabocca n>20 .

Richiedere:

  • gcc è deprecato importdichiarazione .
  • gcc's std::__gcd.
  • -O0 (Penso di sì) altrimenti il ​​compilatore si ottimizzerà d/=a .
  • Almeno 64 bit long.

Spiegazione:

  • Permettere d=n!,un'=Hn.
  • Rotondo a*dper intero più vicino per colata a*d+.5a long, e assegnare a n. Adesson/d è l'output.
  • Semplifica la frazione con std::__gcd.

Non puoi usare auto a=0.invece di double a=0(1 carattere in meno)?
Dan M.

Si Lui può. E un altro byte dal loop: 106 byte
movatica


2

MATL, 13 byte

:tptb/sht&Zd/

Provalo su MATL online

Stesso metodo usato nella risposta Jelly di @Dennis .

:t    % Range from 1 to n, duplicate. 
pt    % Take the product of that (= factorial), duplicate that too.     
b/    % Bring the range to top of stack, divide factorial by each element    
sh    % Sum those. Concatenate factorial and this into a single array.     
t&Zd/ % Compute GCD of those and divide the concatenated array elements by the GCD.     

(Uscita implicita, stampa prima il denominatore e poi il numeratore.)

Inesattezze in virgola mobile indicano che questo non funziona per n = 20, perché i valori intermedi sono troppo grandi. Sembra che l'output del test case sia stato un refuso, questo restituisce la stessa risposta delle altre risposte per n = 20.

Ecco una versione intera di conservazione del tipo (25 byte) che ho provato nel frattempo, prima di scoprirlo:

25 byte, input fino a 43

O1i:3Y%"t@*b@*b+wht&Zd/Z}

Provalo online!

Lancia i numeri uint64prima di operare su di essi, esegue l'aritmetica esplicitamente in un ciclo (senza usare prodo sum). Ancora più importante, divide i numeratori e denominatori parziali per il loro GCD ogni passo lungo il percorso, alla fine di ogni iterazione. Ciò aumenta l'intervallo di input da consentiren fino a 43. Parte del codice si basa sulla risposta Python di @Chas Brown.

Metodo alternativo (originale) utilizzando LCM anziché fattoriale:

16 15 byte

:t&Zmtb/sht&Zd/

Provalo su MATL online


1

Excel VBA, 141 byte

Riceve input [A1]e output dalla console.

s="=If(Row()>A$1,":[B:B]=s+"1,Row())":l=[LCM(B:B)]:[C:C]=s &"0,"&l &"/B1)":g=[GCD(LCM(B:B),SUM(C:C))]:?Format([Sum(C:C)]/g,0)"/"Format(l/g,0)

Ungolfed e commentato

Sub HarmonicSum(n)
    [A1] = n                            ''  Pipe input
    s = "=IF(ROW()>A$1,"                ''  Hold the start of formulas
    [B1:B40] = s + "1,ROW())"           ''  Get series of numbers 1 to N, trailing 1s
    l = [LCM(B1:B40)]                   ''  Get LCM
    [C1:C40] = s & "0," & l & "/B1)"    ''  Get LCM/M for M in 1 to N
    g = [GCD(LCM(B1:B40),SUM(C1:C40))]  ''  Get GCD
                                        ''  Format and print output
    Debug.Print Format([Sum(C1:C40)] / g, 0); "\"; Format(l / g, 0)
End Sub

1

dc , 87 byte

?sn1dsNsD[lndlDdlNln*+sN*sD1-dsn1<M]sMln1<MlDsAlNsB[lAlB%sTlBsAlTsBlB0<G]dsGxlDlA/lNlA/

Provalo online!

Ciò lascia il numeratore e il denominatore in cima allo stack in quell'ordine, come consentito da questo output predefinito. Dal momento dcche non ha un gcdbuilt-in, questo utilizza l' algoritmo euclideo per calcolare il gcd.


1

Stax , 11 byte

ó╢Δ'åç4}ú┌7

Esegui ed esegui il debug

Spiegazione:

Vogliamo calcolare:

Σio=1n1io

Ora abbiamo bisogno di un denominatore B e un elenco di numeratori un'io:

Σio=1nun'ioB=Σio=1nun'ioB

Possiamo fare B=n!, Poi abbiamo:

un'ion!=1io|×n!un'io=n!io

Quindi abbiamo:

Σio=1n1n=Σio=1nn!ion!
|Fx{[/m|+L:_m Full program
|F            Factorial
  x           Push input again
   {  m       Map over range [1, n]
    [           Copy the factorial
     /          Divide factorial by current value
       |+     Sum
         L    Listify stack, top gets first element
          :_  Divide both values by gcd
            m Print each followed by newline

1

APL (NARS), 56 caratteri, 112 byte

{⍵=1:⊂1 1⋄{(r s)←⍺⋄(i j)←⍵⋄m÷∨/m←((r×j)+s×i),s×j}/1,¨⍳⍵}

test:

  f←{⍵=1:⊂1 1⋄{(r s)←⍺⋄(i j)←⍵⋄m÷∨/m←((r×j)+s×i),s×j}/1,¨⍳⍵}
  f 1
1 1 
  f 2
3 2 
  f 3
11 6 
  f 20
55835135 15519504 

In poche parole ridurre la "funzione somma su 2 numeri di frazione" (un numero di frazione è un elenco di 2 numeri interi) sul set:

1 2, 1 3,..., 1 n

questo sotto sembra sbagliato:

 f 56
74359641471727289 16124934538402170

ma se cambio il tipo di input rispetto a:

  f 56x
252476961434436524654789 54749786241679275146400 
  f 226x
31741146384418617995319820836410246588253008380307063166243468230254437801429301078323028997161 529022507845189
  3176693594241665890914638817631063334447389979640757204083936351078274058192000

1

APL (Dyalog Unicode) , 15 12 byte

⌽!(,÷∨)1⊥!÷⍳

Provalo online!

Funzione tacita, prendendo un singolo argomento . Salva un byte rimuovendo se è consentito stampare prima il denominatore.

Grazie @dzaima per 3 byte.

Come:

⌽!(,÷∨)1⊥!÷⍳  Tacit function, argument will be called ⍵.
             Range 1..⍵ 
          ÷   Dividing
         !    the factorial of 
       1     Base-1 decode, aka sum;
 !(   )       Using that sum and the factorial of  as arguments, fork:
             (GCD
    ÷         dividing
   ,          the vector with both arguments)
             reversed.
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.