숫자의 연속 분수의 두 배


21

당신의 작업은 xoutput 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 아니요, 정수, 접두사 및 반복 부분을 기준으로하지 않고 입력 만 지정할 수 있어야합니다 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])?
피터 테일러

답변:


7

Wolfram Language (Mathematica) , 44 바이트

ContinuedFraction[2FromContinuedFraction@#]&

온라인으로 사용해보십시오!

Mathematica는 내장되어 있습니다! 예이! Mathematica의 내장은 매우 길다. 앗

Mathematica의 연속 분수는 다음과 같습니다 {integer, ...prefix, {...repeating}}

정환 민 덕분에 -1


4
*Mathematica의 기본 분리 문자가 없으면이이기 때문에 생략 할 수 Times있습니다.
JungHwan Min

3
귀하의 언어에 글자 맞추기 점수 부터 염소 인식 까지 모든 것이 내장되어 있으면 , 그 이름 중 일부는 필요에 따라 "매우 길어야"합니다. :)
sundar-복원 모니카

1
@sundar 아니요, Mathematica에는 ~ 5000 개의 빌트인 만 있습니다. 각 내장을 최대 2 바이트로 만들 수 있습니다 (Mthmtca 참조)
user202729

@ user202729 그러나 Mathematica는 그렇게한다면 그렇게 인기가 없었을 것입니다 : P
mbomb007

3

자바 스크립트 (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>.

골프 버전은 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.