Converti un decimale ripetuto in una frazione


23

Questa domanda non ha bisogno di applicarsi a decimali solo terminazione - decimali ripetizione possono anche essere convertiti in frazioni tramite un algoritmo.

Il tuo compito è creare un programma che accetta un decimale ripetuto come input e produrre il numeratore e il denominatore corrispondenti (in termini più bassi) che producono quell'espansione decimale. Le frazioni maggiori di 1 dovrebbero essere rappresentate come frazioni improprie come 9/5. Si può presumere che l'input sarà positivo.

Il decimale ripetuto verrà fornito in questo formato:

5.3.87

con tutto dopo il secondo punto ripetuto, in questo modo:

5.3878787878787...

Il tuo programma produrrà due numeri interi che rappresentano il numeratore e il denominatore, separati da una barra (o dalla forma equivalente nella tua lingua se non produci testo semplice):

889/165

Notare che i decimali finali non avranno nulla dopo il secondo punto e che i decimali senza porzione decimale non ripetitiva non avranno nulla tra i due punti.

Casi test

Questi casi di test coprono tutti i casi angolari richiesti:

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

Se lo desideri, puoi anche supporre che le frazioni senza parti intere non abbiano nulla a sinistra del primo punto. Puoi verificarlo con questi casi di test opzionali:

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

1
È necessario semplificare la frazione? O è ragionevole lasciarlo in una forma non semplificata (ad esempio:) 9/99?
Justin

3
(in lowest terms)cioè la frazione deve essere semplificata.
Joe Z.

2
Sono autorizzato a produrre 13invece di 13/1?
mniip,

4
Assicurati di gestire questo input 1.9999...e output2/1
Thomas Eding

3
@ThomasEding 1.9999.è 19999/10000, per farti 2/1avere bisogno 1..9, no?
Qwertiy,

Risposte:


8

Dyalog APL ( 75 73 69 68 caratteri)

Ecco un altro e quinto tentativo (molto probabilmente il mio ultimo); Ho trascorso la giornata cercando di scrivere un pezzo di codice inferiore a 80 caratteri e di essere pienamente coerente con le regole. Questa sfida ha reso la mia giornata!

