Konwertuj powtarzający się ułamek dziesiętny na ułamek

23

To pytanie nie musi dotyczyć tylko kończenia miejsc po przecinku - powtarzające się miejsca po przecinku można również konwertować na ułamki za pomocą algorytmu.

Twoim zadaniem jest stworzenie programu, który pobiera dziesiętną liczbę dziesiętną jako dane wejściowe, i wypisuje odpowiedni licznik i mianownik (w najniższych terminach), który generuje to rozwinięcie dziesiętne. Ułamki większe niż 1 powinny być reprezentowane jako ułamki niewłaściwe, takie jak 9/5. Możesz założyć, że dane wejściowe będą dodatnie.

Powtarzany ułamek dziesiętny zostanie podany w tym formacie:

5.3.87

z powtórzeniem wszystkiego po drugiej kropce:

5.3878787878787...

Twój program wyświetli dwie liczby całkowite reprezentujące licznik i mianownik, oddzielone ukośnikiem (lub równoważną formą w twoim języku, jeśli nie wypisujesz zwykłego tekstu):

889/165

Zauważ, że kończące miejsca po przecinku nie będą miały nic po drugiej kropce, a miejsca po przecinku bez powtarzalnych części dziesiętnych nie będą miały nic między dwiema kropkami.

Przypadki testowe

Te przypadki testowe obejmują wszystkie wymagane przypadki narożne:

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

Jeśli chcesz, możesz również założyć, że ułamki bez części całkowitych nie mają nic po lewej stronie pierwszej kropki. Możesz to przetestować za pomocą tych opcjonalnych przypadków testowych:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1
Joe Z.
źródło
1
Czy konieczne jest uproszczenie frakcji? Czy rozsądne jest pozostawienie go w nie uproszczonej formie (np .:) 9/99?
Justin
3
(in lowest terms)tzn. frakcja musi zostać uproszczona.
Joe Z.
2
Czy mogę wyświetlać dane 13zamiast 13/1?
mniip
4
Pamiętaj, aby obsłużyć te dane wejściowe 1.9999...i wyjściowe2/1
Thomas Eding
3
@ThomasEding 1.9999.jest 19999/10000, 2/1jeśli potrzebujesz 1..9, prawda?
Qwertiy,

Odpowiedzi:

8

Dyalog APL ( 75 73 69 68 znaków)

Oto kolejna i piąta próba (najprawdopodobniej moja ostatnia); Spędziłem dzień próbując napisać fragment kodu krótszy niż 80 znaków i zachowując pełną zgodność z regułami. To wyzwanie sprawiło, że mój dzień!

W końcu otrzymałem wiersz APL złożony z 75 znaków, współpracujący z Dyalog APL (ale nie na stronie interpretera online, ponieważ korzystam z funkcji wykonywania ), który jest następujący:

