Der Stern-Brocot-Baum ist ein binärer Baum von Brüchen, bei dem jeder Bruch durch Addition der Zähler und Nenner der beiden benachbarten Brüche in den obigen Ebenen erfasst wird.
Es wird erzeugt, indem mit 0/1
und 1/0
als "Endpunktbrüche" begonnen wird und von dort aus iteriert wird, indem ein Bruch zwischen jedes aufeinanderfolgende Bruchpaar gesetzt wird, indem die Zähler und Nenner dieser Brüche wie folgt addiert werden:
0. 0/1 1/0
1. 0/1 1/1 1/0
2. 0/1 1/2 1/1 2/1 1/0
3. 0/1 1/3 1/2 2/3 1/1 3/2 2/1 3/1 1/0
4. 0/1 1/4 1/3 2/5 1/2 3/5 2/3 3/4 1/1 4/3 3/2 5/3 2/1 5/2 3/1 4/1 1/0
In jeder Iteration des Stern-Brocot-Baums (der n
th-Iteration) gibt es 2^n + 1
Elemente in der Sequenz, denen wir einen Bruchteil von 0/2^n
bis zuordnen können 2^n/2^n
. Jede neue Iteration fügt einfach einen Bruch "auf halbem Weg" zwischen jedem Paar aufeinanderfolgender Brüche ein.
Dies macht den Stern-Brocot-Baum zu einer Eins-zu-Eins-Abbildung zwischen den positiven rationalen Zahlen und den binären Brüchen zwischen 0 und 1 und dient damit auch als Beweis dafür, dass die beiden Mengen dieselbe Kardinalität haben.
Ihre Aufgabe ist es, ein Programm oder eine Funktion zu schreiben, die unter Berücksichtigung des Zählers und Nenners einer positiven rationalen Zahl in niedrigsten Begriffen den binären Bruch bestimmt, der der Position dieses Bruchs im Stern-Brocot-Baum entspricht.
Beispiele für Ein- und Ausgänge finden Sie unten:
2/3 -> 3/8 (4th number in iteration 3)
4/7 -> 9/32 (between 1/2 and 3/5 in the chart above)
1/1 -> 1/2 (middle number in the first iteration)
Eingaben, die Sie nicht unterstützen müssen, die jedoch als Referenz dienen:
0/1 -> 0/1 (0/1 is considered the left number)
1/0 -> 1/1 (1/0 is considered the rightmost number)
Das kürzeste Programm in einer Sprache, um dieses Ziel zu erreichen, gewinnt.
1/1 => 1
,1/2 => 2
,2/1 => 3
,1/3 => 4
, etc.). Wenn die so erzeugte Zahl für einen Knoten istn
, dann ist2^lg n
(Binärprotokoll) das höchste gesetzte Bitn
, und der gewünschte Binärbruch ist(2*(n - 2^lg n) + 1) / 2^(lg n + 1)
. (Jeder, der versucht, eine Assembler-Lösung in einem Befehlssatz mit einem Get-Highest-Set-Bit zu versuchen, wird wahrscheinlich diesen Ansatz verwenden wollen.)Antworten:
GolfScript (
49 4846 Zeichen)oder
Beides sind Funktionen, die den Zähler und den Nenner auf dem Stapel nehmen und den Zähler und den Nenner auf dem Stapel belassen. Online-Demo .
Die Kernidee wird im Pseudocode in Abschnitt 4.5 der Konkreten Mathematik (S. 122 in meiner Ausgabe) ausgedrückt :
Wenn die Zeichenfolge von Ls und Rs als Binärwert mit L = 0 und R = 1 interpretiert wird, ist der doppelte Wert plus eins der Zähler, und der Nenner ist ein Bit länger.
Als ein Punkt von Interesse für Golfscripters ist dies eine der seltenen Gelegenheiten, in denen ich die Entfaltung als nützlich empfunden habe. (Ok, ich benutze es nur als Schleifenzähler, aber das ist besser als nichts).
quelle
Mathematica,
130 114111 ZeichenBeispiel:
quelle
Ruby,
132125Rubied & Golfed die Referenzlösung von @JoeZ.
Anwendungsbeispiele:
quelle
Ruby (69 Zeichen)CoffeeScript (59 Zeichen)Dies ist eine Funktion, die Zähler und Nenner als Argumente verwendet und nach der Bijektion ein Array zurückgibt, das Zähler und Nenner enthält.
Online-Demo
Es verwendet den gleichen Ansatz wie meine GolfScript-Lösung oben, ist jedoch viel besser lesbar, da ich 4 Variablen verwenden kann, ohne mich um das Ein- und Auspacken in ein Array kümmern zu müssen. Ich habe mich für CoffeeScript entschieden, weil es Variablen keine Präfixe mit
$
(20 Zeichen, die über z. B. PHP gespeichert wurden) voranstellt , eine kurze Funktionsdefinitionssyntax hat, die Standardparameterwerte zulässt (es ist also nicht erforderlich,f(a,b,x,y)
eine Funktiong(a,b) = f(a,b,0,1)
einzuschließen), und ich Boolesche Werte als Ganzzahlen verwenden kann Ausdrücke mit nützlichen Werten. Für diejenigen, die es nicht wissen, hat CoffeeScript nicht den ternären Standardoperator im C-Stil (C?P:Q
), aber ich kann ihnC&&P||Q
hier ersetzen , weilP
niemals falsch sein wird.Eine wohl elegantere, aber unbestreitbar weniger kurze Alternative besteht darin, die wiederholte Subtraktion durch Division und Modulo zu ersetzen:
(65 Zeichen; Online-Demo ). Wenn Sie es so schreiben, wird die Beziehung zum Euklid-Algorithmus sichtbar.
quelle
a<b
die Sie ein Zeichen sparen. Inliningc
gibt zwei weitere. Sie können auch die Syntaxf=->a,b,x=0,y=1{...}
für eine noch kürzere Definition berücksichtigen .c=a<b ?
mit einem zusätzlichen Platz danachb
. Andernfalls wird das Fragezeichen als Teil des behandeltb
.Python - 531
Eine ungolfed Lösung in Python, um als Referenzlösung für den letzten Platz zu dienen:
Es wird einfach eine binäre Suche zwischen Brüchen durchgeführt, wobei die Tatsache ausgenutzt wird , dass der Mediant von zwei beliebigen Brüchen immer zwischen den Werten dieser beiden Brüche liegt.
quelle
GolfScript, 54 Zeichen
Die Eingabe muss auf STDIN in der in der Aufgabe angegebenen Form erfolgen. Sie können den Code online ausprobieren .
quelle
Mathematica 138
Nicht so rational wie das Verfahren von alephalpha, aber es war das Beste, das ich bisher produzieren konnte.
Testen
quelle
JavaScript 186
könnte weniger sein, aber ich mag lesbares Golf
quelle
Haskell , 125 Bytes
Probieren Sie es online aus!
Eingabe und Ausgabe in Form eines Paares
(n,d)
.Kurze Erklärung:
n
Konstruiert die nächste Zeile aus der vorherigen, indem jedes Fraktionspaar betrachtet und die neue zwischen der ersten und der Rekursion eingefügt wird (wodurch die zweite Fraktion genau dort platziert wird). Der Basisfall ist sehr einfach, da es sich im Grunde nur um die Identitätsfunktion handelt. Diet
Funktion iteriert diese Funktion auf unbestimmte Zeit basierend auf dem Anfangszustand mit nur den beiden Grenzfraktionen.t
indiziert dann jede Zeile (i
) und jedes Element in der Zeile (j
) und sucht nach dem ersten Bruch, der dem entspricht, wonach wir suchen. Wenn es es findet, gibt esj
als Zähler und2^i
als Nenner nach.quelle