Double la fraction continue d'un nombre

21

Votre tâche est, donnée x, sortie 2*x. Facile à droite!? Mais il y a un hic: xsera donné comme une fraction continue (éventuellement infinie) , et la sortie doit être une fraction continue. L'entrée est garantie comme un vrai nombre algébrique dont le degré est au plus 2.

Entrée : la fraction continue de x. Il est divisé en 3 parties: la partie entière, le préfixe et la partie répétitive. La partie entière est constituée d'un seul entier. Le préfixe et la partie répétitive sont des tableaux (éventuellement vides) d'entiers positifs qui décrivent le préfixe et la partie répétitive de la fraction continue. Par exemple, l'entrée (3, [1], [2, 4])représente la fraction continue [3; 1, 2, 4, 2, 4, ...].

Si la partie répétitive est vide, cela indique un nombre rationnel. Par exemple, (3, [1, 2], [])représente [3; 1, 2] = 11/3. Vous devez accepter les deux formes d'un nombre rationnel (c'est (3, [1, 1, 1], [])-à- dire qui [3; 1, 1, 1] = 11/3doit également être une entrée valide).

Sortie : Sortie la fraction continue de deux fois l'entrée, dans le même format que l'entrée. Si la sortie est rationnelle, vous pouvez sortir l'une ou l'autre forme de la fraction continue. Tant que la réponse est équivalente à la bonne réponse, c'est très bien; aucune "compression" n'est nécessaire, donc la partie infinie peut être "déroulée" un peu (par exemple [1; 4, 2, 3, 2, 3...]peut être écrite (1, [4], [2, 3])ou (1, [4, 2, 3], [2, 3])). Toutes les réponses doivent être exactes.

Cas de test : La colonne de formulaire exacte est donnée pour plus de commodité.

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

Et enfin un test un peu plus grande pour assurer une précision: (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]).

Le code le plus court gagne!

Astuce : Vous pouvez effectuer l'arithmétique d'une manière plutôt simple sur des fractions continues comme décrit ici . Le doublement d'une fraction continue n'est qu'un cas particulier de cet algorithme (bien que la partie la plus délicate puisse être de trouver quand la fraction continue se répète).

soktinpk
la source
@Pavel Non, vous devez pouvoir spécifier l'entrée uniquement en fonction de l'entier, du préfixe et des parties répétitives plutôt qu'en tant que Sqrt[2].
soktinpk
Désolé, c'était une erreur de ma part. Voici le lien avec la fraction continue réelle en entrée: tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/…
Pavel
1
[3; 1, 1, 1]serait (3, [1, 1, 1], [])dans le format d'entrée que nous utilisons - donc la question devrait probablement le mentionner dans ce format (dans le troisième paragraphe), juste pour assurer la clarté.
Sundar
2
Quelles contraintes existe-t-il sur la façon dont la sortie doit être minimisée? Par exemple, serait (-2, [1, 5, 2], [6, 2])une sortie acceptable pour l'entrée (-1, [2], [2, 1])? Et alors (-2, [1, 5, 2, 6, 2, 6], [2, 6])?
Peter Taylor

Réponses:

7

Wolfram Language (Mathematica) , 44 octets

ContinuedFraction[2FromContinuedFraction@#]&

Essayez-le en ligne!

Mathematica a une fonction intégrée! Yay! La fonction intégrée de Mathematica est super longue. Aww.

Les fractions continues de Mathematica ressemblent {integer, ...prefix, {...repeating}}

-1 merci à JungHwan Min

Pavel
la source
4
Vous pouvez omettre le *car le délimiteur par défaut de Mathematica, s'il n'y en a pas, l'est Times.
JungHwan Min
3
Lorsque votre langue est intégrée à tout, de la notation Scrabble à la reconnaissance de chèvre , certains de leurs noms devront être "super longs" par nécessité. :)
sundar - Réintégrer Monica
1
@sundar Non, Mathematica ne dispose que d'environ 5000 éléments intégrés. Il est possible de faire chaque octet intégré au maximum 2 (voir Mthmtca)
user202729
@ user202729 Mais Mathematica n'aurait pas été aussi populaire s'il l'avait fait: P
mbomb007
3

JavaScript (ES6), 267 octets

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

Accepte 3 arguments (n = partie entière, f = préfixe, r = partie répétitive). Génère les trois parties dans un tableau. Essayez-le en ligne!

Explication

Il s'agit d'une implémentation assez directe de l'algorithme de calcul de l'arithmétique de fraction continue liée dans le défi ici . Les termes répétitifs sont gérés en stockant des matrices intermédiaires dans une table de recherche, en attendant un doublon et en sortant les termes jusqu'à la prochaine apparition de ce doublon. C'est inélégant et double presque les octets nécessaires pour gérer les fractions continues, mais je ne pouvais pas penser à une meilleure alternative.

Le terme principal est calculé séparément pour garantir que les fractions continues négatives conservent des valeurs positives pour tous les termes sauf le premier.

Pour éviter les faux positifs lors de l' attente d' un cycle répété, les magasins de table de recherche les données comme suit: <index of input repeating part><delimiter><matrix values>.

Notez que la version golfée permet evald'économiser 1 octet.

(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
}
redondance
la source