Duplica la fracción continua de un número

21

Su tarea es, dada x, salida 2*x. Fácil, ¿verdad? Pero hay una trampa: xse dará como una fracción continua (posiblemente infinita) , y la salida debe ser una fracción continua. Se garantiza que la entrada sea un número algebraico real cuyo grado sea como máximo 2.

Entrada : La fracción continua de x. Esto se divide en 3 partes: la parte entera, el prefijo y la parte repetitiva. La parte entera consiste en un solo entero. El prefijo y la parte repetitiva son matrices (posiblemente vacías) de enteros positivos que describen el prefijo y la parte repetitiva de la fracción continua. Por ejemplo, la entrada (3, [1], [2, 4])representa la fracción continua [3; 1, 2, 4, 2, 4, ...].

Si la parte que se repite está vacía, eso indica un número racional. Por ejemplo, (3, [1, 2], [])representa [3; 1, 2] = 11/3. Debe aceptar ambas formas de un número racional (es decir (3, [1, 1, 1], []), que [3; 1, 1, 1] = 11/3también debe ser una entrada válida).

Salida : genera la fracción continua del doble de la entrada, en el mismo formato que la entrada. Si el resultado es racional, puede generar cualquiera de las formas de la fracción continua. Mientras la respuesta sea equivalente a la respuesta correcta, está bien; no es necesaria la "compresión", por lo que la parte infinita podría estar "desenrollada" un poco (por ejemplo, [1; 4, 2, 3, 2, 3...]puede estar escrita (1, [4], [2, 3])o (1, [4, 2, 3], [2, 3])). Todas las respuestas deben ser exactas.

Casos de prueba : la columna de formulario exacto se proporciona por conveniencia.

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

Y finalmente un caso de prueba un poco más grande para asegurar la precisión: (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]).

¡El código más corto gana!

Sugerencia : puede realizar operaciones aritméticas de una manera bastante directa en fracciones continuas como se describe aquí . Duplicar una fracción continua es solo un caso especial de este algoritmo (aunque la parte difícil puede ser encontrar cuándo se repite la fracción continua).

soktinpk
fuente
@Pavel No, debe poder especificar la entrada únicamente en función del número entero, el prefijo y las partes repetidas en lugar de como Sqrt[2].
soktinpk
Lo siento, fue un error de mi parte. Aquí está el enlace con la fracción continua real como entrada: tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/…
Pavel
1
[3; 1, 1, 1]estaría (3, [1, 1, 1], [])en el formato de entrada que estamos usando, por lo que la pregunta probablemente debería mencionarlo en ese formato (en el tercer párrafo), solo para garantizar la claridad.
sundar
2
¿Qué restricciones hay sobre cuán minimizado debe ser el resultado? Por ejemplo, ¿ (-2, [1, 5, 2], [6, 2])sería una salida aceptable para la entrada (-1, [2], [2, 1])? ¿Qué tal (-2, [1, 5, 2, 6, 2, 6], [2, 6])?
Peter Taylor

Respuestas:

7

Wolfram Language (Mathematica) , 44 bytes

ContinuedFraction[2FromContinuedFraction@#]&

Pruébalo en línea!

Mathematica tiene un incorporado! ¡Hurra! La construcción de Mathematica es muy larga. Aww.

Las fracciones continuas de Mathematica se ven como {integer, ...prefix, {...repeating}}

-1 gracias a JungHwan Min

Pavel
fuente
44
Puede omitir el *porque el delimitador predeterminado de Mathematica, si no hay uno, es Times.
JungHwan Min
3
Cuando su idioma tiene funciones para todo, desde la puntuación de Scrabble hasta el reconocimiento de cabra , algunos de sus nombres tendrán que ser "super largos" por necesidad. :)
sundar - Restablecer Monica
1
@sundar No, Mathematica solo tiene ~ 5000 incorporados. Es posible hacer que cada uno de los bytes incorporados sea de 2 bytes como máximo (ver Mthmtca)
user202729
@ user202729 Pero Mathematica no habría sido tan popular si hiciera eso: P
mbomb007
3

JavaScript (ES6), 267 bytes

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

Acepta 3 argumentos (n = parte entera, f = prefijo, r = parte repetida). Emite las tres partes en una matriz. Pruébalo en línea!

Explicación

Es una implementación bastante directa del algoritmo para calcular aritmética de fracción continua vinculada en el desafío aquí . Los términos repetidos se manejan almacenando matrices intermedias en una tabla de búsqueda, esperando un duplicado y generando los términos hasta la próxima aparición de ese duplicado. Es poco elegante y casi duplica los bytes necesarios para manejar fracciones continuas, pero no puedo pensar en una mejor alternativa.

El término principal se calcula por separado para garantizar que las fracciones continuas negativas retengan valores positivos para todos los términos salvo el primero.

Para evitar falsos positivos cuando se espera un ciclo repetido, las tiendas de la tabla de conversión de los datos de la siguiente manera: <index of input repeating part><delimiter><matrix values>.

Tenga en cuenta que la versión de golf utiliza evalpara guardar 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
}
redundancia
fuente