(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'

Oczywiście mógłbym to zrobić nieco krócej, ale w szczególnych przypadkach, gdy brakuje jednego, dwóch lub trzech pól. Mój kod może nawet obsłużyć ..przypadek wejściowy.

Wiem, że APL jest trudny do odczytania, a ponieważ ludzie lubią rozumieć, jak fragment kodu faktycznie działa, oto kilka wyjaśnień. Zasadniczo obliczam ostateczny mianownik w zmiennej D i końcowy licznik w zmiennej N.

APL jest analizowany od prawej do lewej.

  • Po pierwsze, ciąg jest przechowywany w zmiennej I ( I←).
  • Następnie jest odwzorowywany na wektor boolean wskazujący, gdzie jest kropka, a ten wektor nazywa się P ( P←'.'=). Na przykład „1.2.3” zostanie zamapowane na 0 1 0 1 0.
  • Ten wektor jest cyframi w podstawie 10 ( 10⊥); teraz „1.2.3” to 1010.
  • Następnie odejmuje się 1 od tej liczby (albo z 1-⍨albo z ¯1+, tutaj wybrałem drugi). Teraz „1.2.3” to 1009.
  • Następnie liczba ta jest konwertowana na ciąg znaków ( ), dwie początkowe cyfry są usuwane ( 2↓), co powoduje, że 09 z naszego początkowego przykładu „1.2.3”; ciąg jest odwrócony ( ).
  • Tutaj, jako szczególny przypadek, dodaję początkowy znak 0 przed ciągiem; smutno mi używać czterech znaków, '0',ale zrobiłem to, aby uniknąć błędu, gdy oba pola: drugi i trzeci są puste. Ciąg jest konwertowany z powrotem na liczbę ( ) i jest przechowywany w D, który jest mianownikiem, z wyjątkiem sytuacji, gdy oba ostatnie pola są puste, ponieważ w takim przypadku D jest równe 0.
  • D←D+0=Element zestawu kodu D 1, jeżeli jest to obecnie pusty, a teraz D zawiera mianownik (przed podziałem GCD jednak).
  • Ten mianownik jest mnożony ( ×) przez zawartość początkowego ciągu I aż do drugiej kropki, od (⍎'0',I/⍨2>+\P)której zaczyna się ponownie od P (0 1 0 1 0 w moim przykładzie), dodaje kolejne liczby poprzez ich kumulację (co daje 0 1 1 2 2 w moim przykładzie), sprawdź, które wartości są mniejsze niż 2 (tworząc wektor boolowski 1 1 1 0 0) i przyjmując odpowiednie znaki w I; kolejne 0 jest dodawane przed ciągiem, aby zapobiec kolejnej pułapce (jeśli dwa początkowe pola są puste), a całość jest konwertowana na liczbę.
  • Ostatnia część ciągu wejściowego jest dodawana do poprzedniego produktu (⍎'0',1↓I/⍨2=+\P), który ponownie pobiera P, dodaje, kumulując ponownie, sprawdza, które wartości są równe 2 (patrz poprzednie wyjaśnienie), pobiera znaki, usuwa pierwszy, który jest kropką , dodaje zapobiegający początkowy znak 0 i konwertuje na liczbę.
  • Ten produkt wraz z sumą jest przechowywany w N, który jest licznikiem.
  • Na koniec GCD jest obliczany za pomocą D∨N i obie liczby są dzielone przez ten GCD.

edycja: Oto poprawka dla 73 znaków:

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

Ideą tego hacka jest obliczenie pierwszego przypadku, w którym sumowanie sumaryczne ma wartości równe 2, przechowywanie ich na później i odwracanie tej bitowej maski w celu uzyskania pierwszego przypadku; dlatego obliczenie następnego przypadku wymaga mniej znaków.

edycja: Oto kolejna poprawka dla 69 znaków:

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

Ideą tego hacka jest osadzenie najbardziej skomplikowanego specjalnego przypadku jako kodu APL w ciągu do oceny (na etapie konwersji ciągu na liczbę).

edycja: Oto kolejna poprawka dla 68 znaków:

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

Ideą tego hacka jest zastąpienie dodawania -1 do wartości odejmowania 1 do tej wartości przez operację odejmowania tej wartości do 1, a następnie usunięcie jednego znaku więcej na początku (który będzie znakiem minus).

edycja: Zmiana kosmetyczna:

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

Bez poprawy wielkości, ale bardziej zadowolony z uzyskania maksymalnej funkcji z kodu do oceny.

Thomas Baruchel
źródło
Próbowałem uruchomić to z tryapl.org i narzeka INVALID TOKEN. Wiesz dlaczego?
Peter Taylor
@Peter Taylor: Tak, w mojej wiadomości jest nawet powiedziane; dzieje się tak, ponieważ używam operatora „execute”, który byłby niebezpieczny dla serwera Dyalog i został wyłączony w trybie online (tryb awaryjny). Musisz wypróbować go na zainstalowanej wersji APL Dyalog.
Thomas Baruchel
Ach, szkoda. Nie zamierzam wydawać 60 €, aby móc od czasu do czasu przetestować zgłoszenie PCG. Znalazłem alternatywny tester APL online, ale wydaje się, że w twoim kodzie jest coś specyficznego dla Dyalog, ponieważ daje on błędy rangi lub błędy długości.
Peter Taylor
@Peter Taylor; nie ;-) Proszę, używaj mojej własnej strony internetowej (wciąż eksperymentalnej i nieoficjalnej) z GNU APL; ale musiałem dodać dwa znaki, aby był kompatybilny (nawias wokół jednego I): patrz ten bezpośredni link
Thomas Baruchel
15

