Знаменатель гармонических рядов


16

Ранее мы делали псевдофакториал числа, который является LCM чисел от 1до n.

Было бы полезно сложить дроби вместе.

Тем не менее, мы видим , что знаменатель 1/1 + 1/2 + 1/3 + 1/4 + 1/5 + 1/6является 20вместо pseudofactorial из 6, что 60.

Ваша задача - найти знаменатель 1/1 + 1/2 + ... + 1/nзаданного положительного целого числа n.

Testcases

 n result
 1 1
 2 2
 3 6
 4 12
 5 60
 6 20
 7 140
 8 280
 9 2520
10 2520
11 27720
12 27720
13 360360
14 360360
15 360360
16 720720
17 12252240
18 4084080
19 77597520
20 15519504
21 5173168
22 5173168
23 118982864
24 356948592
25 8923714800
26 8923714800
27 80313433200
28 80313433200
29 2329089562800
30 2329089562800

Ссылки

Leaderboard


Насколько большой вход должен работать?
Брэд Гилберт b2gills

@ BradGilbertb2gills Как большой, как это разумно.
Утренняя монахиня

Ответы:


8

М , 9 6 байт

Спасибо FryAmTheEggman за сохранение 3 байта! Код:

RİSg¹İ

У M здесь огромное преимущество, потому что он работает с дробями, а не с плавающей точкой. Объяснение:

R       # Get the list [1 ... n].
 İ      # Inverse each, resulting into [1/1, 1/2, 1/3, ..., 1/n].
  S     # Sum it up. (86021/27720 for n=12)
   g¹   # Compute the greatest common denominator with n. (1/27720 for n=12)
     İ  # Calculate the inverse again. (27720 for n=12)

Использует кодировку желе . Попробуйте онлайн! ,


Также существует 4-байтовое решение, которое иногда выводит начальный ноль (например 280 -> 0280). Я не уверен, разрешено это или нет:

RİSV

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


1
1. Объяснение 6-байтового кода не совсем корректно. вычисляет наибольший общий делитель дроби и n . Использование g1, вероятно, будет более понятным. 2. Vпреобразует дробь в строку и исчисляет ее до нуля. <num>/является (не кумулятивным) редукцией ниладическим оператором. Это бессмыслица, но поскольку существует только одно число (неявный аргумент 0 ), оно просто ничего не делает. Следующая ссылка, знаменатель, является niladic, поэтому предыдущее возвращаемое значение печатается неявно и заменяется этим nilad.
Деннис

@ Деннис Спасибо! Исправлено объяснение.
Аднан

@ Adnan Есть ли документация для М?
Esolanging Fruit

@ Challenger5 Не то, что я знаю. Это на самом деле вариант желе, но с произвольной точностью фракций. Документацию Jelly можно использовать, но следует помнить, что многие функции, реализованные в Jelly, не реализованы в M.
Adnan


4

Mathematica, 27 байт

Анонимная функция.

Denominator@*HarmonicNumber

Например:

 In[1] := (Denominator@*HarmonicNumber)[10]
 Out[1] = 2520

Вы можете найти 26-байтовое решение, если покопаетесь в чате :)
Leaky Nun

Ой! Я должен позволить Мартину опубликовать это, если ему нравится. Это восхитительно буквально, так что я буду держать его.
Линн

Не могли бы вы привести пример использования кода?
DavidC

3

Python 2, 69 67 байт

a=b=k=r=1
exec'a=a*k+b;b*=k;k+=1;'*input()
while r*a%b:r+=1
print r

Проверьте это на Ideone .

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

Пусть H (n) будет суммой мультипликативных инверсий первых n натуральных чисел. Мы всегда имеем, что a / b = 1 + H (k - 1) . Фактически, a , b и k все инициализируются в 1 , и 1/1 = 1 = 1 + H (0) .

Мы повторяем фрагмент кода

a=a*k+b;b*=k;k+=1;

(в виде строки) n (входных) раз и выполнить результат. На каждом шаге мы обновляем a , b и k, используя тождество a / b + 1 / k = ak / bk + b / bk = (ak + b) / bk .

После того, как все копии были выполнены, a / b = 1 + H (n) , который имеет тот же знаменатель, что и H (n) .

Полностью сокращенная форма a / b имеет вид (a ÷ gcd (a, b)) / (b ÷ gcd (a, b)) . Вместо того, чтобы вычислять наибольший общий делитель, мы инициализируем r как 1 и продолжаем увеличивать r, пока ra не будет кратно b .

Ясно, что это делает ra наименьшим общим множителем a и b . Поскольку gcd (a, b) · lcm (a, b) = ab , мы имеем, что b ÷ gcd (a, b) = lcm (a, b) ÷ a = ra ÷ a = r , что делает r желаемым выходом.


3

Хаскелл, 52

Import Data.Ratio
f n=denominator$sum[1%k|k<-[1..n]]

Если файл загружен в GHCI, f может использоваться как функция.


1
Предположительно вы имеете в виду importстрочные? Это сохраняет байт, чтобы использовать mapвместо понимания:sum$map(1%)[1..n]
xnor


2

MATL , 14 13 байт

:p:G:!/s1\&X<

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

объяснение

Для входа N выход ограничен сверху N ! (факториал N ). Код вычисляет n / k для n = 1, ..., N ! и к = 1, ..., N . Затем он суммирует по k , что дает номер гармоники, умноженный на каждое n . Желаемый результат - индекс n первого из тех значений, который является целым числом.


