Точная частичная сумма гармонических рядов


15

Вызов

Учитывая положительное целое число N, выведите сумму первых Nобратных значений в виде точной дроби, которая представлена ​​в виде пары целых чисел в согласованном порядке, представляющем числитель и знаменатель.

правила

  • Вывод должен быть точным.

  • Вывод должен быть в виде пары целых чисел в согласованном порядке, представляющем числитель и знаменатель.

  • Использование нецелых числовых типов (встроенных или библиотечных) запрещено.

    • Пояснение / исключение: нецелые числовые типы допустимы, если и только если все используемые, вычисленные и возвращенные значения являются целыми числами (т. Е. Ваш язык использует рациональные числа по умолчанию, но вы используете только целочисленную арифметику в своем ответе)
  • Вывод должен быть как можно меньше. ( 3/2все в порядке, 6/4нет)

  • Стандартные лазейки запрещены.

  • Материалы должны работать для входных данных, по крайней мере, до 20, или эта мета , в зависимости от того, что выше.

Тестовые случаи

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

Генерация тест-кейсов (Python 3)

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

Похож на этот вызов и этот вызов .

Числителями являются OEIS A001008 , а знаменателями являются OEIS A002805 .




Является gcdли «встроенная функция», если ваш язык обеспечивает ее?
Час Браун

@ChasBrown gcdи другие встроенные функции в порядке. Рациональные / дробные типы не допускаются.
pizzapants184

1
@JoKing Хорошо, если числа рационального типа, если используются только целые числа. Я обновлю вопрос.
pizzapants184

Ответы:


8

Python 2 , 80 79 байт

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

Попробуйте онлайн!

Печатает числитель и знаменатель.

Ура! Поддержка MathJax !!!! Один замечает:

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

Затем, думая о рекурсии, для положительных, в umerator:nN

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

и нельзя не думать о Dзнаменателе также рекурсивно; таким образом .n!exec

Мы должны заплатить Пайпер с уменьшенной дробью с помощью вычисления GCD в whileцикле; и тогда мы закончили.


7

Желе , 10 байт

!:RS,!:g/$

Попробуйте онлайн!

Как это устроено

!: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 байт

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

Попробуйте онлайн!

Выполнить примеры

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

Как это устроено

!(,%+.)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 байт, используя тип дроби

1#.1%1+i.

Попробуйте онлайн!

J дает дроби для деления на int-int, если не делится.




Будет ли 2 x:1#.1%1+i.считаться правильным ответом, или это неправильное использование рационального типа?
Коул

5

05AB1E , 10 байтов

!DIL÷O)D¿÷

Попробуйте онлайн!

Использует тот же метод, что и все остальные записи. Выход в форме [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 байт

Возвращает [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]

Попробуйте онлайн!

Как?

Метод похож на ответ @ ChasBrown's Python .

aбaзнак равно0бзнак равно1

aaN+бббNNN-1

Nзнак равно0 .

(a,б)(п,Q)aНОД(a,б)

aббaмодификацияб

бзнак равно0 .

п/aQ/a


3

Perl 6 , 57 53 байта

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

Попробуйте онлайн!

Блок анонимного кода, который принимает целое число и возвращает кортеж denominator, numerator.

Если бы нам было разрешено использовать дробные типы, это было бы намного проще 32 байта:

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

Попробуйте онлайн!



2

C ++ 17 (gcc) , 108 байт

Используйте только целочисленную арифметику:

#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);}

Попробуйте онлайн!


C ++ 17 (gcc) , 108 байт

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

Попробуйте онлайн!

То же, что и ниже, но используйте C ++ 17 std::gcd.


C ++ (gcc) , 109 байт

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

Попробуйте онлайн!

Поскольку C ++ не имеет встроенной поддержки bigint, это определенно переполнится n>20.

Требуется:

  • Устаревшее importзаявление GCC .
  • GCC std::__gcd.
  • -O0 (Я так думаю) иначе компилятор будет оптимизирован d/=a .
  • Как минимум 64-битный long.

Объяснение:

  • dзнак равноN!,aзнак равноЧАСN
  • Круглый a*dдо ближайшего целого числа путем литья a*d+.5до long, и назначьте n. Теперь n/dвыходной.
  • Упростить дробь с std::__gcd.

Вы не можете использовать auto a=0.вместо double a=0(на 1 символ меньше)?
Дэн М.

Да он может. И еще один байт из цикла: 106 байтов
movatica


2

MATL, 13 байт

:tptb/sht&Zd/

Попробуйте это на MATL Online

Тот же метод, который использовался в ответе @Dennis 'Jelly .

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

(Неявный вывод, сначала печатает знаменатель, а затем числитель.)

Неточности с плавающей точкой означают, что это не работает для n = 20, потому что промежуточные значения слишком велики. Похоже, результат теста был опечаткой, он возвращает тот же ответ, что и остальные ответы для n = 20.

Вот целочисленная версия с сохранением типа (25 байт), которую я пробовал за это время, прежде чем выяснить это:

25 байтов, ввод до 43

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

Попробуйте онлайн!

Приводит числа к, uint64прежде чем работать с ними, выполняет арифметику явно в цикле (без использования prodили sum). Что еще более важно, делит частичные числители и знаменатели на их GCD каждый шаг на пути, в конце каждой итерации. Это увеличивает диапазон ввода nдо 43. Часть кода основана на ответе Python @Chas Brown.

Альтернативный (оригинальный) метод с использованием LCM вместо факториала:

16 15 байт

:t&Zmtb/sht&Zd/

Попробуйте это на MATL Online


1

Excel VBA, 141 байт

Принимает ввод [A1]и вывод на консоль.

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 и прокомментировал

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

постоянный ток , 87 байт

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

Попробуйте онлайн!

Это оставляет числитель и знаменатель на вершине стека в этом порядке, как это разрешено этим выходным значением по умолчанию. Так dcкак не имеет gcdвстроенного, это использует евклидов алгоритм для вычисления gcd.


1

Stax , 11 байт

ó╢Δ'åç4}ú┌7

Запустите и отладьте его

Объяснение:

Мы хотим рассчитать:

Σязнак равно1N1я

Теперь нам нужен знаменатель б и список числителей aя:

Σязнак равно1Naябзнак равноΣязнак равно1Naяб

Мы можем сделать бзнак равноN!тогда имеем:

aяN!знак равно1я|×N!aязнак равноN!я

Итак, мы имеем:

Σязнак равно1N1Nзнак равноΣязнак равно1NN!яN!
|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 символов, 112 байтов

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

тестовое задание:

  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 

В нескольких словах уменьшите «функцию суммы на 2 числа дроби» (одно число дроби - это список из 2 целых чисел) на множестве:

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

это ниже кажется неправильным:

 f 56
74359641471727289 16124934538402170

но если я изменю тип ввода, чем:

  f 56x
252476961434436524654789 54749786241679275146400 
  f 226x
31741146384418617995319820836410246588253008380307063166243468230254437801429301078323028997161 529022507845189
  3176693594241665890914638817631063334447389979640757204083936351078274058192000

1

APL (Dyalog Unicode) , 15 12 байт

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

Попробуйте онлайн!

Неявная функция, принимающая единственный аргумент . Сохраняет байт, удаляя, если нам разрешено сначала печатать знаменатель.

Спасибо @dzaima за 3 байта.

Как:

⌽!(,÷∨)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.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.