Perl 6 (93 101 100 80 68 66 bajtów)

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

Rozmiar został zwiększony, aby nic nie obsługiwać, zamiast po prostu zawodzić. Mouq zaproponował użycie $/, więc teraz jest używane, a kod jest o 20 bajtów krótszy. Ayiko zaproponowano zastąpienie /się , tak, że kod jest nawet krótszy (po 12 bajtów). Następnie Mouq zaproponowała zastąpienie charsz comb(w kontekście numerycznym, są identyczne, ponieważ lista znaków po konwersji do liczby jest liczba znaków).

Przykładowe dane wyjściowe:

$ 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
Konrad Borowski
źródło
Niestety okazuje się, że użycie zera jako symbolu zastępczego między dwiema kropkami jest nie do przyjęcia. 0..09zwraca 1/11, ale 0.0.09zwraca 1/110.
Joe Z.
@JoeZ. No dobrze Zaktualizowałem swój kod, aby obsługiwał przypadek, gdy nic nie jest wpisane.
Konrad Borowski
Nie znam Perla 6, ale czy mam rację, zgadując, że biorąc pod uwagę „abc”, twój program używa dokładnej racjonalnej arytmetyki do obliczenia c / 99 ... 9, ale używa tylko zmiennoprzecinkowej do obliczenia ab? W takim przypadku, jeśli b ma wiele cyfr, da niepoprawną odpowiedź.
Omar
@ OmarAntolín-Camarena: Niezupełnie. W Perlu 6 wymierne są wartości domyślne, a nie liczby zmiennoprzecinkowe. Na przykład 0.1 + 0.2 == 0.3w Perlu 6.
Konrad Borowski
2
Grał w golfa do 80 znaków: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq
6

J ( 85 90 89 znaków)

Moja pierwotna funkcja, która była o 5 znaków krótsza od drugiej, zawierała kilka błędów: nie wyświetlała liczb całkowitych jako „n / 1” i dawała błędną odpowiedź na liczbach zawierających więcej niż kilkanaście cyfr. Oto poprawiona funkcja w J, która zawiera także sugestię Eelvex dotyczącą uratowania postaci:

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

Otrzymuje ciąg i zwraca ciąg. Oto przykładowa sesja:

   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
Omar
źródło
Powinieneś naprawić swoją funkcję do wyjścia 0/1i 3/1inf pierwszych dwóch przypadków testowych, Zobacz ten komentarz
mniip
Naprawiłem wyjście liczb całkowitych kosztem 5 znaków, @mniip.
Omar
Użyj ('0','x',~])i zapisz bajt.
Eelvex
5

C 171

Dosyć długo. Można jeszcze bardziej zmniejszyć. Nie scanf, co naprawdę nie poradzi sobie, jeśli między kropkami nie ma żadnych liczb. Nie strtol. Po prostu chrupanie liczb:

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);}

Test:

rfc <<< "2..142857"
15/7
orion
źródło
5

DC (nie w pełni ogólny, skrócony do 76 znaków)

Nie do końca ogólne, ale proszę, pomyśl, że zrobiłem to z jedną z najstarszych rzeczy na świecie:

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

Edytuj: edytuję swoje rozwiązanie; nie jest bardziej ogólny, ale nieco krótszy:

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

