Raddoppia la frazione continua di un numero


21

Il tuo compito è, dato x, output 2*x. Facile vero !? Ma c'è un problema: xverrà data come una frazione continua (forse infinita) e l'output deve essere una frazione continua. L'ingresso è garantito per essere un numero algebrico reale il cui grado è al massimo 2.

Input : la frazione continua di x. Questo è diviso in 3 parti: la parte intera, il prefisso e la parte ripetuta. La parte intera è costituita da un singolo numero intero. Il prefisso e la parte ripetuta sono matrici (possibilmente vuote) di numeri interi positivi che descrivono il prefisso e la parte ripetitiva della frazione continua. Ad esempio, l'input (3, [1], [2, 4])rappresenta la frazione continua [3; 1, 2, 4, 2, 4, ...].

Se la parte ripetuta è vuota, ciò indica un numero razionale. Ad esempio, (3, [1, 2], [])rappresenta [3; 1, 2] = 11/3. Devi accettare entrambe le forme di un numero razionale (cioè (3, [1, 1, 1], []), che [3; 1, 1, 1] = 11/3dovrebbe essere anche un input valido).

Output : emette la frazione continua del doppio dell'input, nello stesso formato dell'input. Se l'output è razionale, è possibile generare l'una o l'altra forma della frazione continua. Fintanto che la risposta equivale alla risposta corretta, va bene; non è necessaria alcuna "compressione", quindi la parte infinita potrebbe essere "srotolata" un po '(ad esempio, [1; 4, 2, 3, 2, 3...]può essere scritta (1, [4], [2, 3])o (1, [4, 2, 3], [2, 3])). Tutte le risposte devono essere esatte.

Casi di prova : la colonna del modulo esatto è indicata per comodità.

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])

E, infine, un banco di prova leggermente più grande per garantire la precisione: (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]).

Vince il codice più corto!

Suggerimento : è possibile eseguire l'aritmetica in modo piuttosto semplice sulle frazioni continue come descritto qui . Raddoppiare una frazione continua è solo un caso speciale di questo algoritmo (anche se la parte difficile potrebbe essere quella di trovare quando la frazione continua si ripete).



@Pavel No, devi essere in grado di specificare l'input esclusivamente sulla base di numeri interi, prefissi e parti ripetute anziché come Sqrt[2].
soktinpk,

Scusa, è stato un errore da parte mia. Ecco il link con l'attuale frazione continua come input: tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/…
Pavel

1
[3; 1, 1, 1]sarebbe (3, [1, 1, 1], [])nel formato di input che stiamo usando - quindi la domanda dovrebbe probabilmente menzionarlo in quel formato (nel terzo paragrafo), solo per garantire chiarezza.
Sundar - Ripristina Monica il

2
Quali sono i vincoli su quanto deve essere ridotto l'output? Ad esempio, sarebbe (-2, [1, 5, 2], [6, 2])un output accettabile per l'input (-1, [2], [2, 1])? Che ne dici (-2, [1, 5, 2, 6, 2, 6], [2, 6])?
Peter Taylor,

Risposte:


7

Wolfram Language (Mathematica) , 44 byte

ContinuedFraction[2FromContinuedFraction@#]&

Provalo online!

Mathematica ha incorporato! Sìì! L'incasso di Mathematica è molto lungo. Aww.

Le frazioni continue di Mathematica sembrano {integer, ...prefix, {...repeating}}

-1 grazie a JungHwan Min


4
Si potrebbe omettere il *perché il delimitatore predefinito di Mathematica, se non ce n'è uno, lo è Times.
JungHwan Min

3
Quando la tua lingua ha incorporato qualsiasi cosa, dal punteggio di Scrabble al riconoscimento di capra , alcuni dei loro nomi dovranno essere "super lunghi" per necessità. :)
Sundar - Ripristina Monica il

1
@sundar No, Mathematica ha solo ~ 5000 builtin. È possibile creare al massimo 2 byte incorporati (vedere Mthmtca)
user202729

@ user202729 Ma Mathematica non sarebbe stato così popolare se lo avesse fatto: P
mbomb007

3

JavaScript (ES6), 267 byte

(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]`)

Accetta 3 argomenti (n = parte intera, f = prefisso, r = parte ripetuta). Emette le tre parti in un array. Provalo online!

Spiegazione

È un'implementazione abbastanza diretta dell'algoritmo per il calcolo dell'aritmetica a frazione continua collegata alla sfida qui . I termini ricorrenti vengono gestiti archiviando matrici intermedie in una tabella di ricerca, aspettando un duplicato e producendo i termini fino alla successiva apparizione di quel duplicato. È inelegante e quasi raddoppia i byte necessari per gestire le frazioni continue, ma non riuscivo a pensare a un'alternativa migliore.

Il termine principale viene calcolato separatamente per garantire che le frazioni continue negative mantengano valori positivi per tutti i termini, escluso il primo.

Per evitare falsi positivi, quando in attesa di un ciclo ripetuto, i negozi tabella di ricerca i dati come segue: <index of input repeating part><delimiter><matrix values>.

Si noti che la versione golfizzata utilizza evalper salvare 1 byte.

(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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.