Wandle eine wiederholte Dezimalstelle in einen Bruch um


23

Diese Frage muss sich nicht nur auf das Beenden von Dezimalstellen beziehen - wiederholte Dezimalstellen können auch über einen Algorithmus in Brüche umgewandelt werden.

Ihre Aufgabe ist es, ein Programm zu erstellen, das eine wiederholte Dezimalzahl als Eingabe verwendet, und den entsprechenden Zähler und Nenner (in niedrigsten Ausdrücken) auszugeben, der diese Dezimalerweiterung erzeugt. Brüche größer als 1 sollten als ungeeignete Brüche wie dargestellt werden 9/5. Sie können davon ausgehen, dass der Eingang positiv ist.

Die wiederholte Dezimalzahl wird in folgendem Format angegeben:

5.3.87

mit allem, was nach dem zweiten Punkt wiederholt wird, wie folgt:

5.3878787878787...

Ihr Programm gibt zwei durch einen Schrägstrich getrennte Ganzzahlen aus, die den Zähler und den Nenner darstellen (oder die entsprechende Form in Ihrer Sprache, wenn Sie keinen einfachen Text ausgeben):

889/165

Beachten Sie, dass beim Beenden von Dezimalstellen nach dem zweiten Punkt nichts angezeigt wird und bei Dezimalstellen ohne nicht wiederholten Dezimalstellen zwischen den beiden Punkten nichts angezeigt wird.

Testfälle

Diese Testfälle decken alle erforderlichen Eckfälle ab:

0..3 = 1/3
0.0.3 = 1/30
0.00.3 = 1/300
0.6875. = 11/16
1.8. = 9/5
2.. = 2/1
5..09 = 56/11
0.1.6 = 1/6
2..142857 = 15/7
0.01041.6 = 1/96
0.2.283950617 = 37/162
0.000000.1 = 1/9000000
0..9 = 1/1
0.0.9 = 1/10
0.24.9 = 1/4

Wenn Sie möchten, können Sie auch davon ausgehen, dass Brüche ohne ganzzahlige Teile nichts links vom ersten Punkt haben. Sie können das mit diesen optionalen Testfällen testen:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1

1
Muss die Fraktion vereinfacht werden? Oder ist es sinnvoll, es in einer nicht vereinfachten Form zu belassen (zB:) 9/99?
Justin

3
(in lowest terms)dh der Bruch muss vereinfacht werden.
Joe Z.

2
Darf ich 13statt ausgeben 13/1?
14.

4
Achten Sie darauf, diese Ein- 1.9999...und Ausgabe zu behandeln2/1
Thomas Eding

3
@ThomasEding 1.9999.ist 19999/10000, um 2/1dich zu holen 1..9, nicht wahr ?
Qwertiy

Antworten:


8

Dyalog APL ( 75 73 69 68 Zeichen)

Hier ist ein weiterer und fünfter Versuch (höchstwahrscheinlich mein letzter); Ich habe den Tag damit verbracht, einen Code zu schreiben, der kürzer als 80 Zeichen ist und den Regeln entspricht. Diese Herausforderung machte meinen Tag!

Endlich habe ich eine APL-Zeile mit 75 Zeichen erhalten, die mit Dyalog APL funktioniert (aber nicht auf der Online-Interpreterseite, da die Ausführungsfunktion verwendet wird). Dies ist die folgende:

