Aufgabe:
Ihr Programm erhält einen korrekten , positiven einfachen Bruch im Format <numerator>/<denominator>
.
Für diese Eingabe müssen zwei Brüche gefunden werden.
- Ein Bruchteil, der kleiner als die Eingabe ist.
- Ein Bruchteil, der größer als die Eingabe ist.
Beide Brüche müssen einen niedrigeren Nenner als die Eingabe haben. Von allen möglichen Brüchen sollten sie den geringsten Unterschied zur Eingabe aufweisen.
Ausgabe:
Die Ausgabe Ihres Programms muss sein:
- Ein Bruch, der im Format kleiner als die Eingabe ist
<numerator>/<denominator>
. - Gefolgt von einem Leerzeichen (ASCII-Code 32).
- Gefolgt von einem Bruch, der größer als die Eingabe ist, im Format
<numerator>/<denominator>
.
Wie folgt:
«fraction that is < input» «fraction that is > input»
Regeln:
- Alle ausgegebenen Brüche müssen in niedrigsten Ausdrücken angegeben werden .
- Alle ausgegebenen Brüche müssen richtige Brüche sein.
- Wenn keine korrekten Brüche möglich sind, die nach den Regeln zulässig sind, müssen Sie
0
anstelle eines Bruches <input und ausgeben1
> anstelle eines Bruchs> eine Eingabe vornehmen. - Sie können wählen, ob Sie den Bruch als Befehlszeilenargument erhalten möchten (z. B.
yourprogram.exe 2/5
) oder zur Eingabe durch den Benutzer . - Sie können davon ausgehen, dass Ihr Programm keine ungültigen Eingaben erhält.
- Der kürzeste Code (in Bytes, in jeder Sprache) gewinnt.
Alle nicht standardmäßigen Befehlszeilenargumente (Argumente, die normalerweise nicht zum Ausführen eines Skripts erforderlich sind) werden auf die Gesamtzahl der Zeichen angerechnet.
Was Ihr Programm nicht tun darf :
- Abhängig von externen Ressourcen.
- Hängen Sie davon ab, einen bestimmten Dateinamen zu haben.
- Geben Sie etwas anderes als die erforderliche Ausgabe aus.
- Es dauert außergewöhnlich lange zu laufen. Wenn Ihr Programm für Brüche mit einem 6-stelligen Zähler und Nenner länger als eine Minute läuft (z. B.
179565/987657
) auf dem Computer eines durchschnittlichen Heimanwenders ausgeführt wird, ist es ungültig. - Ausgabefraktionen mit
0
als Nenner. Sie können nicht durch Null teilen. - Brüche mit
0
als Zähler ausgeben. Ihr Programm muss0
anstelle eines Bruchs ausgegeben werden. - Reduzieren Sie einen eingegebenen Bruch. Wenn der als Eingabe angegebene Bruch reduzierbar ist, müssen Sie den als Eingabe angegebenen Bruch verwenden.
- Ihr Programm darf nicht in einer Programmiersprache geschrieben sein, für die es vor Veröffentlichung dieser Herausforderung keinen öffentlich verfügbaren Compiler / Interpreter gab.
Beispiele:
Eingabe: 2/5
Ausgabe: 1/3 1/2
Eingabe: 1/2
Ausgabe: 0 1
Eingabe: 5/9
Ausgabe: 1/2 4/7
Eingabe: 1/3
Ausgabe: 0 1/2
Eingabe: 2/4
Ausgabe: 1/3 2/3
Eingabe: 179565/987657
Ausgabe: 170496/937775 128779/708320
1/3 1/2
.Antworten:
Salbei -
119117Salbei wird nur in der letzten Zeile benötigt, die sich um die Ausgabe kümmert. Alles andere funktioniert auch in Python.
Ersetzen Sie
raw_input()
durchsys.argv[1]
, um die Eingabe von einem Befehlszeilenargument anstelle einer Eingabeaufforderung lesen zu lassen. Die Zeichenanzahl wird dadurch nicht geändert. (Funktioniert nicht in Python, ohnesys
vorher importiert zu haben .)Dies konstruiert im wesentlichen rekursiv das jeweilige Farey-Sequenz Verwendung von Medianten der vorhandenen Elemente, beschränkt sich jedoch auf diejenigen Elemente, die der Eingabe am nächsten liegen. Aus einer anderen Sicht führt es eine Suche nach verschachtelten Intervallen für die jeweiligen Farey-Sequenzen durch.
Auf meinem Computer werden alle Beispiele in weniger als einer Sekunde korrekt verarbeitet.
Hier ist eine ungolfed Version:
quelle
exec
!Python 2.7 - 138
Ich habe mit der offensichtlichen Brute-Force-Lösung begonnen, aber mir wurde klar, dass ich, da das OP Instanzen mit sechsstelligen Zählern und Nennern in weniger als einer Minute lösen wollte, eine bessere Lösung brauche, als Billionen von Möglichkeiten auszuprobieren. Ich habe auf der Wikipedia-Seite eine nützliche Formel für die Farey-Sequenz gefunden: Wenn a / b, c / d Nachbarn in einer der Farey-Sequenzen sind, mit
a/b<c/d
, dannb*c-a*b=1
. Die while-Schleife in f in meinem Programm erweitert diese Tatsache auf nicht reduzierte Zahlen, wobei die gcd verwendet wird, die die andere while-Schleife berechnet.Ich habe das schon ziemlich hart gespielt, aber ich würde gerne Vorschläge hören.
Bearbeitungen:
166-> 162: Entfernt
a
undb
aus dem äußeren Programm. Sie waren unnötig.162-> 155:
str()
-> ``155-> 154: Hinzugefügt
k
.154-> 152: Wurde
x
aus der Funktion entfernt und stattdessen als Argument übergeben.152-> 150: Hat
a
einen Standardwert angegeben, anstatt ihn als Argument zu übergeben.150-> 146: Die Initialisierung von
x
und wurde geänderty
.146-> 145: entfernt
k
.145-> 144: Geändert ... und ... oder ... zu (..., ...) [...], wodurch Platz gespart wird.
144-> 138: Geändert (..., ...) [...] zu ... + ... * (...). Vielen Dank an @ mbomb007.
Testfälle:
Der vorletzte Test dauerte auf meinem Computer weniger als eine Sekunde, während der letzte etwa 5-10 Sekunden dauerte.
quelle
k=1
ist reine Bosheit.print`(a*n+p)/d`+('/'+`a`)*(a>1),
Mathematica, 163 Bytes
Dies wird durch die Eingabe- / Ausgabeanforderung als Benutzereingabe und Zeichenfolgen stark eingeschränkt. Der Umgang mit Streichern ist in Mathematica sehr umständlich (zumindest, wenn Sie Golf spielen möchten). Wenn ich das in Mathematica auf natürliche Weise mache (nur mit ganzen Zahlen und Rationen), würde ich das wahrscheinlich auf 50% der Größe reduzieren.
Es kann 6-stellige Zahlen in ein paar Sekunden auf meinem Computer machen.
Etwas besser lesbar (allerdings nicht wirklich ungolfed):
Zum Spaß, wenn man dies "auf natürliche Weise" macht, dh als Funktion, die Zähler und Nenner nimmt und zwei Rationen zurückgibt, sind dies nur 84 Zeichen (meine 50% -Schätzung war also eigentlich ziemlich nahe):
quelle
Julia -
127125 BytesIch habe dies aus mathematischer Sicht angegangen, um die Notwendigkeit von Schleifen zu vermeiden, sodass dieser Code für große Eingaben recht schnell ausgeführt wird (Hinweis: Wenn a / b die Eingabe ist, muss a * b in Int64 passen (Int32 auf 32-Bit-Systemen). , andernfalls werden unsinnige Antworten generiert - wenn a und b in Int32 (Int16 auf 32-Bit-Systemen) beide ausgedrückt werden können, treten keine Probleme auf.
UPDATE: Es besteht keine Notwendigkeit mehr, einen Backslash für div zu überladen, indem ÷ verwendet wird, was 2 Bytes einspart.
Ungolfed:
Grundidee: Finde das größte d und f kleiner als b, das ad-bc = gcd (a, b) (das nächstkleinere) und be-af = gcd (a, b) (das nächstgrößere) erfüllt, und berechne dann c und e aus Dort. Die resultierende Ausgabe ist c / de / f, es sei denn, d oder f sind 1. In diesem Fall wird / d oder / f weggelassen.
Interessanterweise bedeutet dies, dass der Code auch für positive nicht ordnungsgemäße Brüche funktioniert, solange die Eingabe keine ganze Zahl ist (d. H. Gcd (a, b) = a).
Auf meinem System nimmt die Eingabe
194857602/34512958303
keine wahrnehmbare Zeit in Anspruch171085289/30302433084 23772313/4210525219
quelle
55552/999999
gibt mir-396/920632 486/936509
.int32(55552*999999)
gibt-282630400
. Bei diesem Test51143/920632 52025/936509
stelle ich fest, dass die Nenner gleich sind und 52025-51143 = 486 - (- 396). Ich werde eine Notiz hinzufügen, um dieses Problem zu erwähnen.1234567891234567/2145768375829475878
zu869253326028691/1510825213275018197 365314565205876/634943162554457681
. Diese Änderung fügt nur 3 zusätzliche Zeichen hinzu.JavaScript, 131
Mit fetter Pfeilnotation und
eval
Aufrufen:Der
179565/987657
Stresstest dauert ca. 35 Sekunden Firefox , unter Chrome noch viel mehr (~ 6 Minuten)Schnellere Methode und ohne
eval
und fette PfeilnotationDer
179565/987657
Stresstest dauert ca. 5 Sekunden.Nicht golfen:
quelle
eval
. EEK2/6
gibt1/3 2/5
jedoch1/3
nicht weniger als aber gleich2/6
.Perl, 142 Bytes (155 ohne CPAN)
Oder wenn CPAN-Module nicht erlaubt sind / 3-4 mal schnellerer Code benötigt wird:
Die erste Version dauert auf meinem Computer 9,55 Sekunden, die zweite Version 2,44 Sekunden.
Weniger unleserlich:
quelle