2

Рубин, 57 47 байт

->n{(1..n).reduce{|a,i|a+1.to_r/i}.denominator}

Спасибо Кевину Лау за сокращение его на десять байтов.


Присвойте переменную 1.to_rтак, чтобы вам не нужно было вводить строки и преобразовывать их. Кроме того, поскольку Ruby по умолчанию для for reduceиспользует первый элемент в качестве начального, и 1/1=1вам не нужно специально устанавливать 0в качестве начального значения.
Value Ink

2

Mathematica, 26 байтов

Denominator@Tr[1/Range@#]&

Безымянная функция, принимающая в nкачестве входных данных и возвращающая знаменатель. Использует стандартный прием злоупотребления Tr(трассировки) для суммирования списка взаимных ссылок.


1

JavaScript (ES6), 88 байт

m=>{for(d=1,i=0;i<m;d*=++i);for(n=i=0;i<m;n+=d/++i);for(g=d;g;[g,n]=[n%g,g]);return d/n}

Работает только до m = 20 из-за ограничений числовой точности JavaScript.


1

05AB1E , 8 байтов

Код:

!йL/O¿/

Объяснение:

!         # Take the factorial of the input.
 Ð        # Triplicate this.
  ¹L      # Get the list [1 ... input].
    /O    # Divide and sum up.
      ¿   # Get the GCD of the sum and the factorial.
       /  # Divide the factorial by this.

Могут быть некоторые проблемы с точностью для n> 19 из-за деления Python ... Использует CP-1252 кодировку .

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



0

J, 20 байт

(!%!+.[:+/!%1+i.)@x:

На основе подхода, используемого @ Линн решения .

Если точность не требуется для больших значений n или если мы можем предположить, что n будет передано как расширенное целое число с суффиксом x, можно использовать более короткое решение для 15 байтов .

!%!+.[:+/!%1+i.

использование

   f =: (!%!+.[:+/!%1+i.)@x:
   f 30
2329089562800
   (,:f"0) >: i. 15
1 2 3  4  5  6   7   8    9   10    11    12     13     14     15
1 2 6 12 60 20 140 280 2520 2520 27720 27720 360360 360360 360360

объяснение

(!%!+.[:+/!%1+i.)@x:  Input: n
                  x:  Convert n into an extended integer
              i.      Creates the range [0, 1, ..., n-1]
            1+        Add one to each, range is now [1, 2, ..., n]
          !           Get factorial of n
           %          Divide n! by each value in the range [1, 2, ..., n]
      [:+/            Sum those values
   !                  Get n!
    +.                Get gcd between n! and the sum
 !                    Get n!
  %                   Divide n! by the gcd and return

0

Perl 6 ,  36  32 байта

{([+] 1.FatRat X/1..$_).denominator}
{([+] 1.FatRat X/1..$_).nude[1]}

Объяснение:

{
  (
    [+]        # reduce with &infix:<+>

      # the following produces a Seq of Rational numbers
      # 1/1, 1/2, 1/3 ... 1/n

      1.FatRat # FatRat.new: 1,1
      X/       # crossed using &infix:</>
      1 .. $_  # Range from 1 to the input inclusive

  ) # resulting in a FatRat

  .nude # (nu)merator (de)nominator
  .[1]  # grab the denominator
}

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

my &hd = {([+] 1.FatRat X/1..$_).nude[1]}

say (1..10)».&hd; # (1 2 6 12 60 20 140 280 2520 2520)

say hd 100; # 2788815009188499086581352357412492142272
say chars hd 1000; # 433
say chars hd 10000; # 4345

0

Хун , 95 байт

|=
@
=+
n=(gulf 1 +<)
=+
f=(roll n mul)
(div f d:(egcd f (roll (turn n |=(@ (div f +<))) add)))

Создать список [1...n], свернуть его с ++mulпомощью факториала, создать список[n!/1, n!/2, ... n!/n] и суммируйте его, найдите GCD n!и список и разделите факториал на это число.

Вероятно, есть гораздо более простой способ вычислить знаменатель, но я не могу понять это: /


О, Хон, зачем вашему токенизатору нужно так много лишних пробелов?
Утренняя монахиня

Все мои записи Hoon выглядят безобразно из-за новых строк :( Обычный код Hoon использует два пробела между токенами, но одна новая строка короче
RenderSettings

0

Python 3, 153 150 146 142 байта

Я уверен, что это может сыграть в гольф дальше. Но я новичок здесь

f=lambda x:0**x or x*f(x-1)
z=int(input());i=f(z)
r=sum(i/y for y in range(1,z+1))  
p=lambda a,b:a if b<1else not a%b+b or p(b,a%b)
print(i/p(r,i))

Добро пожаловать в PPCG!
Утренняя монахиня

0

Аксиома, 34 байта

f(x)==denominator(sum(1/n,n=1..x))

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

(24) -> [[i,f(i)] for i in 1..30]
   (24)
   [[1,1], [2,2], [3,6], [4,12], [5,60], [6,20], [7,140], [8,280], [9,2520],
    [10,2520], [11,27720], [12,27720], [13,360360], [14,360360], [15,360360],
    [16,720720], [17,12252240], [18,4084080], [19,77597520], [20,15519504],
    [21,5173168], [22,5173168], [23,118982864], [24,356948592],
    [25,8923714800], [26,8923714800], [27,80313433200], [28,80313433200],
    [29,2329089562800], [30,2329089562800]]
                                       Type: List List Expression Integer

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.