Simplifica una fracción

8

Ganador: la respuesta de Ian D. Scott , ¡por un byte (48 bytes)! ¡Soberbio!

Su programa debe aceptar la entrada de una fracción que se puede simplificar, luego simplificarla.

Reglas:

  • Si la fracción ya está en su forma más simplificada, debe informar al usuario
  • No hay funciones integradas para hacer esto
  • El usuario debe escribir el número en algún momento, sin embargo, el método que lea el programa no importa. Puede ser con stdin, console.readline, etc. Siempre que el usuario escriba 9/18(por ejemplo) en algún momento, es válido
  • La salida debe hacerse con stdout, console.writeline, etc.
  • La fracción se pondrá como x/y, y debe salir comoa/b
  • La fracción debe generar la forma más simplificada. Por ejemplo, 8/12 -> 6/9 no es válido , la única solución válida es 2/3.

  • Este concurso finaliza el 9 de agosto de 2014 (7 días desde su publicación)
  • Esta es una pregunta de , por lo que gana el código más corto
Jon
fuente
1
¿Cómo debemos informar al usuario?
bebe
Stdout, console.writeline, etc.
Jon
77
Este es realmente un problema bastante trivial. Todo lo que debe hacer es dividir por el mcd (una función que a menudo está integrada pero que no sería difícil de escribir).
Aficiones de Calvin
1
@ Calvin'sHobbies Sí, el problema en sí mismo es trivial. Hacerlo en la menor cantidad de código no es tan fácil.
Jon
3
¿Qué quiere decir con "Si la fracción ya está en su forma más simplificada, debe informar al usuario"? ¿Debería haber un mensaje específico aparte de simplemente devolver la entrada? Si es así, no la respuesta aceptada satisface esto.
Martin Ender

Respuestas:

1

Python - 69 48

Lo primero que debe hacer es representarlo en el formato nativo de Python para almacenar fracciones, es decir, la clase Fraction.

print(__import__("fractions").Fraction(input()))

Ahora simplificamos ... ¡pero mira! Ya está simplificado.

¿Cuenta esto como usar una función incorporada? No está diseñado específicamente para simplificar, y Fraction es una clase de todos modos, no una función.

No llamé a ninguna función de simplificación, por lo que no es mi culpa si Python decide hacerlo por sí mismo.

Ian D. Scott
fuente
¿Pero el constructor de esa clase es una función?
flawr
@flawr type(fractions.Fraction.__init__)regresa en wrapper_descriptorlugar de function, por lo que se podría decir que no es una función. En realidad, esto solo significa que se implementa en c, pero cualquier cosa que no esté en la función de clase no es una función, ¿verdad?
Ian D. Scott, el
2
-1: este es un incorporado. Si bien no dice "simplificar" en el nombre, simplifica las fracciones.
Cyoce
5

> <> (92)

