Convertir un decimal repetido en una fracción

23

Esta pregunta no necesita aplicarse solo a decimales de terminación: los decimales repetidos también se pueden convertir en fracciones a través de un algoritmo.

Su tarea es hacer un programa que tome un decimal repetido como entrada, y generar el numerador y denominador correspondiente (en los términos más bajos) que produce esa expansión decimal. Las fracciones mayores que 1 deben representarse como fracciones impropias como 9/5. Puede suponer que la entrada será positiva.

El decimal repetido se dará en este formato:

5.3.87

con todo después del segundo punto repetido, así:

5.3878787878787...

Su programa generará dos enteros que representan el numerador y el denominador, separados por una barra diagonal (o la forma equivalente en su idioma si no genera texto sin formato):

889/165

Tenga en cuenta que los decimales finales no tendrán nada después del segundo punto, y los decimales sin una porción decimal no repetida no tendrán nada entre los dos puntos.

Casos de prueba

Estos casos de prueba cubren todos los casos de esquina requeridos:

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

Si lo desea, también puede suponer que las fracciones sin partes enteras no tienen nada a la izquierda del primer punto. Puede probar eso con estos casos de prueba opcionales:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1
Joe Z.
fuente
1
¿Es necesario simplificar la fracción? ¿O es razonable dejarlo en una forma no simplificada (por ejemplo:) 9/99?
Justin
3
(in lowest terms)es decir, la fracción debe ser simplificada.
Joe Z.
2
¿Se me permite salir en 13lugar de 13/1?
mniip
44
Asegúrese de manejar esta entrada 1.9999...y salida2/1
Thomas Eding
3
@ThomasEding 1.9999.es 19999/10000, para satisfacer 2/1tus necesidades 1..9, ¿no?
Qwertiy

Respuestas:

8

Dyalog APL ( 75 73 69 68 caracteres)

Aquí hay otro y quinto intento (muy probablemente el último); Pasé el día tratando de escribir un fragmento de código de menos de 80 caracteres y ser totalmente coherente con las reglas. Este desafío me alegró el día!

Finalmente obtuve una línea de APL hecha de 75 caracteres, trabajando con Dyalog APL (pero no en la página de intérprete en línea porque usando la función de ejecución ), que es la siguiente:

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

Por supuesto, podría hacerlo un poco más corto, pero los casos especiales en los que faltan uno, dos o tres campos. Mi código incluso puede manejar el ..caso de entrada.

Sé que APL es difícil de leer, y dado que a la gente le gusta entender cómo funciona realmente un código, aquí hay algunas explicaciones. Básicamente, calculo el denominador final en la variable D y el numerador final en la variable N.

APL se analiza de derecha a izquierda.

  • Primero, la cadena se almacena en la variable I ( I←).
  • Luego se asigna a un vector de booleanos que indica dónde está un punto, y este vector se llama P ( P←'.'=). Por ejemplo, '1.2.3' se asignará a 0 1 0 1 0.
  • Este vector es dígitos en base 10 ( 10⊥); ahora '1.2.3' es 1010.
  • Entonces 1 se resta de este número (ya sea con 1-⍨o con ¯1+, aquí elegí el segundo). Ahora '1.2.3' es 1009.
  • Luego, este número se convierte en una cadena ( ), se eliminan dos dígitos iniciales ( 2↓), lo que hace que 09 sea nuestro ejemplo inicial '1.2.3'; la cadena se invierte ( ).
  • Aquí, como un caso especial, agrego un carácter inicial 0 delante de la cadena; Me entristece usar los cuatro caracteres, '0',pero lo hice para evitar un error cuando los campos segundo y tercero están vacíos. La cadena se convierte de nuevo en un número ( ) y se almacena en D, que es el denominador, excepto cuando los dos últimos campos están vacíos, porque en ese caso D es igual a 0.
  • El D←D+0=fragmento de código establece D en 1 si actualmente es nulo, y ahora D contiene el denominador (sin embargo, antes de la división GCD).
  • Este denominador se multiplica ( ×) con el contenido de la cadena inicial I hasta el segundo punto con el (⍎'0',I/⍨2>+\P)que comienza desde P nuevamente (0 1 0 1 0 en mi ejemplo), suma los números sucesivos al acumularlos (lo que hace 0 1 1 2 2 en mi ejemplo), verifique qué valores son menores que 2 (haciendo el vector booleano 1 1 1 0 0) y tomando los caracteres correspondientes en I; se agrega otro 0 delante de la cadena para evitar otra trampa (si los dos campos iniciales están vacíos) y el todo se convierte en un número.
  • La última parte de la cadena de entrada se agrega al producto anterior con (⍎'0',1↓I/⍨2=+\P), que toma P nuevamente, agrega acumulando nuevamente, verifica qué valores son iguales a 2 (ver explicación anterior), toma los caracteres, elimina el primero que es un punto , agrega un carácter inicial de prevención 0 y convierte a un número.
  • Este producto seguido de una suma se almacena en N, que es el numerador.
  • Finalmente, el MCD se calcula con D∨N y ambos números se dividen por este MCD.