Alla fine ho ottenuto una riga di APL composta da 75 caratteri, lavorando con Dyalog APL (ma non sulla pagina dell'interprete online perché usando la funzione di esecuzione ), che è la seguente:

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

Ovviamente potrei renderlo un po 'più breve, ma i casi speciali in cui mancano uno, due o tre campi. Il mio codice può persino gestire il ..caso di input.

So che APL è difficile da leggere, e poiché alla gente piace capire come funziona effettivamente un pezzo di codice, ecco alcune spiegazioni. Fondamentalmente, computo il denominatore finale nella variabile D e il numeratore finale nella variabile N.

L'APL viene analizzato da destra a sinistra.

  • Innanzitutto, la stringa è memorizzata nella variabile I ( I←).
  • Quindi viene mappato su un vettore di valori booleani che indica dove si trova un punto e questo vettore si chiama P ( P←'.'=). Ad esempio '1.2.3' verrà mappato su 0 1 0 1 0.
  • Questo vettore è composto da cifre in base 10 (10⊥ ); ora "1.2.3" è 1010.
  • Quindi 1 viene sottratto da questo numero (sia con 1-⍨ o con ¯1+, qui ho scelto il secondo). Ora "1.2.3" è 1009.
  • Quindi questo numero viene convertito in una stringa ( ), vengono rimosse due cifre iniziali (2↓ ), il che rende 09 dal nostro esempio iniziale "1.2.3"; la stringa è invertita ( ).
  • Qui, come caso speciale, aggiungo un carattere 0 iniziale davanti alla stringa; mi rende triste usare i quattro caratteri, '0',ma l'ho fatto per evitare un errore quando il secondo e il terzo campo sono entrambi vuoti. La stringa viene riconvertita in un numero ( ) ed è memorizzata in D, che è il denominatore tranne quando entrambi gli ultimi campi sono vuoti, perché in tal caso D è uguale a 0.
  • Il D←D+0= pezzo di codice imposta D su 1 se è attualmente nullo e ora D contiene il denominatore (prima della divisione GCD).
  • Questo denominatore viene moltiplicato ( ×) per il contenuto della stringa iniziale I fino al secondo punto con(⍎'0',I/⍨2>+\P) quale inizia di nuovo da P (0 1 0 1 0 nel mio esempio), aggiunge i numeri successivi cumulandoli (il che rende 0 1 1 2 2 nel mio esempio), controlla quali valori sono inferiori a 2 (rendendo il vettore booleano 1 1 1 0 0) e prendendo i caratteri corrispondenti in I; un altro 0 viene aggiunto davanti alla stringa per impedire un'altra trap (se i due campi iniziali sono vuoti) e l'intero viene convertito in un numero.
  • L'ultima parte della stringa di input viene aggiunta al prodotto precedente con (⍎'0',1↓I/⍨2=+\P), che prende di nuovo P, aggiunge cumulando di nuovo, controlla quali valori sono uguali a 2 (vedi la spiegazione precedente), prende i caratteri, rimuove il primo che è un punto , aggiunge un carattere iniziale 0 di prevenzione e si converte in un numero.
  • Questo prodotto seguito da una somma è memorizzato in N che è il numeratore.
  • Infine, il GCD viene calcolato con D∨N ed entrambi i numeri sono divisi per questo GCD.

modifica: ecco una correzione per 73 caratteri:

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

L'idea di questo hack è di calcolare prima il caso in cui l'addizione cumulativa ha valori pari a 2, memorizzandoli per dopo e invertendo questa maschera bit a bit per ottenere il primo caso; quindi il calcolo del caso successivo richiede meno caratteri.

modifica: ecco un'altra correzione per 69 caratteri:

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

L'idea di questo hack è quella di incorporare il caso speciale più complicato come codice APL nella stringa da valutare (nella fase di conversione da stringa a numero).

modifica: ecco un'altra correzione per 68 caratteri:

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

L'idea di questo hack è quella di sostituire l' aggiunta di -1 al valore per sottrarre 1 a quel valore con l'operazione sottraendo quel valore a 1, quindi rimuovere un carattere successivo in più all'inizio (che sarà il segno meno).

modifica: cambio cosmetico:

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

Nessun miglioramento dimensionale, ma più soddisfacente per ottenere la massima funzione dal codice da valutare.


Ho provato a eseguirlo con tryapl.org e si lamenta INVALID TOKEN. Sai perché?
Peter Taylor,

@Peter Taylor: Sì, si dice anche nel mio messaggio; questo perché uso l'operatore "esegui" che non sarebbe sicuro per il server di Dyalog ed è stato disabilitato online (modalità sicura). Devi provarlo su una versione installata di Dyalog APL.
Thomas Baruchel,

Ah, vergogna. Non spenderò 60 € per poter testare un invio occasionale di PCG. Ho trovato un tester APL online alternativo, ma sembra che ci sia qualcosa di specifico di Dyalog nel tuo codice perché fornisce errori di rango o errori di lunghezza.
Peter Taylor,

@Peter Taylor; no ;-) Per favore, usa il mio sito web (ancora sperimentale e non ufficiale) con GNU APL; ma ho dovuto aggiungere due personaggi per renderlo compatibile (parentesi attorno a uno I): vedi questo permalink
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 byte)

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

