lunes, 5 de junio de 2017

Euler #33

https://projecteuler.net/problem=33

De nuevo, la facilidad que ofrece Python para pasar de unos tipos a otros y los módulos estándar que trae hacen que este problema sea trivial.

Se puede compactar más la solución, pero así se ve claro cómo vamos filtrando poco a poco los números candidatos hasta llegar a la solución. También ayuda mucho el enunciado del problema, estableciendo cuántos resultados son esperables.

#!/usr/bin/env python
from fractions import Fraction
from operator import mul

fracts = []
for d in range(10, 100):
 for n in range(10, 100):
  if n / d < 1 and n % 10 != 0 and d % 10 != 0:
   num = str(n)
   den = str(d)
   for x in range(1, 10):
    xstr = str(x)
    if (num[0] == xstr and den[1] == xstr) or (num[1] == xstr and den[0] == xstr):
     new_n = int(num.replace(xstr, '', 1))
     new_d = int(den.replace(xstr, '', 1))
     if (new_n * d == new_d * n):
      fracts.append(Fraction(new_n, new_d))

print reduce(mul, fracts, 1)

La función "reduce" es muy útil para operar con listas en bloque. Es un atajo para no tener que escribir bucles:

tot = 1
for f in fracts:
    tot *= f
print tot

Así mismo, la clase Fraction es lo suficientemente inteligente para lidiar con enteros, operar con fracciones, simplificarlas,...