editar: Aquí hay una solución para 73 caracteres:

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

La idea de este truco es calcular primero el caso en el que la suma acumulativa tiene valores iguales a 2, almacenarlos para más adelante e invertir esta máscara bit a bit para obtener el primer caso; calculando así el siguiente caso necesita menos caracteres.

editar: Aquí hay otra solución para 69 caracteres:

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

La idea de este truco es incorporar el caso especial más complicado como código APL en la cadena a evaluar (en la etapa de conversión de cadena a número).

editar: Aquí hay otra solución para 68 caracteres:

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

La idea de este truco es reemplazar la suma de -1 al valor para restar 1 a ese valor mediante la operación restando ese valor a 1 y luego eliminar un carácter más al principio (que será el signo menos).

editar: cambio cosmético:

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

No mejora el tamaño, pero está más satisfecho de obtener la máxima función del código que se va a evaluar.

Thomas Baruchel
fuente
Intenté ejecutar esto con tryapl.org y se queja INVALID TOKEN. ¿Sabes por qué?
Peter Taylor
@ Peter Taylor: Sí, incluso se dice en mi mensaje; Esto se debe a que uso el operador "Ejecutar", que no sería seguro para el servidor de Dyalog y se ha desactivado en línea (modo seguro). Tienes que probarlo en una versión instalada de Dyalog APL.
Thomas Baruchel
Ah, lástima. No voy a gastar 60 € para poder probar una presentación PCG ocasional. He encontrado un probador de APL en línea alternativo, pero parece que hay algo específico de Dyalog en su código porque da errores de rango o errores de longitud.
Peter Taylor
@Peter Taylor; no ;-) Por favor, use mi propio sitio web (todavía experimental y no oficial) con GNU APL; pero tuve que agregar dos caracteres para que sea compatible (paréntesis alrededor de uno I): vea este enlace permanente
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

Se aumentó el tamaño para no manejar nada, en lugar de simplemente fallar. Mouq propuso su uso $/, por lo que ahora se está utilizando y el código es 20 bytes más corto. Ayiko propuso sustituir /con , por lo que el código es aún más corta (por 12 bytes). Luego Mouq propuso reemplazar charscon comb(en contexto numérico, son idénticos, porque la lista de caracteres después de la conversión a número es el número de caracteres).

Salida de muestra:

$ 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
fuente
Desafortunadamente, resulta que usar cero como marcador de posición entre dos puntos es una opción prohibida. 0..09vuelve 1/11, pero 0.0.09vuelve 1/110.
Joe Z.
@JoeZ. Oh ok Actualicé mi código para manejar el caso cuando no se escribe nada.
Konrad Borowski el
No sé Perl 6, pero ¿estoy en lo cierto al adivinar que dado 'abc', su programa usa aritmética racional exacta para calcular c / 99 ... 9, pero solo usa punto flotante para calcular ab? En ese caso, si b tiene muchos dígitos, dará una respuesta incorrecta.
Omar
@ OmarAntolín-Camarena: No del todo. En Perl 6, los racionales son predeterminados, no los números de coma flotante. Por ejemplo, 0.1 + 0.2 == 0.3en Perl 6.
Konrad Borowski
2
Golfed a 80 caracteres: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq
6

J ( 85 90 89 caracteres)

Mi función original, que era 5 caracteres más corta que la segunda, tenía un par de errores: no generaba enteros como "n / 1" y daba la respuesta incorrecta en números con más de una docena de dígitos. Aquí hay una función corregida en J que también incorpora la sugerencia de Eelvex para guardar un personaje:

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

Recibe una cadena y devuelve una cadena. Aquí hay una sesión de muestra:

   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
fuente
Debería arreglar su función para generar 0/1e 3/1inflar los dos primeros casos de prueba. Vea este comentario
mniip
Arreglé la salida para enteros al costo de 5 caracteres, @mniip.
Omar
Usa ('0','x',~])y guarda un byte.
Eelvex
5

C, 171

Bastante largo. Podría reducirse aún más. No scanf, lo que realmente no puede manejar si no hay números entre los puntos. No se strtol. Solo números:

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

Prueba:

rfc <<< "2..142857"
15/7
Orión
fuente
5

DC (no totalmente general, acortado a 76 caracteres)

No del todo general, pero por favor, considere que lo hice con una de las cosas más antiguas del mundo:

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

Editar: edito mi solución; No es más general, pero un poco más corto:

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

Úselo como:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • El primer campo no es obligatorio:

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

    está bien

  • El segundo y primer campo requieren al menos un dígito

Thomas Baruchel
fuente
5

Javascript, 203

Demasiado tiempo, pero sigue siendo divertido. Nuevas líneas porque los puntos y comas son ilegibles.

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
fuente
Me da 889/NaNcuando corro 5.3.87... ¿Estoy haciendo algo mal?
rafaelcastrocouto
No sé ... Si solo pego este código en la consola de Safari (Firefox o Chrome también deberían hacerlo), presiono enter y escribo "5.3.87", solo entro "889/165"en la consola. Como lo estas ejecutando @rafaelcastrocouto
tomsmeding
No importa ... supongo que hice algo mal, ya que está trabajando ahora ...
rafaelcastrocouto
1
Puede guardar 1 personaje moviendo la b=1parte dentro 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 (método diferente)

Otra solución basada en un método muy diferente; esta vez es completamente general; solo falta el denominador 1 cuando se envía un entero:

   ".((({.~(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
fuente
3

GolfScript (67 caracteres)

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

NB Esto admite partes enteras vacías.

Si la cadena tiene la forma, 'n.p.q'entonces el valor es n + p/E + q/(DE) = ((nD + p)E + q)/DEdónde D = 10^(len p)y E = 10^(len q) - 1, excepto cuándo len q = 0, en cuyo caso E = 1(para evitar la división por 0).

Disección:

           # 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

Demostración en línea que simula ejecutar el programa con cada una de las entradas de prueba, una a la vez.