La dimensione è stata aumentata per non gestire nulla, invece di fallire. Mouq ha proposto di utilizzare $/, quindi ora viene utilizzato e il codice è più corto di 20 byte. Ayiko ha proposto di sostituirlo /con , quindi il codice è ancora più breve (di 12 byte). Quindi Mouq ha proposto di sostituirlo charscon comb(in un contesto numerico, sono identici, poiché l'elenco di caratteri dopo la conversione in numero è il numero di caratteri).

Uscita campione:

$ 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

Sfortunatamente, si scopre che usare zero come segnaposto tra due punti è un non-andare. 0..09ritorna 1/11, ma 0.0.09ritorna 1/110.
Joe Z.

@JoeZ. Oh va bene. Ho aggiornato il mio codice per gestire il caso quando non viene digitato nulla.
Konrad Borowski il

Non conosco Perl 6, ma ho ragione nel supporre che dato 'abc', il tuo programma usa l'aritmetica razionale esatta per calcolare c / 99 ... 9, ma usa solo il virgola mobile per calcolare ab? In tal caso, se b ha molte cifre, darà una risposta errata.
Omar

@ OmarAntolín-Camarena: Non proprio. In Perl 6, i razionali sono predefiniti, non numeri in virgola mobile. Ad esempio, 0.1 + 0.2 == 0.3in Perl 6.
Konrad Borowski

2
$/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude
Giocato a golf

6

J ( 85 90 89 caratteri)

La mia funzione originale, che era di 5 caratteri più corta della seconda, aveva un paio di bug: non emetteva numeri interi come "n / 1" e dava la risposta sbagliata sui numeri con più di una dozzina di cifre. Ecco una funzione corretta in J che incorpora anche il suggerimento di Eelvex per salvare un personaggio:

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

Riceve una stringa e restituisce una stringa. Ecco una sessione di esempio:

   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

Dovresti correggere la tua funzione in modo da emettere 0/1e visualizzare i 3/1primi due casi di test, vedi questo commento
mniip

Ho corretto l'output per numeri interi al costo di 5 caratteri, @mniip.
Omar,

Usa ('0','x',~])e salva un byte.
Eelvex,

5

C, 171

Abbastanza lungo. Potrebbe essere ulteriormente ridotto. No scanf, che non può davvero gestirlo se non ci sono numeri tra i punti. No strtol. Solo lo scricchiolio dei numeri:

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

5

DC (non completamente generale, abbreviato a 76 caratteri)

Non del tutto generale, ma per favore, considera che l'ho fatto con una delle cose più antiche del mondo:

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

Modifica: modifica la mia soluzione; non è più generale, ma un po 'più breve:

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

Usalo come:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • Il primo campo non è richiesto:

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

    va bene

  • Il secondo e il campo della sete richiedono almeno una cifra


5

Javascript, 203

Troppo a lungo, ma comunque divertente. Newline perché i punti e virgola sono illeggibili.

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

Ricevo 889/NaNquando corro 5.3.87... Sto facendo qualcosa di sbagliato?
rafaelcastrocouto,

Non lo so ... Se ho appena incollato questo codice nella console Safari (anche Firefox o Chrome dovrebbero farlo), premi invio e digito "5.3.87", accedo semplicemente "889/165"alla console. Come lo stai eseguendo? @rafaelcastrocouto
tomsmeding

non importa ... immagino di aver fatto qualcosa di sbagliato dato che ora funziona ...
rafaelcastrocouto

1
Puoi salvare 1 personaggio spostando la b=1parte all'interno 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 (metodo diverso)

Un'altra soluzione basata su un metodo molto diverso; questa volta è completamente generale; manca solo il denominatore 1 quando viene inviato un numero intero:

   ".((({.~(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 caratteri)

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

NB Questo supporta parti intere vuote.

Se la stringa è nella forma, 'n.p.q'il valore è n + p/E + q/(DE) = ((nD + p)E + q)/DEdove D = 10^(len p)e E = 10^(len q) - 1, tranne quando len q = 0, nel qual caso E = 1(per evitare la divisione per 0).

Dissezione:

           # 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 che simula l'esecuzione del programma con ciascuno degli input di test, uno alla volta.


L'ho provato e non sembra seguire tutte le regole: "Nota che i decimali di terminazione non avranno nulla dopo il secondo punto e i decimali senza una parte decimale non ripetitiva non avranno nulla tra i due punti". Non riuscivo a far funzionare il tuo codice con input essendo0.1.
Thomas Baruchel il

-1. L'ho provato un'altra volta dopo aver notato che hai ottenuto i +300 punti. Non è giusto, perché altre soluzioni hanno fatto del loro meglio per seguire tutte le regole, cosa che ovviamente non hai fatto.
Thomas Baruchel,

