将数字的连续分数加倍


21

给定您的任务x,输出2*x。容易吧!!但是有一个陷阱:x将作为(可能是无限的)连续分数给出,并且输出必须是连续分数。确保输入为实数代数,其次数最多为2。

输入:的连续分数x。这分为三部分:整数部分,前缀和重复部分。整数部分由一个整数组成。前缀和重复部分是(可能为空)正整数数组,用于描述连续分数的前缀和重复部分。例如,输入(3, [1], [2, 4])表示连续分数[3; 1, 2, 4, 2, 4, ...]

如果重复部分为空,则表示有理数。例如,(3, [1, 2], [])代表[3; 1, 2] = 11/3。您必须接受两种形式的有理数(即(3, [1, 1, 1], []),也[3; 1, 1, 1] = 11/3应该是有效的输入)。

输出:以与输入相同的格式输出输入两倍的连续分数。如果输出是合理的,则可以输出连续分数的任何一种形式。只要答案等同于正确答案,就可以了。不需要“压缩”,因此无限部分可能会“展开”一点(例如,[1; 4, 2, 3, 2, 3...]可能是书写的(1, [4], [2, 3])(1, [4, 2, 3], [2, 3]))。所有答案必须准确。

测试用例:为方便起见,给出了准确的表格列。

Input               Exact Form       Output
(0, [] [])          0                (0, [] []) or (-1, [1], [])
(-5, [1, 1], [])    -4.5             (-9, [], []) or (-10, [1], [])
(3, [1, 2], [])     11/3             (7, [3], []) or (7, [2, 1], [])
(1, [], [2])        sqrt(2)          (2, [], [1, 4])
(-1, [2], [2, 1])   -1/sqrt(3)       (-2, [1, 5], [2, 6])

最后一个稍大的测试案例,以确保精度:(0, [1], [6, 1, 3, 1, 42, 1, 3, 1, 6, 2]) --> (1, [], [1, 2, 1, 8, 1, 20, 1, 8, 1, 2, 1, 2])

最短的代码胜出!

提示:您可以按照此处描述的那样对连续分数以一种非常直接的方式执行算术运算。将连续分数加倍只是该算法的一种特殊情况(尽管棘手的部分可能是要找到连续分数何时重复)。



@Pavel不,您必须只能基于整数,前缀和重复部分而不是as来指定输入Sqrt[2]
soktinpk

抱歉,这是我的错误。这是实际连续分数作为输入的链接:tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/…
Pavel

1
[3; 1, 1, 1]会采用(3, [1, 1, 1], [])我们正在使用的输入格式-因此问题可能应该以该格式(在第三段中)提及,以确保清晰度。
sundar-恢复莫妮卡

2
对输出必须如何最小化有什么限制?例如(-2, [1, 5, 2], [6, 2]),输入可接受的输出(-1, [2], [2, 1])?怎么(-2, [1, 5, 2, 6, 2, 6], [2, 6])
彼得·泰勒

Answers:


7

Wolfram语言(Mathematica),44字节

ContinuedFraction[2FromContinuedFraction@#]&

在线尝试!

Mathematica具有内置功能!好极了!Mathematica的内置函数非常长。w

Mathematica的连续分数看起来像 {integer, ...prefix, {...repeating}}

-1感谢郑焕敏


4
您可以省略,*因为Mathematica的默认定界符(如果没有)为Times
JungHwan Min '18

3
当您的语言内置了从拼字游戏评分山羊识别等所有功能的语言时,其中的某些名称必然会变得“超长”。:)
sundar-恢复莫妮卡

1
@sundar不,Mathematica只有约5000个内置函数。最多可以使每个内置2个字节(请参阅Mthmtca)
user202729 '18

@ user202729但是Mathematica不会那么受欢迎:P
mbomb007 '18

3

JavaScript(ES6),267字节

(n,f,r)=>eval(`f=[0,...f];e=i=[0,2,1,0];o=j=[];k=[];m={};while([a,b,c,d]=e,c|d&&o)i*m[s=i+m+(e=c*d&&(q=a/c|0)==(b/d|0)?(o.push(q),[c,d,a-c*q,b-d*q]):1/(++i,[p,...f]=f+f?f:(i=r[0],r),p)?[b,a+b*p,d,c+d*p]:[b,b,d,d])]?k+(o=k)?o=0:(m={})[s]=1:m[s]=1;[2*n+j.shift(),j,k]`)

接受3个参数(n =整数部分,f =前缀,r =重复部分)。将三个部分输出为数组。在线尝试!

说明

它是用于计算的挑战联连分数算法相当直接执行算法在这里。通过将中间矩阵存储在查找表中,等待重复项并输出条件直到该重复项的下一次出现,来处理重复项。它不雅致,将处理连续分数所需的字节几乎增加了一倍,但我想不到更好的选择。

前导项是单独计算的,以确保除第一个项外的所有项的负连续分数保持正值。

为了防止在等待重复周期时出现误报,查找表按如下方式存储数据:<index of input repeating part><delimiter><matrix values>

请注意,打高尔夫球的版本用于eval保存1个字节。

(n, f, r) => {
    f = [0, ...f];                       // use a 0 to chop off the integer part
    e = i = [0,2,1,0];                   // e: matrix with starting values to handle doubling
                                         // 0 + 2x
                                         // ------
                                         // 1 + 0x
                                         // i: tracks index of repeating part; until the function loops through the
                                         // repeating part, i is equivalent to NaN
    o = j = [];                          // o: alias for group of terms currently being computed
                                         // j: output array of non-repeating terms
    k = [];                              // k: output array of repeating terms
    m = {};                              // lookup table
    while ([a,b,c,d] = e, c | d && o)    // destructure matrix
                                         // c | d stops loop if both a/c and b/d equal infinity
        i * m[s = i + m + (              // m also serves as the delimiter; JS will stringify it as "[object Object]"
                                         // if i equals a value that is coerced to NaN, this multiplication
                                         // will be falsy
            e = c * d && (q=a/c|0) == (b/d|0) // checks if either c or d is 0 to avoid converting an Infinity value to 0 using the bitwise or
                ? (o.push(q), [c, d, a - c*q, b - d*q]) // append the output term and compute the new matrix
                : 1/(++i, [p, ...f] = f+f ? f : (i=r[0], r), p) // 1/(... p) checks if p is a valid number
                                         // f+f is a short way to check length of f; if f is an empty
                                         // array, f+f = '' (which is falsy)
                                         // if f is empty, try to replace with r
                                         // if r is empty, the value of i will be set to undefined (e.g. NaN)
                    ? [b, a + b*p, d, c + d*p]
                    : [b,b,d,d]
            )
        ]                                // checks if matrix has been cached in lookup table
            ? k+(o=k)                    // if the repeating part of the output has a value...
                ? o=0                    // o serves as a flag to halt the loop
                : (m={})[s] = 1          // reset lookup table to only hold the first duplicate matrix
            : m[s] = 1;                  // otherwise flag a matrix as seen
    return [2*n + j.shift(), j, k]       // add the doubled integer part to the first term
}
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.