(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'

Natürlich könnte ich es etwas kürzer machen, aber die Sonderfälle, in denen ein, zwei oder drei Felder fehlen. Mein Code kann sogar den ..Eingabefall verarbeiten.

Ich weiß, dass APL schwer zu lesen ist, und da die Leute gerne verstehen, wie ein Teil des Codes tatsächlich funktioniert, hier einige Erklärungen. Grundsätzlich berechne ich den letzten Nenner in der Variablen D und den letzten Zähler in der Variablen N.

APL wird von rechts nach links analysiert.

  • Zunächst wird der String in der Variablen I ( I←) gespeichert .
  • Dann wird es auf einen Vektor von Booleschen Werten abgebildet, der angibt, wo sich ein Punkt befindet, und dieser Vektor wird P ( P←'.'=) genannt. Zum Beispiel wird '1.2.3' auf 0 1 0 1 0 abgebildet.
  • Dieser Vektor ist Ziffern in der Basis 10 ( 10⊥); jetzt ist '1.2.3' 1010.
  • Dann wird 1 von dieser Zahl abgezogen (entweder mit 1-⍨oder mit ¯1+, hier habe ich die zweite gewählt). Jetzt ist '1.2.3' 1009.
  • Dann wird diese Zahl in einen String ( ) umgewandelt, zwei Anfangsziffern werden entfernt ( 2↓), was in unserem anfänglichen '1.2.3'-Beispiel 09 ergibt; Die Zeichenfolge ist umgekehrt ( ).
  • In diesem Fall füge ich als Sonderfall vor der Zeichenfolge eine anfängliche 0 hinzu. Es macht mich traurig, die vier Zeichen zu verwenden, '0',aber ich habe es getan, um einen Fehler zu vermeiden, wenn das zweite und dritte Feld beide leer sind. Die Zeichenfolge wird zurück in eine Zahl ( ) konvertiert und in D gespeichert, was der Nenner ist, außer wenn beide letzten Felder leer sind, da in diesem Fall D gleich 0 ist.
  • Das Teil D←D+0=des Codes hat D auf 1 gesetzt, wenn es aktuell null ist, und jetzt enthält D den Nenner (jedoch vor der GCD-Division).
  • Dieser Nenner wird multipliziert ( ×) mit dem Inhalt der Anfangszeichenfolge I bis zu dem zweiten Punkt, mit (⍎'0',I/⍨2>+\P)dem wieder bei P begonnen wird (0 1 0 1 0 in meinem Beispiel), addiert die aufeinanderfolgenden Zahlen, indem sie kumuliert werden (was 0 1 1 2 ergibt 2 in meinem Beispiel), überprüfen Sie, welche Werte kleiner als 2 sind (was den Booleschen Vektor zu 1 1 1 0 0 macht), und nehmen Sie die entsprechenden Zeichen in I; Eine weitere 0 wird vor der Zeichenfolge hinzugefügt, um eine weitere Überfüllung zu verhindern (wenn die beiden Anfangsfelder leer sind), und das Ganze wird in eine Zahl umgewandelt.
  • Der letzte Teil der Eingabezeichenfolge wird zum vorherigen Produkt hinzugefügt (⍎'0',1↓I/⍨2=+\P), wobei P erneut verwendet wird, indem erneut kumuliert wird, überprüft wird, welche Werte gleich 2 sind (siehe vorherige Erläuterung), die Zeichen verwendet werden und der erste Punkt entfernt wird , fügt ein vorbeugendes Anfangszeichen 0 hinzu und wandelt es in eine Zahl um.
  • Dieses Produkt, gefolgt von einer Summe, wird in N gespeichert, welches der Zähler ist.
  • Schließlich wird die GCD mit D∨N berechnet und beide Zahlen werden durch diese GCD geteilt.

edit: Hier ist ein Fix für 73 Zeichen:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←

Die Idee dieses Hacks ist, zunächst den Fall zu berechnen, in dem die kumulative Addition Werte gleich 2 hat, diese für später zu speichern und diese bitweise Maske zu invertieren, um den ersten Fall zu erhalten. Die Berechnung des nächsten Falls erfordert daher weniger Zeichen.

Bearbeiten: Hier ist eine weitere Korrektur für 69 Zeichen:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←

Die Idee dieses Hacks ist es, den kompliziertesten Sonderfall als APL-Code in die zu bewertende Zeichenfolge einzubetten (bei der Konvertierung von Zeichenfolge zu Zahl).

Bearbeiten: Hier ist eine weitere Korrektur für 68 Zeichen:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←

Die Idee dieses Hacks ist es, das Hinzufügen von -1 zu dem Wert zum Subtrahieren von 1 zu diesem Wert durch die Operation zum Subtrahieren dieses Werts zu 1 zu ersetzen und später ein Zeichen mehr am Anfang zu entfernen (dies ist das Minuszeichen).

bearbeiten: Kosmetische Veränderung:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←

Keine Größenverbesserung, aber zufriedener damit, die maximale Funktion aus dem zu bewertenden Code herauszuholen.


Ich habe versucht, dies mit tryapl.org auszuführen und es beschwert sich INVALID TOKEN. Wissen Sie, warum?
Peter Taylor

@ Peter Taylor: Ja, das steht sogar in meiner Nachricht; Dies liegt daran, dass ich den Operator "Ausführen" verwende, der für den Server von Dyalog unsicher wäre und online deaktiviert wurde (abgesicherter Modus). Sie müssen es auf einer installierten Version von Dyalog APL versuchen.
Thomas Baruchel

Ah, schade. Ich werde keine 60 € ausgeben, um eine gelegentliche PCG-Einreichung testen zu können. Ich habe einen alternativen Online-APL-Tester gefunden, aber es scheint etwas Dyalog-spezifisches in Ihrem Code zu geben, da es Rang- oder Längenfehler gibt.
Peter Taylor

@ Peter Taylor; nein ;-) Bitte benutze meine eigene Website (noch experimentell und nicht offiziell) mit GNU APL; aber ich musste zwei Zeichen hinzufügen, um es kompatibel zu machen (Klammer um eins I): siehe diesen Permalink
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 Bytes)