0v
+>>>>>>a*ic4*-:0(?v
v@:{:~^?=2l0  ,a~ <
>:?!v:@%
=1:~<;no-1*4c,n,@:/?
|oooo;!'simplest' /

Sé que puedo bajar esto, lo jugaré un poco más por la mañana.

Explicación básica: las dos primeras líneas y la segunda mitad de la tercera son para leer números. Lamentablemente,> <> no tiene forma de hacerlo, por lo que el análisis ocupa la mitad del programa.

La cuarta línea es un simple cálculo de GCD iterativo. Me sorprende cuán bien> <> le fue en el recuento de bytes para el algoritmo real. Si no fuera por la terrible E / S, en realidad podría ser un lenguaje de golf razonable.

Las últimas dos líneas son solo para imprimir el resultado y dividir los números originales por el mcd.

Mike Precup
fuente
en realidad lo hiciste mejor que todos excepto el golfscript. ¡bonito!
orgulloso Haskeller
ya no es cierto :-(
orgulloso haskeller
3

GolfScript, 49 caracteres

'/'/{~}%.~{.@\%.}do;:G({{G/}%'/'*}{;'simplest'}if

Ejecute las dos cajas de prueba aquí :

> 8/12
2/3

> 7/12
simplest
Howard
fuente
3

JavaScript 101

Por una vez, una solución que no usa EcmaScript 6

v=prompt().split('/');for(a=v[0]|0,b=v[1]|0;a-b;)a>b?a-=b:b-=a;
alert(a>1?v[0]/a+'/'+v[1]/a:'Reduced')

Pero con E6 podría ser 93

[n,d]=prompt().split('/');for(a=n|0,b=d|0;a-b;)a>b?a-=b:b-=a;
alert(a>1?n/a+'/'+d/a:'Reduced')
edc65
fuente
1
for([a,b]=[c,d]=prompt().split('/');b;[a,b]=[b,a%b]);alert(a-1?c/a+'/'+d/a:'Reduced'); 86 espero que sea matemáticamente correcto ...
bebe
2

Python 2.7, 124

from fractions import gcd;x,y=map(int,raw_input().split('/'));g=gcd(x,y);print'%d/%d'%(x/g,y/g)if g!=1 else'Already reduced'

Solución muy simple, aunque sé que sería más corta en muchos otros idiomas.

Utilicé un importado, gcdpero si cuenta como un reductor de fracción incorporado, podría implementarse directamente.

Pasatiempos de Calvin
fuente
2

Pitón 2 (82)

A,B=a,b=map(int,raw_input().split("/"))
while b:a,b=b,a%b
print`A/a`+"/"+`B/a`,a<2

Imprime un booleano después para decir si el original estaba en la forma más simple. Simplemente hace el algoritmo GCD habitual. La mayoría de los caracteres se gastan en entrada / salida.

xnor
fuente
¿No sería más corto usar Python 3 input()?
mbomb007
@ mbomb007 Ha pasado un tiempo, pero creo que los 4 caracteres guardados en eso están más que perdidos por Python 3 necesitando parens print, el mapdesempaquetado y tal vez un número entero en lugar de una división flotante.
xnor
Olvidé la división. Eso solo haría que "no valga la pena". ¿Qué quieres decir con mapser desempacado?
mbomb007
@ mbomb007 Mi error, a,b=map(int,...)no requiere caracteres adicionales ya que se a,b=...desempaqueta automáticamente. El problema que a veces te encuentras con Python 3 es que mapno produce una lista sino un objeto de mapa que requiere convertirse en una lista antes de que puedas hacer algo como cortarla. En su lugar, *l,=map(...)se necesita una expresión como para asignar lcomo una lista.
xnor
2

PHP> = 7.1, 76 bytes (no competitivos)

for([$x,$y]=explode("/",$argn),$t=1+$x;$y%--$t||$x%$t;);echo$x/$t."/".$y/$t;

Versión en línea

Jörg Hülsermann
fuente
1

C, 94

Solo adivine y verifique la fuerza bruta, para GCD que comienza en a | b hasta 1;

main(a,b,c){scanf("%d/%d",&a,&b);for(c=a|b;--c;)if(a%c+b%c<1)a/=c,b/=c;printf("%d/%d\n",a,b);}
technosaurus
fuente
83: c;d;f(a,b){b?f(b,a%b):printf("%d/%d",c/a,d/a);}main(){scanf("%d/%d",&c,&d);f(c,d);}
bebe
0

Rebmu (104 caracteres)

P"/"rSst[a b]paSp AtiA BtiB Ca DbFOiMNcD 1 -1[izADmdCiMDdI[CdvCi DdvDi]]QapAPtsCpTSdIa^e?aCe?bD[Q"Err"]Q

Sin purgar:

P"/"
rS
; extract numerator to a, denominator to b
st [a b] pa s p
; convert a,b to integers
AtiA
BtiB
; set c=a, d=b
Ca Db
; loop from min(c,d) to 1
fo i mn c d 1 -1[
    ; check if (c mod i) + (d mod i) is 0
    iz ad md c i md d i [
        ; divide c, d by i
        Cdv c i
        Ddv d i
    ]
]
; set Q to c/d
Qap ap ts c p ts d
; check if a==c and b==d
i a^ e? a c e? b d[
    ; set q to "err"
    Q"err"
]
; print q
Q
es1024
fuente
0

PHP 156

meh

$f=$argv[1];$p=explode('/',$f);$m=max(array_map('abs',$p));for(;$m;$m--)if(!($p[0]%$m||$p[1]%$m)){$r=$p[0]/$m.'/'.$p[1]/$m;break;}echo $r===$f?'reduced':$r;

Correr:

php -r "$f=$argv[1];$p...[code here]...:$r;" 9/18;
1/2
  • imprime "reducido" si la fracción ya está en su forma más simple
  • trabaja con fracciones negativas
  • funciona con fracciones impropias (por ejemplo, 150/100 da 3/2)
  • funciona un poco con decimales (por ejemplo, 1.2 / 3.6 da 0.75 / 2.25)
  • 99/0 da incorrectamente 1/0 ?
  • no se reducirá a un número entero (por ejemplo, 100/100 da 1/1)

Aquí hay una versión no protegida con algunas pruebas (modificada en forma de función):

<?php
$a = array(
    '9/18','8/12','50/100','82/100','100/100','150/100','99/100',
    '-5/10','-5/18','0.5/2.5','1.2/3.6','1/0','0/1','99/0'
);
print_r(array_map('r',array_combine(array_values($a),$a)));

function r($f) {
    $p = explode('/',$f);
    $m = max(array_map('abs',$p));
    for ( ; $m; $m-- )
        if ( !($p[0] % $m || $p[1] % $m) ) {
            $r = $p[0]/$m.'/'.$p[1]/$m;
            break;
        }
    return $r === $f ? 'reduced' : $r;
}
/*
Array(
    [9/18] => 1/2
    [8/12] => 2/3
    [50/100] => 1/2
    [82/100] => 41/50
    [100/100] => 1/1
    [150/100] => 3/2
    [99/100] => reduced
    [-5/10] => -1/2
    [-5/18] => reduced
    [0.5/2.5] => 0.2/1
    [1.2/3.6] => 0.75/2.25
    [1/0] => reduced
    [0/1] => reduced
    [99/0] => 1/0
)
*/
?>
zamnuts
fuente
0

Java, 361 349 329 (gracias @Sieg por el intconsejo)

class P{public static void main(String[]a){String[]e=a[0].split("/");String f="";int g=new Integer(e[0]),h=new Integer(e[1]);if(g>h){for(int i=h;i>=1;i--){if(g%i==0&&h%i==0){f=g/i+"/"+h/i;break;}}}else if(g<h){for(int i=g;i>=1;i--){if(g%i==0&&h%i==0){f=g/i+"/"+h/i;break;}}}else if(g.equals(h)){f="1/1";}System.out.println(f);}}

Sé que no es corto, pero estoy hipnotizado por lo que hice.

Para usarlo, compile el código y ejecútelo pasando los argumentos a través de la línea de comandos.

  • Solo enteros (no me gusta doublesy la tarea no lo requiere).
  • Si la fracción ya está simplificada, se devuelve.
  • No funciona con fracciones negativas.
  • ¿Dividiendo por cero? Ninguna cookie para ti (Devuelve una cadena vacía).

Sin golf (si alguien quiere ver este desastre):

class P{
    public static void main(String[]a){
        String[]e=a[0].split("/");
        String f="";
        int g=new Integer(e[0]),h=new Integer(e[1]);
        if(g>h){
            for(int i=h;i>=1;i--){
                if(g%i==0&&h%i==0){
                    f=g/i+"/"+h/i;
                    break;
                }
            }
        }else if(g<h){
            for(int i=g;i>=1;i--){
                if(g%i==0&&h%i==0){
                    f=g/i+"/"+h/i;
                    break;
                }
            }
        }else if(g.equals(h)){
            f="1/1"; //no processing if the number is THAT obvious.
        }
        System.out.println(f);
    }
}
g.carvalho97
fuente
1
Realmente debería usar en intlugar de Integer, incluso en el código de producción. Int se asigna desde la pila, mientras que el entero es del montón.
seequ
@Sleg Bueno, no lo sabía, muchas gracias.
g.carvalho97
Entonces algo que no debes usar en la producción. Solo llamar new Integer(str)tendrá el mismo resultado que Integer.parseInt(str). Además, ¿por qué no usar String f=""(siempre)?
seequ
@Sieg Gracias de nuevo, pero ¿por qué? Sé que eso new Integer(str)crea una Integercadena, pero ¿no Integer.parseInt(str)hace lo mismo? Y lo que pasa String f=""es que sé que debería usarlo String f=new String(), pero no sé por qué no, tal vez sea un mal hábito: P
g.carvalho97
1
Integer.parseIntde hecho hace lo mismo, pero con algunos valores en caché para una búsqueda más rápida.
seequ
0

Ruby - 112 caracteres

ges una lambda auxiliar que calcula el MCD de dos enteros. ftoma una fracción como una cadena, por ejemplo '42/14', y genera la fracción reducida o simplestsi el numerador y el denominador son relativamente primos.

g=->a,b{(t=b;b=a%b;a=t)until b==0;a}
f=->z{a,b=z.split(?/).map &:to_i;y=g[a,b];puts y==1?:simplest:[a/y,b/y]*?/}

Algunos casos de prueba:

test_cases = ['9/18', '8/12', '50/100', '82/100', '100/100',
              '150/100', '99/100', '-5/10', '-5/18', '0/1']

test_cases.map { |frac| f[frac] }

Salida:

1/2
2/3
1/2
41/50
1/1
3/2
simplest
-1/2
simplest
simplest

Tenga en cuenta que, aunque contra las reglas, Ruby tiene Rationalsoporte incorporado, por lo que podríamos hacer

a=gets.chomp;b=a.to_r;puts b.to_s==a ?:simplest:b
OI
fuente
0

JavaScript (91) (73)

Devuelve '/' cuando la fracción ya está en su forma más simple. La función g calcula el mcd. Por cierto: ¿Hay alguna forma más corta para '1 == algo' donde algo es un entero no negativo?

function s(f){[n,m]=f.split(b='/');g=(u,v)=>v?g(v,u%v):u;return 1==(c=g(n,m))?b:n/c+b+m/c;}

Gracias a @bebe por una versión aún más corta:

s=f=>([n,m]=f.split(b='/'),c=(g=(u,v)=>v?g(v,u%v):u)(n,m))-1?n/c+b+m/c:f;
falla
fuente
use es6 constantemente. llame a su función, s=f=>...luego asigne g cuando lo use, (g=...)(n,m)luego páselo a c y pruebe si es igual a 1 por c-1?not_equals:equalse intente evitar usar return. resultado: s=f=>([n,m]=f.split(b='/'),c=(g=(u,v)=>v?g(v,u%v):u)(n,m))-1?n/c+b+m/c:f;73 (devuelve la forma más simple (f) si no se puede reducir)
bebe
1
¡Wow eso es genial! No pude pensar en una forma de agrupar la cosa de shole en una declaración que es por eso que usé functiony return. Y gracias por el -1=)
error
0

Lua - 130 115 caracteres

10/10 realmente lo intenté

a,b=io.read():match"(.+)/(.+)"u,v=a,b while v+0>0 do t=u u=v v=t%v end print(a+0==a/u and"reduced"or a/u.."/"..b/u)
  • imprime "reducido" si la fracción está en la forma más simple
  • trabaja con negativos
  • trabaja con fracciones impropias
  • presumiblemente funciona con decimales (1.2 / 3.6 da 5.4043195528446e + 15 / 1.6212958658534e + 16)
  • cualquier número / 0 da 1/0
  • no se reduce a números enteros

Aproveché al máximo la capacidad de Lua para convertir automáticamente una cadena en un número al realizar operaciones aritméticas en una cadena. Tuve que agregar "+0" en lugar de tonumber para algún código de comparación.

Lo siento, no tengo una versión sin golf, lo anterior es en realidad cómo la escribí

Dwayne Slater
fuente
0

Lote - 198

for /f "tokens=1,2delims=/" %%a in ("%1")do set a=%%a&set b=%%b&set/ac=%%b
:1
set/ax=%a%%%%c%&set/ay=%b%%%%c%
if %x%%y%==00 set/aa/=%c%&set/ab/=%c%
if %c% GTR 0 set/ac=%c%-1&goto 1
echo %a%/%b%

De entrada se divide como a/b, a continuación, para cada cen b,b-1,...1comprobamos si ay bson divisibles por c, y dividirlos por csi lo son. Luego volvemosa/b

Οurous
fuente
0

Befunge 93 (192)

&04p~$&14p2       > :24p  v       >34g#v_0"tselpmiS">:#,_@
>134p 24g>        ^+1g42$<>04g`   |    >04g."/",14g.@
^p41/g42p40/g42<         |%g42:g41<
         #     |!%g42:g40<
   0     ^+1g42<
sig_seg_v
fuente
0

C 135

Acepta entradas para 2 enteros separados por espacios. Sigue dividiendo por un mínimo de a & b hasta 1 para encontrar el MCD.

int a,b,m;
void main()
{
scanf("%d %d", &a, &b);
m=a<b?a:b;
for (;m>0;m--){if (a%m==0&&b%m==0)break;}
printf("%d/%d",a/m,b/m);
}
bacchusbeale
fuente
0

Java (200)

La mejor solución anterior en Java todavía tenía> 300 bytes, esta tiene 200:

class M {public static void main(String[]args){String[]s=args[0].split("/");int a=Integer.parseInt(s[0]),b=Integer.parseInt(s[1]),c=a,d=b;while(d>0){int g=c;c=d;d=g%d;}System.out.print(a/c+"/"+b/c);}}

Esto usa el módulo (más rápido) para determinar el mcd en lugar de iterar todos los números.

Roy van Rijn
fuente
1
Puede eliminar el espacio despuésclass M
mbomb007