调和数列的精确部分和


15

挑战

给定一个正整数N,输出第一个N倒数的总和作为精确的分数,将其表示为一对整数,以一致的顺序表示分子和分母。

规则

  • 输出必须准确。

  • 输出应为一对整数,以一致的顺序表示分子和分母。

  • 禁止使用非整数数字类型(内置或库)。

    • 澄清/例外:当且仅当使用,计算和返回的所有值都是整数时,非整数数字类型才可以(例如,您的语言默认使用有理数,但您的答案中仅使用整数算术)
  • 输出应尽可能减少。(3/2还可以,6/4不是)

  • 禁止出现标准漏洞

  • 提交的内容至少应输入20个或此meta,以较高者为准。

测试用例

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如果您的语言提供的话,是“内置功能”吗?
Chas Brown

@ChasBrown gcd和其他内置函数很好。不允许使用有理/小数类型。
pizzapant184 '18

1
@JoKing如果数字是有理数,只要只使用整数,就可以了。我将更新问题。
pizzapant184 '18

Answers:


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!

然后,在累加器中考虑正数的递归: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

我们必须通过while循环中的GCD计算来支付减分数吹打器;然后我们完成了。


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的Python answer

aba=0b=1个

一种一种ñ+bbbñññ-1个

ñ=0

一种bpq一种光盘一种b

一种bb一种b

b=0

p/一种q/一种


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

要求:

  • gcc不推荐使用的import语句。
  • gcc的std::__gcd
  • -O0(我认为是这样),否则编译器将进行优化d/=a
  • 至少64位long

说明:

  • d=ñ一种=Hñ
  • 回合a*d由铸造最接近的整数a*d+.5long分配,和n。现在n/d是输出。
  • 用简化分数std::__gcd

您不能使用auto a=0.代替double a=0(少1个字符)吗?
Dan M.

是的,他可以。循环中还有一个字节:106个字节
movatica


2

MATL,13个字节

:tptb/sht&Zd/

在MATL Online上尝试

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

(隐式输出,先打印分母,然后打印分子。)

浮点数错误意味着这对于n = 20不起作用,因为中间值太大。看起来测试用例输出是一个错字,对于n = 20,它返回的答案与其他答案相同。

这是在发现之前我尝试过的整数类型保留版本(25字节):

25个字节,最多输入43

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

在线尝试!

将数字转换为,uint64然后再对其进行运算,并在循环中显式地执行算术运算(不使用prodsum)。更重要的是,在每次迭代的最后,将部分分子和分母除以GCD的每一步。这样可以增加输入范围,n最多允许43个输入。部分代码基于@Chas Brown的Python答案。

使用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)

取消评论

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

Stax,11 个字节

ó╢Δ'åç4}ú┌7

运行并调试

说明:

我们要计算:

一世=1个ñ1个一世

现在我们需要一个分母 b 和分子列表 一种一世

一世=1个ñ一种一世b=一世=1个ñ一种一世b

我们可以做 b=ñ,那么我们有:

一种一世ñ=1个一世|×ñ一种一世=ñ一世

因此,我们有:

一世=1个ñ1个ñ=一世=1个ññ一世ñ
|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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.