@ ברוכאל, mi oppongo alla tua affermazione che non ho provato a seguire le regole. La posizione dei casi di test opzionali mi ha confuso nel pensare che il blocco finale coprisse tutti i casi richiesti; si scopre che mi sbagliavo e ho intenzione di modificare la domanda a breve per evitare che altre persone commettano lo stesso errore. Ora ho aggiornato il mio codice per gestire i casi d'angolo precedentemente non gestiti e ho aggiornato il mio link a un test per dimostrarlo.
Peter Taylor,

va bene. Probabilmente ti meriti i 300 punti. Essendo nuovo di CodeGolf, questi 300 punti sono stati un obiettivo stimolante per me, e sono ancora deluso di non averli ottenuti mentre sto ancora pensando che alla scadenza il mio codice era il più corto per adattarsi perfettamente alle regole. Ad ogni modo, ho tutta la mia vita per vincere punti. Saluti.
Thomas Baruchel,

@ ברוכאל: Volevo iniziare 500 punti (sì, sono generoso in quel modo, non è che posso dare di meno) generosità e darti quei punti, ma immagino che sia già iniziata una generosità. Bene, qualunque cosa. Mi chiedo quando finirà questa generosità e chi otterrà quei punti.
Konrad Borowski il

2

Pitone

Nessuna libreria - 156 caratteri

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

Utilizzando fractions- 127 caratteri

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

La fractionsversione stampa cose come "Frazione (7, 5)" invece di "7/5", non è vero?
Omar,

Non lo fa; A proposito, non sto facendo funzionare quello principale. _=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, printutilizza strquando disponibile, no repr. Questo è l'output dalla mia parte: puu.sh/7w64w.png
Oberon

@tomsmeding Entrambi sono su una riga; l'interruzione di riga è stata aggiunta per adattarli alla risposta. _=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)dovrebbe andare tutto in una riga.
Oberon,

Oh giusto, @Oberon, come probabilmente puoi immaginare che non ero al mio computer e non ho potuto eseguire il codice.
Omar,

2

Mathematica, 143

Come al solito, Mathematica offre molte funzioni di alto livello per svolgere il lavoro, ma dà loro nomi dettagliati.

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)

Uscita di esempio da aggiungere in seguito quando ho tempo.


Mi sembra che questo restituisca numeri interi come n, anziché n / 1. È giusto? (La mia soluzione ha lo stesso bug ... :()
Omar

Ah, ora vedo .... specificato nei commenti. Che strano requisito ... se ogni altra frazione viene ridotta, perché non consentire n/1di ridurla n? Aggiungerò i ~ 50 byte extra per convertire i numeri interi in seguito.
Jonathan Van Matre,

Il tuo approccio va bene. Il mio ne fa uso, FromDigitscosì ho deciso di pubblicarlo anch'io.
DavidC

2

Rubino - 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

Questo è il mio primo esperimento con il rubino, quindi sentiti libero di suggerire miglioramenti.

$ 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

Rimuovere il supporto ".." e ".1.2" significa che non stai seguendo le specifiche, giusto? (Preferirei rimuoverle anch'io.)
Omar

@ OmarAntolín-Camarena su quel particolare punto, le specifiche dice, If you wish. Non desidero, quindi non sto supportando le frazioni senza il 1o o il 3o gruppo di cifre. Sto tuttavia supportando le frazioni che mancano del 2 ° gruppo di cifre, che corrispondono alle specifiche.
mniip,

@minip, hai letto male le specifiche: non dice "se lo desideri puoi supportare .. e .1.2", dice "se lo desideri, puoi presumere che 0 .. e 0.1.2 siano sempre dati come .. e .1.2 ".
Omar,

@ OmarAntolín-Camarena Punto preso. Modificato.
mniip,

2

C, 164

Questo è simile alla soluzione C di Orione, anche se l'ho fatto da zero. Confesso comunque rubando una serie di sue ottimizzazioni. Non è molto più corto, ma gestisce 0,25. = 1/4 e 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

Due risposte di Python senza l'uso di librerie. Innanzitutto gestisce l'input opzionale senza una cifra prima del primo. ed è 162 caratteri

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

Il secondo non gestisce nulla prima della prima cifra ma gestisce correttamente tutti gli input richiesti ed è di 150 caratteri

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

Ehi, questo è code-golf, non ci stai nemmeno provando!
mniip,

@mniip Non sono bravo a code golf. Almeno ho usato nomi di variabili a carattere singolo.
PyRulez,

1
Non hai mai specificato la lingua o la quantità totale di caratteri / byte utilizzati.
Justin Fay,

2
Utilizzare {;} per risparmiare spazio sui rientri, spanper implementare s, aggiungere brevi alias per le funzioni, rimuovere lo spazio ove possibile. 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 caratteri, in calo da 321. NB Trueè sinonimo di otherwise, null zèlength 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)

Anche se non è un chiaro vincitore per le 300 taglie ... questo è il più breve che posso inventare:

  • Modifiche rispetto alla versione precedente: alcune lievi alterazioni della logica e modifiche alla Pfunzione Power modificandola in +("1e"+a)invece di Math.pow(10,a)salvare quindi qualche altro carattere ...

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]