Peter Taylor
fuente
Lo intenté, y no parece seguir todas las reglas: "Tenga en cuenta que los decimales finales no tendrán nada después del segundo punto, y los decimales sin una porción decimal no repetida no tendrán nada entre los dos puntos". No pude hacer que tu código funcionara con la entrada de entrada0.1.
Thomas Baruchel
-1. Lo volví a intentar otra vez después de haber notado que obtuviste los +300 puntos. No es justo, porque otras soluciones han hecho todo lo posible para seguir todas las reglas, lo que obviamente no ha hecho.
Thomas Baruchel
@ ברוכאל, me opongo a su afirmación de que no he tratado de seguir las reglas. La posición de los casos de prueba opcionales me confundió al pensar que el bloque final cubría todos los casos requeridos; Resulta que estaba equivocado, y voy a editar la pregunta en breve para evitar que otras personas cometan el mismo error. Ahora he actualizado mi código para manejar los casos de esquina no manejados previamente, y actualicé mi enlace a una prueba para demostrarlo.
Peter Taylor
está bien. Probablemente mereces los 300 puntos. Al ser nuevo en CodeGolf, estos 300 puntos fueron un objetivo desafiante para mí, y todavía estoy decepcionado de no haberlos recibido, mientras sigo pensando que en el tiempo límite mi código era el más corto para cumplir perfectamente las reglas. De todos modos, tengo toda mi vida para ganar puntos. Saludos.
Thomas Baruchel
@ ברוכאל: Quería comenzar 500 puntos (sí, soy generoso así, no es que pueda dar menos) recompensa, y darte esos puntos, pero supongo que ya ha comenzado una recompensa. Bueno lo que sea. Me pregunto cuándo terminará esta recompensa y quién obtendrá esos puntos.
Konrad Borowski
2

Pitón

Sin bibliotecas: 156 caracteres

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

Usando fractions- 127 caracteres

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
fuente
La fractionsversión imprime cosas como "Fracción (7, 5)" en lugar de "7/5", ¿no?
Omar
No lo hace; Por cierto, no estoy haciendo que el mejor funcione. _=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, printutiliza strcuando está disponible, no repr. Esta es la salida de mi lado: puu.sh/7w64w.png
Oberon
@tomsmeding Ambos están en una línea; se agregó el salto de línea para que encajen en la respuesta. _=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)debería ir todo en una línea.
Oberon
Ah, claro, @Oberon, como probablemente puedas adivinar que no estaba en mi computadora y no podía ejecutar el código.
Omar
2

Mathematica, 143

Como de costumbre, Mathematica ofrece muchas funciones de alto nivel para hacer el trabajo, pero les da nombres detallados.

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)

Salida de muestra que se agregará más tarde cuando tenga tiempo.

Jonathan Van Matre
fuente
Me parece que esto genera enteros como n, en lugar de n / 1. ¿Está bien? (Mi solución tiene el mismo error ... :()
Omar
Ah, ahora veo ... especificado en los comentarios. Qué requisito tan extraño ... si se reduce cualquier otra fracción, ¿por qué no permitir n/1reducir a n? Agregaré los ~ 50 bytes adicionales para convertir enteros más tarde.
Jonathan Van Matre
Tu enfoque está bien. El mío hace uso, FromDigitsasí que decidí publicarlo también.
DavidC
2

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

Este es mi primer experimento con rubí, así que siéntete libre de sugerir mejoras.

$ 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
fuente
Eliminar el soporte ".. 'y" .1.2 "significa que no estás siguiendo las especificaciones, ¿verdad? (Preferiría eliminarlas también.)
Omar
@ OmarAntolín-Camarena En ese punto en particular, la especificación dice If you wish. No deseo, así que no estoy admitiendo fracciones sin el primer o tercer grupo de dígitos. Sin embargo, estoy apoyando fracciones que carecen del segundo grupo de dígitos, que coincide con la especificación.
mniip
@minip, leyó mal la especificación: no dice "si lo desea puede apoyar ... y .1.2", dice: "si lo desea, puede suponer que 0 .. y 0.1.2 siempre se dan como .. y .1.2 ".
Omar
@ OmarAntolín-Camarena Punto tomado. Editado
mniip
2

C, 164

Esto es similar a la solución C de Orion, aunque lo hice desde cero. Sin embargo, confieso que robé varias de sus optimizaciones. No es mucho más corto, pero maneja .25. = 1/4 y 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
fuente
2

Dos respuestas de Python sin bibliotecas. Primero maneja la entrada opcional sin un dígito antes del primero. y es de 162 caracteres

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

El segundo no maneja nada antes del primer dígito, pero maneja todas las entradas requeridas correctamente y tiene 150 caracteres

_=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)
escalera27
fuente
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
fuente
Oye, esto es código golf, ¡ni siquiera lo estás intentando!
mniip
@mniip No soy bueno en el código de golf. Al menos usé nombres de variables de un solo carácter.
PyRulez
1
Nunca especificó el idioma o la cantidad total de caracteres / bytes utilizados.
Justin Fay
2
Use {;} para ahorrar espacio en las sangrías, spanimplementar s, agregar alias cortos para funciones, eliminar espacio donde sea posible. 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 caracteres, por debajo de 321. NB Truees sinónimo de otherwise, null zeslength 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)

