简化连续分数


21

连续分数是迭代描述分数的表达式。它们可以用图形表示:

在此处输入图片说明

或者它们可以表示为值列表: [a0; a1, a2, a3, ... an]

挑战:

取一个基数:和一个分母值列表:并将连续分数简化为简化的有理分数:分别返回或打印分子和分母。a0[a1, a2, a3, ... an]

例子:

  • √19 : [4;2,1,3,1,2]: 170/39
  • ℯ: [1;0,1,1,2,1,1]: 19/7
  • π: [3;7,15,1,292,1]: 104348/33215
  • ϕ: [1;1,1,1,1,1]: 13/8

示例实现:(python)

def foo(base, sequence):
    numerator = 1
    denominator = sequence[-1]
    for d in sequence[-2::-1]:
        temp = denominator
        denominator = d * denominator + numerator
        numerator = temp
    return numerator + base * denominator, denominator

获奖情况:

最短的代码(以字节为单位):-没有内置插件可以解决整个问题-


您应该使这句话更清楚:“并将连续分数简化为单个分​​数”;除非您打算将表示结果的措辞2.002表示为2002/1000。从技术上讲,这是“单个分数”,您可能要说“最简单的形式是单个分数”。
魔术章鱼缸

@carusocomputing点..虽然我不会对2/4(或类似的)感到难过,因为它仍将多分数结构简化为一个分数
Aaron

嗯...我认为有办法利用这一点,但是对于13字节的golfscript答案,我可能必须使用MATL才能获胜。
Magic Octopus Urn

@carusocomputing我会说的...如果您能击败13字节的答案,那就太好了
Aaron

您可以使pi更早停止-355/113。
托尔比约恩Ravn的安徒生

Answers:


15

J,8 5字节

相同,但是使用了内置原理。

参数是{a0,a1,a2,a3,...}作为J个扩展精度有理数的列表。结果是作为J扩展精度有理数的分数。

(+%)/

(+%) 互惠的

/ 减少

在线尝试!

-3多亏了


如果将输入作为扩展整数列表,则可以节省3个字节。另外,您在解释中使用了APL划分。
英里

@miles谢谢。没有比这更接近内置禁令了。可惜的是,J没有像Dyalog APL的钩子组成字符
亚当

尝试J在线链接已损坏
Chiel 10 Brinke

@ChieltenBrinke谢谢。固定。
亚当

12

Haskell,37 36 18字节

foldr1$(.(1/)).(+)

该函数期望Haskell的Ratio类型作为输入。用法示例:

Prelude Data.Ratio> ( foldr1$(.(1/)).(+) )  [4%1,2,1,3,1,2] 
170 % 39

注意:Ratio输入列表(4%1)中的一个显式就足够了,类型系统指出其他类型也必须是Ratios。

编辑:@Lynn保存一个字节。谢谢!

编辑II:删除了import(请参阅有关meta的讨论)。


1
哦,很好的边缘情况。函数本身是多态的,因此不需要import。但是要调用它,您必须将Ratios 馈入它,而确实需要import。我应该import在字节数上添加还是不添加?
nimi

1
对于meta来说,这听起来像是个好问题。
Martin Ender

我从未使用过Haskell,因此如果我错了,请更正我,但是如果python等价于:from fractions import FractionFraction对象执行操作,则import语句也将被计入。
亚伦

..我们以前有过
nimi

@Aaron:问题是:函数的定义不需要导入,因为它是多态的。当您要调用它时,您需要提供Ratio只能通过构造的数字%,这需要导入。通常我们不为调用开销而计算字节数,仅针对函数本身。
nimi

11

GolfScript,13个字节

~]-1%{\-1?+}*

在线尝试!

是的,GolfScript的隐藏原理。:)

说明

GolfScript唯一的“官方”数字类型是整数。但是,取幂运算符不会将其结果转换为整数,并且方便地,Ruby(GolfScript的解释器的语言)中整数取幂的本机结果是一个有理数。因此,我们可以通过将东西提高到-1的幂来轻松获得分数。方便地,我们还是想互惠...

~]     # Evaluate input and wrap all a_i in a list.
-1%    # Reverse the list so that a_n is at the start and a_0 at the end.
{      # Fold... (apply this block to each element from a_n-1 down to a_0, with
       # the previous result on the stack)
  \    #   Swap previous result with current a_i.
  -1?  #   Raise previous result to the power of -1, computing its reciprocal
       #   as a rational number.
  +    #   Add a_i.
}*

11

Mathematica,23 22字节