Gran parte della routine va a massaggiare l'input. Circa 50 caratteri sono andati alla gestione di numeri interi.


Esempi

f["7801.098.765"]

frac1

Altri esempi:

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


Come sarebbe normalmente realizzato in Mathematica

FromDigitspuò ottenere una frazione direttamente da un decimale ricorrente ricorrente, a condizione che l'input abbia una forma particolare. I numeri interi vengono visualizzati come numeri interi.

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


Il tuo output è nel formato sbagliato, è troppo bello.
Omar,

Stranamente, questo è il formato predefinito per esprimere le frazioni in Mathematica. Occorrerebbero molti più caratteri per cambiare questo formato in uno più semplice.
DavidC

1

J (96 caratteri)

Non uso il simbolo della barra come separatore (ma la soluzione in Mathematica non lo fa nemmeno perché utilizza una rappresentazione grafica che è comunque migliore); in J la frazione viene visualizzata con rinvece come /:

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

1

APL (non completamente generale)

Non del tutto generale (come la mia soluzione per dc); funziona con Dyalog APL (ma non sulla versione online di Dyalog APL, non so perché):

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

Il primo campo è facoltativo, ma è necessaria almeno una cifra per entrambi gli altri campi.


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)

Esempio:

Ingresso:

5.3.87

Produzione:

889/165

1

C (420 caratteri come scritto; meno dopo aver rimosso gli spazi bianchi non necessari)

Si noti che ciò presuppone 64 bit long(ad esempio Linux a 64 bit); fallirà per il test case 0.2.283950617su sistemi che usano 32 bit long. Questo può essere risolto al costo di alcuni caratteri cambiando il tipo in long longe cambiando la printfstringa di formato di conseguenza.

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

Bello. Puoi radere 1 personaggio cambiando '0'in 48.
Todd Lehman,

Penso che potresti anche risparmiare qualche altro riscrivendo la switchdichiarazione come 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

Esempio

?3.25.
            13/4

4
Fino a quando un compilatore non sarà reso disponibile gratuitamente per questa lingua, declasserò ogni risposta che la utilizza.
Gareth,

1
Sembra che ci sia un compilatore sulla pagina collegata sopra?
skibrianski,

@skibrianski Vedi questo post su meta
mniip il

2
@Gareth, ci sono anche un paio di risposte di Mathematica da sottovalutare. : P
Omar

2
@ OmarAntolín-Camarena C'è un compilatore / interprete per Mathematica. GTB non ne ha. Segui il GTBlink qui sopra se non mi credi. Otterrai alcune cose compresse per un programma proprietario, quindi cercherai quel programma e scoprirai che il sito che afferma di fornire un download dice che non è disponibile. Quindi, come lo compiliamo?
Gareth,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.