$/=split ".",get;say ($0+($1+$2/(9 x$2.comb||1))/10**$1.comb).nude

Die Größe wurde erhöht, um nichts zu handhaben, anstatt nur zu versagen. Mouq hat die Verwendung vorgeschlagen $/, daher wird sie jetzt verwendet, und der Code ist 20 Byte kürzer. Ayiko vorgeschlagen Ersetzen /mit , so dass der Code noch kürzer ist (von 12 Bytes). Dann Mouq vorgeschlagen ersetzt charsmit comb(in numerischem Kontext, sie sind identisch, weil die Liste der Zeichen nach der Umwandlung in Anzahl Anzahl der Zeichen ist).

Beispielausgabe:

$ perl6 script.p6
5.3.87
889 165
$ perl6 script.p6
2.0.0
2 1
$ perl6 script.p6
0..3
1 3
$ perl6 script.p6
0.0.3
1 30
$ perl6 script.p6
0.0.0
0 1
$ perl6 script.p6
0.1.6
1 6
$ perl6 script.p6
0.01041.6
1 96
$ perl6 script.p6
0.2.283950617
37 162
$ perl6 script.p6
123.456.789
41111111 333000

Leider hat sich herausgestellt, dass die Verwendung von Null als Platzhalter zwischen zwei Punkten kein Problem darstellt. 0..09kehrt zurück 1/11, 0.0.09kehrt aber zurück 1/110.
Joe Z.

@JoeZ. Oh ok. Ich habe meinen Code aktualisiert, um den Fall zu behandeln, wenn nichts eingegeben wird.
Konrad Borowski

Ich kenne Perl 6 nicht, aber ich vermute, dass Ihr Programm bei gegebenem 'abc' für die Berechnung von c / 99 ... 9 eine exakte rationale Arithmetik verwendet, für die Berechnung von ab jedoch nur Gleitkommazahlen? In diesem Fall gibt b eine falsche Antwort, wenn es viele Ziffern hat.
Omar

@ OmarAntolín-Camarena: Nicht ganz. In Perl 6 sind Rationalitäten Standardwerte und keine Gleitkommazahlen. Zum Beispiel 0.1 + 0.2 == 0.3in Perl 6.
Konrad Borowski

2
Golf zu 80 Zeichen: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq

6

J ( 85 90 89 Zeichen)

Meine ursprüngliche Funktion, die 5 Zeichen kürzer als die zweite war, hatte ein paar Fehler: Sie gab keine Ganzzahlen als "n / 1" aus und gab die falsche Antwort auf Zahlen mit mehr als einem Dutzend oder so Ziffern. Hier ist eine korrigierte Funktion in J, die auch den Vorschlag von Eelvex enthält, ein Zeichen zu speichern:

f=:3 :0
'a t'=.|:(".@('0','x',~]),10x^#);._1'.',y
(,'/'&,)&":/(,%+.)&1+/a%*/\1,0 1-~}.t
)

Es empfängt eine Zeichenfolge und gibt eine Zeichenfolge zurück. Hier ist eine Beispielsitzung:

   f '..'
0/1
   f '0.0.0'
0/1
   f '3..'
3/1
   f '..052631578947368421'
1/19
   f '0.2.283950617'
37/162
   f '.0.103092783505154639175257731958762886597938144329896907216494845360824742268041237113402061855670'