Fold[#2+1/#&]@*Reverse

本质上是我的GolfScript答案的一部分。以下是一些替代方案:

对于24个字节,我们可以编写一个递归可变参数函数:

f@n_=n
n_~f~m__:=n+1/f@m

对于21个字节,我们甚至可以定义一个“变数运算符”,但是它的调用约定太奇怪了,以至于我不愿数一数:

±n_=n
n_ ±m__:=n+1/±m

您必须使用一系列输入值(例如±Sequence[3, 7, 15, 1, 292, 1]或)来调用它±##&[3, 7, 15, 1, 292, 1]

对于21个字节,也将内置(禁止):

FromContinuedFraction

10

LabVIEW,36个等效字节

使用OP的算法非常简单明了的实现。有没有更好的方法可以做到这一点?

在此处输入图片说明


5
您的电气工程学位正在显示。
魔术章鱼缸

1
@ijustlovemath道具,但是..... 相关
亚伦

是的,肯定是一种有争议的语言。我将LabVIEW视为程序员界的“我讨厌数学”。问题不在于数学本身,而是数学的教学方法(或者常常根本没有教学)。
ijustlovemath

6

Dyalog APL,10 个字节

甚至不使用内置原理。

以{a 0,a 1,a 2,a 3,...}作为参数,返回{denominator,numerator}。

1(,÷∨)+∘÷/

1(,÷∨) 1前置-除以GCD 1和

+∘÷ 互惠的

/ 减少

在线尝试APL!


6

Python 2,62个字节

a=d=0
b=c=1
for n in input():a,b=b,n*b+a;c,d=d,n*d+c
print b,d

不幸的是,它不像golfy(请参见@xnor 的答案以较短),但是它无需返回输入即可计算分数。这里使用了“魔表”的渐近方法-定的最后两个部分a/cb/d,下分数(n*b+a)/(n*c+d)

例如,对于pi:

          3    7    15     1      292        1

  0   1   3   22   333   355   103993   104348
  1   0   1    7   106   113    33102    33215

我们可以看到15*22 + 3 = 33315*7 + 1 = 1061*333 + 22 = 3551*106 + 7 = 113,等。


4

M,5个字节

Ṛİ+¥/

输入是值的列表,[a0, a1, ..., aN]并且输出有理数。

在线尝试!验证所有测试用例。

说明

Ṛİ+¥/  Input: list A
Ṛ      Reverse A
    /  Reduce A from left to right using
   ¥     A dyadic chain
 İ         Take the reciprocal of the left value
  +        Add the reciprocal to the right value
       Return and print implicitly

1
这是什么?一些新的果冻方言?
亚当

@miles实际上是9个字节,对不起:(
Aaron

@Adám这是Jelly的旧叉子,用于数学和符号学。这是它的Github回购
2016年

1
@Aaron M使用与Jelly 相同的代码页,并且可以对每个字符使用一个字节对其进行编码。
英里

@miles确定,已添加
亚当

4

Haskell,30个字节

foldr(\h(n,d)->(h*n+d,n))(1,0)

递归添加向外的每一层,更新n/dh+(1/(n/d)),等于h+d/n(h*n+d)/n。该分数存储为的元组(num,denom)(1,0)翻转的初始分数0/10


3

Python,50个字节

f=lambda l,n=1,d=0:l and f(l,l.pop()*n+d,n)or(n,d)

从列表末尾开始向后构建连续分数,n/d将最后一个元素的分数重复更新xn/d -> 1+1/(n/d) == (x*n+d)/n


3

 常见的Lisp,54岁

右手折叠有些冗长:

(lambda(s)(reduce(lambda(a r)(+(/ r)a))s :from-end t))

测验

PASS  NAME  ACTUAL               EXPECTED
===============================================
T     √19   170/39               170/39              
T     ℯ     19/7                 19/7                
T     π     104348/33215         104348/33215        
T     ϕ     13/8                 13/8                

2

朱莉娅(53字节)

这是我第一次使用Julia,如果我忽略了一个迭代器,可能会丢失更多字节,请告诉我。这是向不知道选择哪种语言以应对特定挑战的人的提示:https : //en.wikipedia.org/wiki/Rational_data_type

f(x,c)=(a=0;for b in x[end:-1:1];a=1//(b+a);end;a+c;)
  • 反转输入数组。
  • 用合理的划分遍历它。
  • 将c加到十进制结果中。

您可以通过定义运算符(例如)而不是函数来节省两个字节
Tasos Papastylianou

同样,将for循环更改一段时间并弹出:x∘c=(a=0;while x!=[];a=1//(pop!(x)+a);end;a+c;)
Tasos Papastylianou

1
25 :(x->foldr((x,y)->x+1//y,x)与Haskell解决方案相同)。用法:(x->foldr((x,y)->x+1//y,x))([4//1,2,1,3,1,2])
王凤阳

噢...反向折叠功能?那好美丽!我不值得为此而称赞,尽管哈哈。
魔术章鱼缸

2

Javascript(ES6),55个字节

s=>eval('for(F=[1,0];s+"";)F=[s.pop()*F[0]+F[1],F[0]]')

测试用例

var f =
s=>eval('for(F=[1,0];s+"";)F=[s.pop()*F[0]+F[1],F[0]]')

console.log(f([4, 2, 1, 3, 1, 2]));
console.log(f([1, 0, 1, 1, 2, 1, 1]));
console.log(f([3, 7, 15, 1, 292, 1]));
console.log(f([1, 1, 1, 1, 1, 1]));


2

CJam18 16字节

XUq~W%{2$*+\}/]p

在线口译员

XU                  Push 1 and 0 to the stack
  q~W%              Push input, eval and reverse it
      {     }/      For each n in the reversed input...
       2$             Copy numerator
         *+           Calculate n*denominator + numerator
           \          Swap numerator and denominator
              ]p   Wrap in array and output

2

05AB1E19 17字节

R¬V¦vyY*X+YUV}YX)

说明

输入为数字列表

                     # variable X is initialized as 1
R¬V¦                 # reverse the list, remove the first item and store it in variable Y
    v        }       # for each item N left in list
     yY*X+  V        # store N*Y+X in Y
          YU         # store Y in X
              YX)    # wrap X and Y in a list