Użyj go jako:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • Pierwsze pole nie jest wymagane:

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

    jest OK

  • Pole drugie i pragnienie wymagają co najmniej jednej cyfry

Thomas Baruchel
źródło
5

JavaScript, 203

Zbyt długo, ale nadal fajnie. Nowe linie, ponieważ średniki są nieczytelne.

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
Tomsmeding
źródło
Dostaję, 889/NaNkiedy biegnę 5.3.87... Czy robię coś złego?
rafaelcastrocouto
Nie wiem ... Jeśli po prostu wkleję ten kod do konsoli Safari (Firefox lub Chrome też powinien to zrobić), naciśnij Enter i wpisz „5.3.87”, po prostu dostanę się "889/165"do konsoli. Jak to działa? @rafaelcastrocouto
tomsmeding
nieważne ... Chyba zrobiłem coś złego, ponieważ teraz działa ...
rafaelcastrocouto
1
Możesz uratować 1 postać, przesuwając b=1część do środka 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 (inna metoda)

Kolejne rozwiązanie oparte na zupełnie innej metodzie; tym razem jest to w pełni ogólne; brakuje tylko 1-mianownika, gdy podana jest liczba całkowita:

   ".((({.~(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
Thomas Baruchel
źródło
3

GolfScript (67 znaków)

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

Uwaga: Obsługuje puste części całkowite.

Jeżeli łańcuch ma postać 'n.p.q'to wartość jest n + p/E + q/(DE) = ((nD + p)E + q)/DEgdzie D = 10^(len p)i E = 10^(len q) - 1, z wyjątkiem przypadku len q = 0, w tym przypadku E = 1(w celu uniknięcia dzielenie przez 0).

Sekcja:

           # 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

Demo online, które symuluje uruchamianie programu z każdym wejściem testowym, pojedynczo.

Peter Taylor
źródło
Wypróbowałem to i wydaje się, że nie przestrzega wszystkich zasad: „Zauważ, że kończenie miejsc dziesiętnych nie będzie miało nic po drugiej kropce, a ułamki dziesiętne bez powtarzającej się części dziesiętnej nie będą miały nic między dwiema kropkami”. Nie mogłem sprawić, by Twój kod działał przy użyciu danych wejściowych0.1.
Thomas Baruchel
-1. Ponownie spróbowałem po tym, jak zauważyłeś, że masz +300 punktów. To niesprawiedliwe, ponieważ inne rozwiązania starały się przestrzegać wszystkich zasad, których oczywiście nie przestrzegałeś.
Thomas Baruchel
@ ברוכאל, sprzeciwiam się twojemu twierdzeniu, że nie próbowałem przestrzegać zasad. Położenie opcjonalnych przypadków testowych pomieszało mnie z myśleniem, że ostatni blok obejmował wszystkie wymagane przypadki; okazuje się, że się myliłem i wkrótce zmienię pytanie, aby inni nie popełnili tego samego błędu. Zaktualizowałem teraz mój kod, aby obsługiwał wcześniej nieobsługiwane przypadki narożników, i zaktualizowałem mój link do testu, aby to wykazać.
Peter Taylor
W porządku. Prawdopodobnie zasługujesz na 300 punktów. Będąc nowym w CodeGolf, te 300 punktów było dla mnie trudnym celem i nadal jestem rozczarowany, że ich nie otrzymałem, podczas gdy wciąż myślę, że w terminie mój kod był najkrótszy, aby idealnie pasował do reguł. W każdym razie mam całe życie na zdobywanie punktów. Pozdrowienia.
Thomas Baruchel
@ ברוכאל: Chciałem zacząć 500 punktów (tak, jestem hojny, nie jest tak, że mogę dać mniej) nagrodę i dać ci te punkty, ale myślę, że już rozpoczęto nagrodę. Cóż, cokolwiek. Zastanawiam się, kiedy ta nagroda się skończy i kto zdobędzie te punkty.
Konrad Borowski
2