1/97

Sie sollten Ihre Funktion so 0/13/1
einstellen, dass sie die

Ich habe die Ausgabe für ganze Zahlen auf Kosten von 5 Zeichen @mniip korrigiert.
Omar

Verwenden ('0','x',~])und speichern Sie ein Byte.
Eelvex

5

C 171

Ziemlich lange. Könnte weiter reduziert werden. Nein scanf, die wirklich nicht damit umgehen können, wenn zwischen den Punkten keine Zahlen stehen. Nein strtol. Nur Zahlen knacken:

a,b,c,d,q;main(){while((q=getchar()-48)>-3)q<0?(d=b>0,b+=!b):d?(c=c*10+q,d*=10):(a=a*10+q,b*=10);for(a=a*--d+c,q=b*=d;q>1;a%q+b%q?--q:(a/=q,b/=q));printf("%d/%d\n",a,b);}

Prüfung:

rfc <<< "2..142857"
15/7

5

DC (nicht ganz allgemein, auf 76 Zeichen gekürzt)

Nicht ganz allgemein, aber bitte denken Sie daran, dass ich es mit einem der ältesten Dinge der Welt gemacht habe:

5.3.87 dsaX10r^d1-rla*sasbdscX10r^dlc*rlb*rlb*la+snsdlnld[dSarLa%d0<a]dsax+dldr/rlnr/f

Bearbeiten: Ich bearbeite meine Lösung. es ist nicht allgemeiner, aber etwas kürzer:

sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f

Verwenden Sie es als:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • Das erste Feld ist nicht erforderlich:

    .1.3 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
    

    ist in Ordnung.

  • Zweites und durstiges Feld erfordern mindestens eine Ziffer


5

Javascript, 203

Viel zu lang, aber trotzdem lustig. Zeilenumbrüche, da Semikolons nicht lesbar sind.

s=prompt(b=1).split(".")
P=Math.pow
a=s[0]
c=s[1]
d=P(10,l=c.length)
f=(P(10,s[2].length)-1)*P(10,l)||1
e=s[2]=+s[2]
a=d*a+b*c;b*=d
a=f*a+b*e;b*=f
function g(a,b){return b?g(b,a%b):a}g=g(a,b);a/g+"/"+b/g

Ich bekomme, 889/NaNwenn ich renne 5.3.87... Mache ich etwas falsch?
Rafaelcastrocouto

Ich weiß nicht ... Wenn ich diesen Code einfach in die Safari-Konsole einfüge (Firefox oder Chrome sollten es auch tun), drücke die Eingabetaste und tippe "5.3.87". Ich komme einfach "889/165"in die Konsole. Wie läuft es? @rafaelcastrocouto
tomsmeding

vergiss es ... ich schätze, ich habe etwas falsch gemacht, da es jetzt funktioniert ...
rafaelcastrocouto

1
Sie können 1 Zeichen speichern, indem Sie das b=1Teil nach innen bewegen prompt().
user2428118

1
f=(P(10,s[2].length)-1)*P(10,l),f=f?f:1=>f=(P(10,s[2].length)-1)*P(10,l)||1
f.ardelian

3

J (andere Methode)

Eine andere Lösung basiert auf einer ganz anderen Methode; diesmal ist es ganz allgemein; Es fehlt nur der 1-Nenner, wenn eine Ganzzahl übergeben wird:

   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.3'
2r15
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.'
1r10
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..'
1
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..3'
4r3

3

GolfScript (67 Zeichen)

`{'.'/1$=.10\,?@-).!+0@+~}+3,/1$4$*]-1%~;*+*+].~{.@\%.}do;{/}+/'/'@

NB Dies unterstützt leere ganzzahlige Teile.

Wenn die Zeichenfolge der Form ist , 'n.p.q'dann ist der Wert , n + p/E + q/(DE) = ((nD + p)E + q)/DEwo D = 10^(len p)und E = 10^(len q) - 1, außer wenn len q = 0, in welchem Fall E = 1(zu vermeiden Division durch 0).

Präparation:

           # Stack: 'n.p.q'
`{         # Combined with the }+ below this pulls the value into the block
           # Stack: idx 'n.p.q'
    '.'/   # Stack: idx ['n' 'p' 'q']
    1$=    # Stack: idx str   (where str is the indexed element of ['n' 'p' 'q'])
    .10\,? # Stack: idx str 10^(len str)
    @-)    # Stack: str 10^(len str)-idx+1
           #   If idx = 0 we don't care about the top value on the stack
           #   If idx = 1 we compute D = 10^(len 'p')
           #   If idx = 2 we compute E' = 10^(len 'q') - 1
    .!+    # Handle the special case E'=0; note that D is never 0
    0@+~   # Stack: 10^(len str)-idx+1 eval('0'+str) (GolfScript doesn't treat 011 as octal)
}+         # See above
3,/        # Run the block for idx = 0, 1, 2
           # Stack: _ n D p E q