Si bien no es un ganador claro para la recompensa de 300 ... este es el más corto que puedo encontrar:

  • Cambios de la versión anterior: alguna ligera alteración de la lógica, y cambios en la Pfunción Power al alterarla en +("1e"+a)lugar de Math.pow(10,a)guardar algunos caracteres más ...
WallyWest
fuente
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]

La mayor parte de la rutina va a masajear la entrada. Aproximadamente 50 caracteres fueron para manejar enteros.


Ejemplos

f["7801.098.765"]

frac1

Más ejemplos:

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


Cómo se lograría normalmente en Mathematica

FromDigitspuede obtener una fracción directamente de un decimal recurrente recurrente, siempre que la entrada sea de una forma particular. Los enteros se muestran como enteros.

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
fuente
Su salida está en el formato incorrecto, es demasiado bonita.
Omar
Curiosamente, este es el formato predeterminado para expresar fracciones en Mathematica. Se necesitarían varios caracteres más para cambiar este formato al más simple.
DavidC
1

J (96 caracteres)

No uso el símbolo de barra como separador (pero la solución en Mathematica tampoco lo hace, ya que usa una representación gráfica que es mejor de todos modos); en lenguaje J, la fracción se muestra rcomo /:

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

APL (no totalmente general)

No completamente general (como mi solución para DC); funciona con Dyalog APL (pero no en la versión en línea de Dyalog APL, no estoy seguro de por qué):

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

El primer campo es opcional, pero se requiere al menos un dígito para los otros dos campos.

Thomas Baruchel
fuente
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)

Ejemplo:

Entrada:

5.3.87

Salida:

889/165
kitcar2000
fuente
1

C (420 caracteres como están escritos; menos después de eliminar espacios en blanco innecesarios)

Tenga en cuenta que esto supone 64 bits long(por ejemplo, Linux de 64 bits); fallará para el caso de prueba 0.2.283950617en sistemas que usan 32 bits long. Esto se puede solucionar a costa de algunos caracteres cambiando el tipo a long longy cambiando elprintf cadena de formato en consecuencia.

#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
fuente
Agradable. Puedes eliminar 1 personaje cambiando '0'a 48.
Todd Lehman
Creo que también podría ahorrar algunos más reescribiendo la switchdeclaración como 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

Ejemplo

?3.25.
            13/4
Timtech
fuente
44
Hasta que un compilador esté disponible gratuitamente para este idioma, rechazaré cada respuesta que lo use.
Gareth
1
Parece que hay un compilador en la página vinculada anteriormente?
skibrianski
@skibrianski Ver esta publicación en meta
mniip
2
@Gareth, también hay un par de respuestas de Mathematica para que desestimes tu voto. : P
Omar
2
@ OmarAntolín-Camarena Hay un compilador / intérprete para Mathematica. GTB no tiene ninguno. Sigue el GTBenlace de arriba si no me crees. Obtendrá algunas cosas comprimidas para un programa propietario, luego buscará ese programa y encontrará que el sitio que dice proporcionar una descarga dice que no está disponible. Entonces, ¿cómo lo compilamos?
Gareth