Pyton

Brak bibliotek - 156 znaków

_=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)

Używanie fractions- 127 znaków

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))
Oberon
źródło
W fractionsdrukuje wersja rzeczy jak „frakcja (7, 5)” zamiast „7/5”, prawda?
Omar
Nie; Nawiasem mówiąc, nie działam na pierwszym miejscu. _=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, printużywa, strgdy jest dostępna, a nie repr. Oto wynik na moim końcu: puu.sh/7w64w.png
Oberon
@tomsmeding Oba są w jednej linii; podział linii został dodany, aby pasowały do ​​odpowiedzi. _=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)powinny iść wszystkie w jednej linii.
Oberon,
No tak, @Oberon, jak zapewne można się domyślić, nie byłem przy komputerze i nie mogłem uruchomić kodu.
Omar,
2

Mathematica, 143

Jak zwykle Mathematica oferuje wiele funkcji wysokiego poziomu do wykonania zadania, ale nadaje im pełne nazwy.

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)

Przykładowe dane wyjściowe zostaną dodane później, gdy będę miał czas.

Jonathan Van Matre
źródło
Wydaje mi się, że to wypisuje liczby całkowite jako n, a nie n / 1. Czy to prawda? (Moje rozwiązanie ma ten sam błąd ... :()
Omar
Ach, teraz widzę .... określone w komentarzach. Co za dziwny wymóg ... jeśli każda inna frakcja jest zmniejszona, dlaczego nie pozwolić n/1na redukcję n? Dodam dodatkowe ~ 50 bajtów, aby później przekonwertować liczby całkowite.
Jonathan Van Matre
Twoje podejście jest w porządku. Mój wykorzystuje, FromDigitswięc postanowiłem go opublikować.
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

To mój pierwszy eksperyment z rubinem, więc sugeruj ulepszenia.

$ 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
mniip
źródło
Usunięcie obsługi „..” i „.1.2” oznacza, że ​​nie postępujesz zgodnie ze specyfikacją, prawda? (Wolałbym również ją usunąć.)
Omar
@ OmarAntolín-Camarena Na dany punkt, spec mówi If you wish. Nie chcę, więc nie obsługuję ułamków bez pierwszej lub trzeciej grupy cyfr. Popieram jednak ułamki pozbawione drugiej grupy cyfr, która pasuje do specyfikacji.
mniip
@minip, źle odczytałeś specyfikację: nie mówi „jeśli chcesz, możesz wesprzeć .. i .1.2”, mówi: „jeśli chcesz, możesz założyć, że 0 .. i 0.1.2 są zawsze podawane jako .. i .1.2 ".
Omar
@ OmarAntolín-Camarena Punkt zajęty. Edytowany.
mniip
2

C, 164

Jest to podobne do rozwiązania C Oriona, mimo że zrobiłem to od zera. Przyznaję jednak, że kradną wiele jego optymalizacji. Nie jest dużo krótszy, ale obsługuje 0,25. = 1/4 i 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);}
Florian F.
źródło
2

Dwie odpowiedzi na python bez bibliotek. Pierwszy obsługuje opcjonalne wprowadzanie bez cyfry przed pierwszym. i ma 162 znaki

_=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)

Drugi nie obsługuje niczego przed pierwszą cyfrą, ale poprawnie obsługuje wszystkie wymagane dane wejściowe i ma 150 znaków

_=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)
schody 27
źródło
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
PyRulez
źródło
Hej, to jest golfowy kod, nawet nie próbujesz!
mniip
@mniip Nie jestem dobry w golfie kodu. Przynajmniej użyłem nazw zmiennych jednoznakowych.
PyRulez
1
Nigdy nie podałeś języka ani całkowitej liczby użytych znaków / bajtów.
Justin Fay
2
Użyj {;}, aby zaoszczędzić miejsce na wcięciach, spanzaimplementować s, dodać krótkie aliasy dla funkcji, w miarę możliwości usunąć miejsce. 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 znaków, w dół od 321. NB Truejest synonimem otherwise, null zjestlength 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)