在线尝试!


2

JavaScript(ES6),44个字节

a=>a.reduceRight(([n,d],v)=>[v*n+d,n],[1,0])

1

Javascript(ES6),50个字节

f=(s,n=1,d=s.pop())=>s+""?f(s,d,s.pop()*d+n):[d,n]

这要归功于Arnauld的回答,在看到它之前,我被固定为66个字节:

f=(b,s,i=s.length-1,n=1,d=s[i])=>i?f(b,s,--i,d,s[i]*d+n):[n+b*d,d]

示例:
呼叫:f([1, 0, 1, 1, 2, 1, 1])
输出:Array [ 19, 7 ]


1

Perl 6,24个字节

{[R[&(1/*+*)]](@_).nude}

说明:

  • 1 / * + *是具有两个参数(*)的lambda,它取第一个参数的倒数,然后加上第二个。(返回老鼠

  • R[&(…)]使用它,就好像它是一个中缀运算符并将其取反。
    (包括使其正确关联)

  • […](@_) 接受并使用它来减少输入。

  • … .nude返回NU merator和中的提名

  • { … }使它成为带有隐式参数的裸块lambda @_

用法:

say {[R[&(1/*+*)]](@_).nude}(3,7,15,1,292,1) #*/# (104348 33215)

my &code = {[R[&(1/*+*)]](@_).nude}; # stupid highlighter */

say code 4,2,1,3,1,2;    # (170 39)
say code 1,0,1,1,2,1,1;  # (19 7)
say code 1,1,1,1,1,1;    # (13 8)

1

和风,145字节

input n as Integer
set a to Array(n)
for i from 1to n
input a[i]as Integer
next
set r to a[n]
for i from 1to n-1
set r to(/r)+a[n-i]
next
print r

Zephyr是我创建的第一种编程语言。它被设计为直观且语法简洁-只是为了简洁起见。你问我为什么要打高尔夫球呢?因为,与我以后编写的任何语言不同,它具有内置Fraction类型。您甚至可以使用除法运算符/运算符用作“逆”(我为Pip借用的功能)的一元运算符。

现在,存在重大限制。此挑战的最大问题是必须以固定大小定义数组,这意味着程序首先从用户读取数组的大小开始。(我希望这样可以;替代方法是对大小进行硬编码。)还有一个小问题,即运算符优先级不存在,这意味着多运算符表达式必须带有括号。

这是一个示例运行:

C:\Zephyr> python zephyr.py contfrac.zeph
6
1
1
1
1
1
1
13/8

1

Ruby,34个字节

->a{a.reverse.inject{|b,i|i+1r/b}}

这将执行右折(先反转再折左),然后将每个元素加到运行总计(右元素)上的1。Ruby具有Rational类型,这非常好。字面有理数后缀为r


1

Stax,4 个字节

╣╩┼►

运行并调试

尽管很小,但它不是内置的。内置的原理虽然有很多帮助。程序解压缩为ascii rksu+

  1. 反转数组。
  2. 使用折叠数组(a, b) => (a + 1/b)

1

APL(NARS),15 + 1个字符,30 + 2个字节

{1=≢⍵:↑⍵⋄+∘÷/⍵}

来自Adam J solution的Apl(Nars)转换...该函数允许的输入将全部为整数列表,其中第一个元素为有理数类型。测试:

  f←{1=≢⍵:↑⍵⋄+∘÷/⍵}      
  f 4x 2 1 3 1 2
170r39 
  f 1x 0 1 1 2 1 1
19r7 
  f 3x 7 15 1 292 1
104348r33215 
  f 1x 1 1 1 1 1
13r8 
  f 3x 89 888 999 11 222 373 7282 9272 3839 2828 
158824716824887954093160207727r52744031585005490644982548907 
  f ,0x
0 
  f ,9x
9 

因此,函数长度为15个字符,“ x”为1个字符,用于输入所需的输入类型并退出所需的类型...

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.