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
fuente
9/99
?(in lowest terms)
es decir, la fracción debe ser simplificada.13
lugar de13/1
?1.9999...
y salida2/1
1.9999.
es19999/10000
, para satisfacer2/1
tus necesidades1..9
, ¿no?Respuestas:
Dyalog APL (
75736968 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: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.
I←
).P←'.'=
). Por ejemplo, '1.2.3' se asignará a 0 1 0 1 0.10⊥
); ahora '1.2.3' es 1010.1-⍨
o con¯1+
, aquí elegí el segundo). Ahora '1.2.3' es 1009.⍕
), se eliminan dos dígitos iniciales (2↓
), lo que hace que 09 sea nuestro ejemplo inicial '1.2.3'; la cadena se invierte (⌽
).'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.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).×
) 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.(⍎'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.editar: Aquí hay una solución para 73 caracteres:
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:
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:
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:
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.
fuente
INVALID TOKEN
. ¿Sabes por qué?I
): vea este enlace permanentePerl 6 (
93101100806866 bytes)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
chars
concomb
(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:
fuente
0..09
vuelve1/11
, pero0.0.09
vuelve1/110
.0.1 + 0.2 == 0.3
en Perl 6.$/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude
:)J (
859089 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:
Recibe una cadena y devuelve una cadena. Aquí hay una sesión de muestra:
fuente
0/1
e3/1
inflar los dos primeros casos de prueba. Vea este comentario('0','x',~])
y guarda un byte.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 sestrtol
. Solo números:Prueba:
fuente
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:
Editar: edito mi solución; No es más general, pero un poco más corto:
Úselo como:
El primer campo no es obligatorio:
está bien
El segundo y primer campo requieren al menos un dígito
fuente
Javascript, 203
Demasiado tiempo, pero sigue siendo divertido. Nuevas líneas porque los puntos y comas son ilegibles.
fuente
889/NaN
cuando corro5.3.87
... ¿Estoy haciendo algo mal?"889/165"
en la consola. Como lo estas ejecutando @rafaelcastrocoutob=1
parte dentroprompt()
.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
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:
fuente
GolfScript (67 caracteres)
NB Esto admite partes enteras vacías.
Si la cadena tiene la forma,
'n.p.q'
entonces el valor esn + p/E + q/(DE) = ((nD + p)E + q)/DE
dóndeD = 10^(len p)
yE = 10^(len q) - 1
, excepto cuándolen q = 0
, en cuyo casoE = 1
(para evitar la división por 0).Disección:
Demostración en línea que simula ejecutar el programa con cada una de las entradas de prueba, una a la vez.
fuente
0.1.
Pitón
Sin bibliotecas: 156 caracteres
Usando
fractions
- 127 caracteresfuente
fractions
versión imprime cosas como "Fracción (7, 5)" en lugar de "7/5", ¿no?_=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
print
utilizastr
cuando está disponible, norepr
. Esta es la salida de mi lado: puu.sh/7w64w.png_=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.Mathematica, 143
Como de costumbre, Mathematica ofrece muchas funciones de alto nivel para hacer el trabajo, pero les da nombres detallados.
Salida de muestra que se agregará más tarde cuando tenga tiempo.
fuente
n/1
reducir an
? Agregaré los ~ 50 bytes adicionales para convertir enteros más tarde.FromDigits
así que decidí publicarlo también.Ruby - 112
Este es mi primer experimento con rubí, así que siéntete libre de sugerir mejoras.
fuente
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.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.
fuente
Dos respuestas de Python sin bibliotecas. Primero maneja la entrada opcional sin un dígito antes del primero. y es de 162 caracteres
El segundo no maneja nada antes del primer dígito, pero maneja todas las entradas requeridas correctamente y tiene 150 caracteres
fuente
Haskell
fuente
span
implementar 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. NBTrue
es sinónimo deotherwise
,null z
eslength z==0
JavaScript (ECMAScript 6)
180175Si bien no es un ganador claro para la recompensa de 300 ... este es el más corto que puedo encontrar:
P
función Power al alterarla en+("1e"+a)
lugar deMath.pow(10,a)
guardar algunos caracteres más ...fuente
Mathematica 175
La mayor parte de la rutina va a masajear la entrada. Aproximadamente 50 caracteres fueron para manejar enteros.
Ejemplos
Más ejemplos:
Cómo se lograría normalmente en Mathematica
FromDigits
puede 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.fuente
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
r
como/
:fuente
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é):
El primer campo es opcional, pero se requiere al menos un dígito para los otros dos campos.
fuente
JavaScript (189)
Ejemplo:
Entrada:
Salida:
fuente
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 prueba0.2.283950617
en sistemas que usan 32 bitslong
. Esto se puede solucionar a costa de algunos caracteres cambiando el tipo along long
y cambiando elprintf
cadena de formato en consecuencia.fuente
'0'
a48
.switch
declaración comoif(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;
.GTB , 81
Ejemplo
fuente
GTB
enlace 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?