1$4$*      # Stack: _ n D p E q D*E
]-1%~;     # Stack: D*E q E p D n
*+*+       # Stack: D*E q+E*(p+D*n)
].~        # Stack: [denom' num'] denom' num'
{.@\%.}do; # Stack: [denom' num'] gcd
{/}+/      # Stack: denom num
'/'@       # Stack: num '/' denom

Online-Demo, bei der das Programm nacheinander mit jedem Testeingang ausgeführt wird.


Ich habe es versucht, und es scheint nicht allen Regeln zu entsprechen: "Beachten Sie, dass beim Beenden von Dezimalstellen nach dem zweiten Punkt nichts steht und bei Dezimalstellen ohne nicht wiederholten Dezimalstellenanteil zwischen den beiden Punkten nichts steht." Ich konnte Ihren Code nicht mit Eingaben arbeiten lassen0.1.
Thomas Baruchel

-1. Ich habe es ein weiteres Mal versucht, nachdem ich bemerkt hatte, dass du die +300 Punkte hast. Es ist nicht fair, weil andere Lösungen ihr Bestes gegeben haben, um alle Regeln zu befolgen, was Sie offensichtlich nicht getan haben.
Thomas Baruchel

@ ברוכאל, ich widerspreche Ihrer Behauptung, dass ich nicht versucht habe, die Regeln zu befolgen. Die Position der optionalen Testfälle verwirrte mich in der Annahme, dass der letzte Block alle erforderlichen Fälle abdeckte. Es stellt sich heraus, dass ich mich geirrt habe, und ich werde die Frage in Kürze bearbeiten, um zu vermeiden, dass andere Menschen den gleichen Fehler machen. Ich habe jetzt meinen Code aktualisiert, um die zuvor nicht behandelten Eckfälle zu behandeln, und meinen Link zu einem Test aktualisiert, um dies zu demonstrieren.
Peter Taylor

das ist ok. Sie verdienen wahrscheinlich die 300 Punkte. Als Neueinsteiger bei CodeGolf waren diese 300 Punkte ein herausforderndes Ziel für mich und ich bin immer noch enttäuscht, dass ich sie nicht bekommen habe, während ich immer noch denke, dass mein Code zum Zeitpunkt des Abgabetermins der kürzeste war, um die Regeln perfekt zu erfüllen. Wie auch immer, ich habe mein ganzes Leben für das Gewinnen von Punkten. Grüße.
Thomas Baruchel

@ ברוכאל: Ich wollte mit 500 Punkten anfangen (ja, ich bin so großzügig, es ist nicht so, dass ich weniger geben kann), und ich gebe dir diese Punkte, aber ich denke, es wurde bereits ein Kopfgeld ausgesprochen. OK Was solls. Ich frage mich, wann diese Prämie enden wird und wer diese Punkte bekommt.
Konrad Borowski

2

Python

Keine Bibliotheken - 156 Zeichen

_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),
(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)

Verwenden von fractions- 127 Zeichen

from fractions import*;a,b,c=raw_input().split('.');print Fraction(int(a+b+c)-bool(c)*int(a+b
),(10**len(c)-bool(c))*10**len(b))

Die fractionsVersion gibt Dinge wie "Bruch (7, 5)" anstelle von "7/5" aus, nicht wahr?
Omar

Das tut es nicht. Ich bekomme übrigens nicht den Besten zum Laufen. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b), ValueError: need more than 1 value to unpack
Tomsmeding

@ OmarAntolín-Camarena AFAIK, printnutzt strbei Verfügbarkeit nicht repr. Dies ist die Ausgabe auf meinem Ende: puu.sh/7w64w.png
Oberon

