Verdoppeln Sie den fortgesetzten Bruch einer Zahl

21

Ihre Aufgabe ist gegeben x, Ausgabe 2*x. Einfach richtig!? Aber es gibt einen Haken: xWird als (möglicherweise unendlicher) fortgesetzter Bruch angegeben , und die Ausgabe muss ein fortgesetzter Bruch sein. Die Eingabe ist garantiert eine echte algebraische Zahl, deren Grad höchstens 2 beträgt.

Eingabe : Der fortgesetzte Bruchteil von x. Dies ist in drei Teile unterteilt: den ganzzahligen Teil, das Präfix und den sich wiederholenden Teil. Der ganzzahlige Teil besteht aus einer einzelnen ganzen Zahl. Das Präfix und der Wiederholungsteil sind (möglicherweise leere) Arrays positiver Ganzzahlen, die das Präfix und den Wiederholungsteil des fortgesetzten Bruchs beschreiben. Beispielsweise (3, [1], [2, 4])repräsentiert die Eingabe den fortgesetzten Bruch [3; 1, 2, 4, 2, 4, ...].

Wenn der Wiederholungsteil leer ist, gibt dies eine rationale Zahl an. Zum Beispiel (3, [1, 2], [])repräsentiert [3; 1, 2] = 11/3. Sie müssen beide Formen einer rationalen Zahl akzeptieren (dh (3, [1, 1, 1], [])die muss [3; 1, 1, 1] = 11/3auch eine gültige Eingabe sein).

Ausgabe : Gibt den fortgesetzten Bruchteil der doppelten Eingabe im gleichen Format wie die Eingabe aus. Wenn die Ausgabe rational ist, können Sie jede Form des fortgesetzten Bruchs ausgeben. Solange die Antwort der richtigen entspricht, ist sie in Ordnung. es ist keine "Komprimierung" erforderlich, so dass der unendliche Teil möglicherweise ein wenig "abgerollt" wird (z. B. [1; 4, 2, 3, 2, 3...]geschrieben (1, [4], [2, 3])oder (1, [4, 2, 3], [2, 3])). Alle Antworten müssen exakt sein.

Testfälle : Der Einfachheit halber wird die genaue Formularspalte angegeben.

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

Und schließlich ein etwas größerer Testfall Präzision zu gewährleisten: (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]).

Kürzester Code gewinnt!

Tipp : Sie können mit fortlaufenden Brüchen, wie hier beschrieben, auf einfache Weise rechnen . Das Verdoppeln eines fortgesetzten Bruchs ist nur ein Sonderfall dieses Algorithmus (obwohl es schwierig sein kann, herauszufinden, wann sich der fortgesetzte Bruch wiederholt).

soktinpk
quelle
@Pavel Nein, Sie müssen in der Lage sein, die Eingabe ausschließlich auf der Grundlage der Ganzzahl, des Präfix und der sich wiederholenden Teile und nicht als anzugeben Sqrt[2].
Soktinpk
Entschuldigung, das war ein Fehler von meiner Seite. Hier ist der Link mit dem tatsächlichen Kettenbruch als Eingang: tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/...
Pavel
1
[3; 1, 1, 1]würde (3, [1, 1, 1], [])in dem Eingabeformat sein, das wir verwenden - daher sollte die Frage es wahrscheinlich in diesem Format erwähnen (im dritten Absatz), nur um Klarheit zu gewährleisten.
Sundar - Reinstate Monica
2
Welche Einschränkungen bestehen hinsichtlich der Minimierung der Ausgabe? Wäre zB (-2, [1, 5, 2], [6, 2])eine akzeptable Ausgabe für die Eingabe (-1, [2], [2, 1])? Wie wäre es (-2, [1, 5, 2, 6, 2, 6], [2, 6])?
Peter Taylor

Antworten:

7

Wolfram-Sprache (Mathematica) , 44 Byte

ContinuedFraction[2FromContinuedFraction@#]&

Probieren Sie es online!

Mathematica hat eine eingebaute! Yay! Die eingebaute Mathematica ist super lang. Aww.

Die fortgesetzten Brüche von Mathematica sehen aus wie {integer, ...prefix, {...repeating}}

-1 dank JungHwan Min

Pavel
quelle
4
Sie können *das Standardtrennzeichen von Mathematica weglassen , wenn es keines gibt Times.
JungHwan Min
3
Wenn Sie Ihre Sprache builtins für alles von hat Scrabble - Scoring zu Goat Anerkennung , werden einige ihrer Namen haben „Super - long“ von Notwendigkeit. :)
Sundar - Reinstate Monica
1
@ Sundar Nein, Mathematica hat nur ~ 5000 eingebaute Funktionen. Es ist möglich, jede eingebaute 2 Bytes (siehe Mthmtca) zu machen
user202729
@ user202729 Aber Mathematica wäre nicht so beliebt gewesen, wenn es das getan hätte: 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]`)

Akzeptiert 3 Argumente (n = ganzzahliger Teil, f = Präfix, r = sich wiederholender Teil). Gibt die drei Teile in einem Array aus.Probieren Sie es online!

Erläuterung

Es ist eine ziemlich direkte Implementierung des Algorithmus zum Berechnen der fortgesetzten Brucharithmetik, die in der Herausforderung hier verknüpft ist . Wiederholende Terme werden behandelt, indem Zwischenmatrizen in einer Nachschlagetabelle gespeichert werden, auf ein Duplikat gewartet wird und die Terme bis zum nächsten Auftreten dieses Duplikats ausgegeben werden. Es ist unelegant und verdoppelt fast die Bytes, die benötigt werden, um fortgesetzte Brüche zu verarbeiten, aber ich könnte mir keine bessere Alternative vorstellen.

Der führende Term wird separat berechnet, um sicherzustellen, dass negative fortgesetzte Brüche positive Werte für alle Terms behalten, mit Ausnahme des ersten.

Um Fehlalarme beim Warten auf einen wiederholten Zyklus zu vermeiden, werden die Daten in der Nachschlagetabelle wie folgt gespeichert: <index of input repeating part><delimiter><matrix values> .

Beachten Sie, dass die Golf-Version verwendet eval, um 1 Byte zu sparen.

(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
}
Redundanz
quelle