数の連続分数を2倍にする


21

与えられたタスクはxoutput 2*xです。簡単ですよね!?しかし、キャッチxがあります:(おそらく無限の)継続分数として与えられ、出力は継続分数でなければなりません。入力は、次数が最大2の実代数になることが保証されています。

入力x。これは、整数部分、プレフィックス、および繰り返し部分の3つの部分に分割されます。整数部分は単一の整数で構成されます。プレフィックスと繰り返し部分は、連続した分数のプレフィックスと繰り返し部分を記述する正の整数の配列(空の場合もあります)です。たとえば、入力(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も有効な入力である必要があります)。

出力:入力と同じ形式で、入力の2倍の連続した部分を出力します。出力が合理的であれば、どちらの形式の連続分数も出力できます。答えが正解と同等である限り、それは問題ありません。「圧縮」は必要ないので、無限部分は少し「展開」される可能性が[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])

最短のコードが勝ちます!

ヒントここで説明するように、連続した分数に対してかなり簡単に算術演算を実行できます。継続分数を2倍にすることは、このアルゴリズムの特殊なケースにすぎません(ただし、継続分数が繰り返されるタイミングを見つけるのは難しい場合があります)。



@Pavelいいえ、としてではなく、整数、接頭辞、繰り返し部分のみに基づいて入力を指定できる必要がありますSqrt[2]
soktinpk

申し訳ありませんが、それは私の側の間違いでした。ここでは、入力として実際の連分数とのリンクがあります:tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/...
パベル

1
[3; 1, 1, 1]だろう(3, [1, 1, 1], [])、我々が使用している入力フォーマットに-質問はおそらく明確性を確保するために、(第3段落で)その形式でそれを言及する必要がありますので。
スンダ

2
出力を最小化する方法にはどのような制約がありますか?たとえば(-2, [1, 5, 2], [6, 2])、入力に対して許容可能な出力でしょう(-1, [2], [2, 1])か?どう(-2, [1, 5, 2, 6, 2, 6], [2, 6])
ピーターテイラー

回答:


7

Wolfram言語(Mathematica)、44バイト

ContinuedFraction[2FromContinuedFraction@#]&

オンラインでお試しください!

Mathematicaにはビルトインがあります!わーい!Mathematicaの組み込みは非常に長いです。ああ

Mathematicaの連続分数は次のようになります {integer, ...prefix, {...repeating}}

-1ジョンファンミンのおかげ


4
*Mathematicaのデフォルトの区切り文字は存在しない場合はなので、省略できますTimes
ジョンファンミン

3
スクラブルのスコアリングからヤギの認識まで、すべての言語に組み込み言語が組み込まれている場合、その名前の一部は必然的に「超長」である必要があります。:)
スンダ-復活モニカ

1
@sundarいいえ、Mathematicaには〜5000個のビルトインしかありません。各組み込みを最大で2バイトにすることができます(Mthmtcaを参照)
-user202729

@ user202729しかしMathematicaはそうするならそれほど人気が​​なかっただろう:P
mbomb007

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 =繰り返し部)。配列の3つの部分を出力します。オンラインでお試しください!

説明

ここでの課題にリンクされている連分数演算を計算するためのアルゴリズムのかなり直接的な実装です。繰り返し用語は、ルックアップテーブルに中間行列を格納し、複製を待って、その複製が次に現れるまで用語を出力することで処理されます。それは洗練されておらず、連続した小数部を処理するのに必要なバイト数がほぼ2倍になりますが、より良い代替案は考えられませんでした。

先行する項は、最初の項を除くすべての項で負の継続分数が正の値を保持するように、個別に計算されます。

繰り返しのサイクルを待つときに誤検知を防ぐため、ルックアップテーブルは次のようにデータを保存します<index of input repeating part><delimiter><matrix values>

ゴルフバージョンではeval1バイトの節約に使用されることに注意してください。

(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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.