@tomsmeding Beide befinden sich in einer Zeile. Der Zeilenumbruch wurde hinzugefügt, damit sie in die Antwort passen. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)sollte alles in einer Zeile gehen.
Oberon

Oh richtig, @Oberon, wie Sie wahrscheinlich vermuten können, war ich nicht an meinem Computer und konnte den Code nicht ausführen.
Omar

2

Mathematica, 143

Wie üblich bietet Mathematica viele Funktionen auf hoher Ebene, um die Aufgabe zu erledigen, gibt ihnen jedoch ausführliche Namen.

x=StringTake;c=ToExpression;p=s~StringPosition~".";{o,t}=First/@p;u=StringLength@s-t;d=t-o-1;Rationalize@(c@x[s,t-1]+c@x[s,-u]/((10^u)-1)/10^d)

Beispielausgabe, die später hinzugefügt wird, wenn ich Zeit habe.


Es sieht für mich so aus, als ob dies ganze Zahlen als n und nicht als n / 1 ausgibt. Ist das richtig? (Meine Lösung hat den gleichen Fehler ... :()
Omar

Ah, jetzt sehe ich .... angegeben in den Kommentaren. Was für eine seltsame Anforderung ... wenn jeder zweite Bruchteil reduziert wird, warum nicht zulassen n/1, dass er reduziert wird n? Ich werde die zusätzlichen ~ 50 Bytes hinzufügen, um die Ganzzahlen später zu konvertieren.
Jonathan Van Matre

Ihr Ansatz ist in Ordnung. Meins nutzt, FromDigitsalso habe ich beschlossen, es auch zu posten.
DavidC

2

Rubin - 112

x,y,z=gets.chop.split".";y||='0';z||='0';puts((y.to_i+Rational(z.to_i,10**z.length-1))/10**y.length+x.to_i).to_s

Dies ist mein erstes Experiment mit Ruby. Sie können also jederzeit Verbesserungen vorschlagen.

$ ruby20 % <<< '5.3.87'
889/165
$ ruby20 % <<< '0..3'
1/3
$ ruby20 % <<< '0.0.3'
1/30
$ ruby20 % <<< '0.00.3'
1/300
$ ruby20 % <<< '0.6875.0'
11/16
$ ruby20 % <<< '1.8.0'
9/5
$ ruby20 % <<< '2..'
2/1
$ ruby20 % <<< '..'
0/1

Entfernen der Unterstützung ".." und ".1.2" bedeutet, dass Sie die Spezifikation nicht befolgen, richtig? (Ich würde es vorziehen, sie auch zu entfernen.)
Omar

@ OmarAntolín-Camarena an diesem bestimmten Punkt, sagt der spec, If you wish. Ich möchte nicht, also unterstütze ich keine Brüche ohne 1. oder 3. Zifferngruppe. Ich unterstütze jedoch Brüche ohne 2. Zifferngruppe, was der Spezifikation entspricht.
14.

@minip, Sie haben die Spezifikation falsch verstanden: Es heißt nicht "Wenn Sie möchten, dass Sie ... und .1.2 unterstützen können", sondern "Wenn Sie möchten, können Sie davon ausgehen, dass 0 ... und 0.1.2 immer als gegeben sind .. und .1.2 ".
Omar

@ OmarAntolín-Camarena Punkt genommen. Bearbeitet
14.

2

C 164

Dies ähnelt der C-Lösung von orion, obwohl ich es von Grund auf getan habe. Ich gestehe jedoch, einige seiner Optimierungen gestohlen zu haben. Es ist nicht viel kürzer, aber es verarbeitet 0,25. = 1/4 und 0,000000,1 = 1/9000000.

long a,b,c,d,e;main(){while((c=getchar()-48)>-3)c+2?a=a*10+c,b*=10:b?e=a,d=b:(b=1);
b>d?a-=e,b-=d:0;for(d=2;d<=a;)a%d+b%d?d++:(a/=d,b/=d);printf("%ld/%ld\n",a,b);}

2

Zwei Python-Antworten ohne Bibliotheken. First behandelt die optionale Eingabe ohne eine Ziffer vor der ersten. und ist 162 Zeichen

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int((i+t+r)or 0)-b*int((i+t)or 0);f=_(d,n);print "%i/%i"%(n,d)

Der zweite behandelt nichts vor der ersten Ziffer, behandelt aber alle erforderlichen Eingaben korrekt und hat 150 Zeichen

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int(i+t+r)-b*int(i+t);f=_(d,n);print "%i/%i"%(n,d)

2

Haskell

import Data.Ratio
f n=case s '.' n of
    [x,y,z]->(r x)%1+(r y)%(10^(length y))+(r z)%((10^t-1)*(10^(length y)))
        where
            r ""=0
            r n=read n
            t = if length z==0 then 9 else length z
s _ []=[[]]
s n (x:xs) | x==n = []:(s n xs)
           | otherwise = let (l:ls)=s n xs in (x:l):ls

Hey, das ist Code-Golf, du versuchst es nicht einmal!
16.

@mniip Ich bin nicht gut im Code Golf. Zumindest habe ich einzelne Zeichen Variablennamen verwendet.
PyRulez

1
Sie haben nie die Sprache oder die Gesamtanzahl der verwendeten Zeichen / Bytes angegeben.
Justin Fay

2
Verwenden Sie {;}, um Platz in Einzügen zu sparen, spans zu implementieren, kurze Aliase für Funktionen hinzuzufügen und wenn möglich Leerzeichen zu entfernen. import Data.Ratio v=span(/='.');w=tail;l=length;f n=(r x)%1+(r y)%p+(r z)%((10^t-1)*p)where{(x,b)=v n;(y,d)=v(w b);z=w d;p=10^(l y);r""=0;r n=read n;t=if null z then 9 else l z}- 178 Zeichen, unten von 321. NB Trueist ein Synonym für otherwise, null zistlength z==0
bazzargh

2

JavaScript (ECMASCript 6) 180 175

G=(a,d)=>d?G(d,a%d):a;P=a=>+("1e"+a);L=a=>a.length;f=prompt().split(".");B=P(L(b=f[1]));D=P(L(b)+L(c=f[2]))-P(L(b))||1;alert((m=(f[0]+b||0)*D+B*(c||0))/(g=G(m,n=B*D))+"/"+n/g)

Es ist zwar kein klarer Gewinner für die 300-Kopfgelder ... aber dies ist die kürzeste, die ich mir einfallen lassen kann:

  • Änderungen gegenüber der Vorgängerversion: Einige geringfügige Änderungen an der Logik und Änderungen an der Power- PFunktion, indem diese in geändert wird, +("1e"+a)anstatt Math.pow(10,a)ein paar weitere Zeichen zu speichern ...

1

Mathematica 175

f@i_:=
If[IntegerQ[g=FromDigits[Map[IntegerDigits@ToExpression@#&,StringSplit[i,"."]/.""-> {}]
/.{a_,b_,c_}:> {{Sequence@@Join[a,b],c},Length@a}]],HoldForm[Evaluate@g]/HoldForm@1,g]

Der größte Teil der Routine wird zum Massieren der Eingabe ausgeführt. Ungefähr 50 Zeichen wurden für die Verarbeitung ganzer Zahlen verwendet.


Beispiele

f["7801.098.765"]

frac1

Mehr Beispiele:

TableForm[
 Partition[{#, f[#]} & /@ {"19..87", "19.3.87", "5.3.87", "0.0.3", "0..3", "0.2.283950617", 
"123.456.789", "6666.7777.8888", "2.0.0","0.0.0"}, 5], TableSpacing -> {5, 5}]

frac2


Wie es normalerweise in Mathematica geschehen würde

FromDigitskann einen Bruch direkt aus einer wiederkehrenden wiederholten Dezimalstelle erhalten, vorausgesetzt, die Eingabe hat eine bestimmte Form. Ganzzahlen werden als Ganzzahlen angezeigt.

z={{{1, 9, {8, 7}}, 2}, {{1, 9, 3, {8, 7}}, 2}, {{5, 3, {8, 7}}, 1}, {{{3}}, -1}, {{{3}}, 0}, 
{{2, {2, 8, 3, 9, 5, 0, 6, 1, 7}}, 0}, {{1, 2, 3, 4, 5, 6, {7, 8, 9}}, 3}, 
{{6, 6, 6, 6, 7, 7, 7, 7, {8}}, 4}, {{2}, 1}, {{0}, 1}}

FromDigits/@z

z


Ihre Ausgabe hat das falsche Format, sie ist viel zu hübsch.
Omar

Seltsamerweise ist dies das Standardformat zum Ausdrücken von Brüchen in Mathematica. Es würde mehrere weitere Zeichen erfordern, um dieses Format auf das einfachere zu ändern.
DavidC

1

J (96 Zeichen)

Ich verwende das Schrägstrichsymbol nicht als Trennzeichen (aber in Mathematica auch nicht, da es eine grafische Darstellung verwendet, die sowieso besser ist). In der Sprache J wird der Bruch mit rstattdessen wie folgt angezeigt /:

   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '1..3'
4r3
   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '123.456.789'
41111111r333000

1

APL (nicht ganz allgemein)

Nicht ganz allgemein (wie meine Lösung für DC); funktioniert mit Dyalog APL (aber nicht in der Online-Version von Dyalog APL, nicht sicher warum):

(R,F)÷(F←D×N)∨R←(⍎C)+D×(⍎I/⍨2>+\P)×N←10*¯1++/≠\P⊣D←¯1+10*⍴C←1↓I/⍨2=+\P←'.'=I← '123.456.789'

Das erste Feld ist optional, für beide anderen Felder ist jedoch mindestens eine Ziffer erforderlich.


1

JavaScript (189)

i=prompt().split(".");a=i[0];b=i[1];c=i[2];B=b.length;p=Math.pow;n=a+b+c-(a+b);d=p(10,B+c.length)-p(10,B);f=1;while(f){f=0;for(i=2;i<=n;i++)if(n%i==0&&d%i==0){n/=i;d/=i;f=1}};alert(n+"/"+d)

Beispiel:

Eingang:

5.3.87

Ausgabe:

889/165

1

C (420 Zeichen wie geschrieben; weniger nach dem Entfernen unnötiger Leerzeichen)

Beachten Sie, dass dies 64-Bit voraussetzt long(z. B. 64-Bit-Linux). 0.2.283950617Auf Systemen mit 32-Bit-Version schlägt der Test fehl long. Dies kann auf Kosten einiger Zeichen behoben werden, indem der Typ auf long longund die printfFormatzeichenfolge entsprechend geändert werden.

#include <stdio.h>

long d[3], n[3], i;

int main(int c, char** v)
{
  while (c = *v[1]++)
    switch(c)
    {
    case '.':
      n[++i] = 1;
      break;
    default:
      d[i] = 10 * d[i] + c - '0';
      n[i] *= 10;
    }

  n[2] -= n[2] != 1;

  while (i--)
    d[2] += d[i] * n[i+1], n[i]*=n[i+1];

  i = d[2];
  *n = n[1];

  while (i)
    *d = i, i = *n%i, *n = *d;
  printf("%ld/%ld\n", d[2]/ *n, n[1]/ *n);
}

Nett. Sie können sich 1 Charakter abrasieren durch Änderung '0'zu 48.
Todd Lehman

Ich denke, Sie könnten auch ein paar mehr sparen, indem Sie die switchAnweisung als neu schreiben if(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;.
Todd Lehman

-3

GTB , 81

`_:s;_,1,l?_)-S;_,"."
s;A;,1,S;_,".")-1
s;_,1+S;_,"."),l?_)-S;_,"."))→_
x?A;+_)►Frac

Beispiel

?3.25.
            13/4

4
Bis ein Compiler für diese Sprache frei verfügbar ist, werde ich jede Antwort, die ihn verwendet, ablehnen.
Gareth

1
Es scheint einen Compiler auf der oben verlinkten Seite zu geben?
Skibrianski

@skibrianski Siehe diesen Beitrag auf meta
mniip

2
@Gareth, es gibt auch ein paar Mathematica-Antworten, die Sie ablehnen können. : P
Omar

2
@ OmarAntolín-Camarena Es gibt einen Compiler / Interpreter für Mathematica. GTB hat keine. Folgen Sie dem GTBLink oben, wenn Sie mir nicht glauben. Sie erhalten ein paar komprimierte Dateien für ein proprietäres Programm, suchen dann nach diesem Programm und stellen fest, dass die Website, die angibt, einen Download bereitzustellen, diese als nicht verfügbar bezeichnet. Wie kompilieren wir es?
Gareth
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.