Chociaż nie jest to wyraźny zwycięzca nagrody za 300, to jest najkrótszy z możliwych:

  • Zmiany w stosunku do poprzedniej wersji: niewielka zmiana w logice i zmiany w Pfunkcji Mocy poprzez zmianę na +("1e"+a)zamiast Math.pow(10,a)zapisywania kilku dodatkowych znaków ...
WallyWest
źródło
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]

Większość rutyny zajmuje się masowaniem danych wejściowych. Około 50 znaków poszło na obsługę liczb całkowitych.


Przykłady

f["7801.098.765"]

frac1

Więcej przykładów:

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


Jak to normalnie można osiągnąć w Mathematica

FromDigitsmoże otrzymać ułamek bezpośrednio z powtarzającego się powtarzającego się miejsca po przecinku, pod warunkiem, że dane wejściowe mają określoną postać. Liczby całkowite są wyświetlane jako liczby całkowite.

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

DavidC
źródło
Twoje wyjście jest w niewłaściwym formacie, jest zbyt ładne.
Omar
O dziwo, jest to domyślny format wyrażania ułamków zwykłych w Mathematica. Zmiana tego formatu na prostszy wymagałaby kilku kolejnych znaków.
DavidC
1

J (96 znaków)

Nie używam symbolu ukośnika jako separatora (ale rozwiązanie w Mathematica też tego nie robi, ponieważ używa graficznej reprezentacji, która i tak jest lepsza); w języku J ułamek wyświetlany jest rzamiast jako /:

   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '1..3'
4r3
   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '123.456.789'
41111111r333000
Thomas Baruchel
źródło
1

APL (nie w pełni ogólny)

Nie do końca ogólne (jak moje rozwiązanie dla DC); współpracuje z Dyalog APL (ale nie w wersji online Dyalog APL, nie wiem dlaczego):

(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'

Pierwsze pole jest opcjonalne, ale co najmniej jedna cyfra jest wymagana dla obu pozostałych pól.

Thomas Baruchel
źródło
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)

Przykład:

Wkład:

5.3.87

Wydajność:

889/165
kitcar2000
źródło
1

C (420 znaków jak napisano; mniej po usunięciu niepotrzebnych białych znaków)

Zauważ, że zakłada to 64-bit long(np. 64-bitowy Linux); nie powiedzie się w przypadku testowym 0.2.283950617w systemach używających 32-bitów long. Można to naprawić kosztem niektórych znaków, zmieniając odpowiednio typ long longi printfciąg formatu.

#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);
}
celtschk
źródło
Miły. Możesz ogolić 1 postać, zmieniając '0'na 48.
Todd Lehman
Myślę, że możesz także zaoszczędzić jeszcze kilka, przepisując switchinstrukcję jako 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

Przykład

?3.25.
            13/4
Timtech
źródło
4
Dopóki kompilator nie zostanie udostępniony za darmo dla tego języka, będę głosować za każdą odpowiedzią, która go używa.
Gareth
1
Wydaje się, że na powyższej stronie znajduje się kompilator?
skibrianski
@skibrianski Zobacz ten post na meta
mniip
2
@Gareth, istnieje również kilka odpowiedzi Mathematica, które możesz głosować. : P
Omar
2
@ OmarAntolín-Camarena Istnieje kompilator / tłumacz dla Mathematica. GTB nie ma. Kliknij GTBlink powyżej, jeśli mi nie wierzysz. Dostaniesz skompresowane pliki do zastrzeżonego programu, a następnie poszukasz tego programu i zobaczysz, że strona, która twierdzi, że zapewnia pobieranie, twierdzi, że nie jest dostępna. Jak to skompilujemy?
Gareth