Mostrando las entradas con la etiqueta euler. Mostrar todas las entradas
Mostrando las entradas con la etiqueta euler. Mostrar todas las entradas

viernes, mayo 08, 2009

Project Euler problema 6

Lo lei, hice un oneliner en python y no lo corri porque pense que iba a demorar mucho, trate de recordar alguna propiedad pero no me acorde nada, buscando en internet todas eran resoluciones de project euler asi que decidi correrlo por fuerza bruta, termino siendo rapido asi que no me esforce mas:

problema:

The sum of the squares of the first ten natural numbers is,

1^(2) + 2^(2) + ... + 10^(2) = 385

The square of the sum of the first ten natural numbers is,

(1 + 2 + ... + 10)^(2) = 55^(2) = 3025

Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.



python:

>>> sum(xrange(1, 101)) ** 2 - sum(map(lambda x: x**2, xrange(1, 101)))
25164150

lisp:

[44]> (- (expt (apply #'+ (loop for x from 1 to 100 collect x)) 2) (apply #'+ (loop for x from 1 to 100 collect (expt x 2))))
25164150

erlang:

-module(ej_006).
-export([show/0]).

do_to_range(Stop, Stop, Accum, Fun) -> Accum + Fun(Stop);
do_to_range(Start, Stop, Accum, Fun) ->
do_to_range(Start + 1, Stop, Accum + Fun(Start), Fun).

show() ->
SumOfSquares = do_to_range(1, 100, 0, fun(X) -> X * X end),
SquareOfSums = math:pow(do_to_range(1, 100, 0, fun(X) -> X end), 2),
SquareOfSums - SumOfSquares.



observaciones:
  • encontre esta referencia de lisp: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node81.html
  • la exponenciacion en lisp se hace con expt
  • no encontre algo como xrange asi que use el macro de for
  • no me gusta la cantidad de funciones que hay en lisp (y en un solo namespace! :P)
  • en erlang lo hice un poco mas prolijito porque lo tuve que hacer recursivo
  • si no fuera por que python no tiene notacion prefija, la resolucion seria casi igual (si hiciese una funcion range con los for)

viernes, febrero 20, 2009

project euler - problema 5

Hasta ahora a todos los problemas los venia resolviendo por fueza bruta aplicando algunas optimizaciones (para que no sea tan bruto vio?), pero decidi ejercitar un poco mis conocimientos matematicos para intentar resolverlo puramente con matematicas o al menos eliminar muchas cosas innecesarias.

el problema 5 es este:

2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?

agarre un lapiz y un papel (posta!) y me puse a pensar un poco.

Lo primero que probe (fuerza bruta matematica) es el producto de los numeros del 1 al 20 es divisible por todos ellos, el problema es que no es el mas chico.. entonces pense un poco mas. Porque no es el mas chico? bueno, porque ahi hay muchas multiplicaciones innecesarias, si es multiplo de 20 es tambien multiplo de 10, 5, 4 2 etc.

despues de eso llegue a la conclusion de que el numero era el producto de los numeros del 11 al 20, pero resulto no ser asi, pense un rato mas y no se me ocurrio nada asi que decidi darle mi problema acotado a python, lo que hice a grandes rasgos fue.

incrementar de a 380 el contador (producto de 20 y 19), y ya que incremento en multiplos de 20 y 19 no me hace falta controlar que sean multiplos de ellos, por lo tanto hice una lista de numeros del 18 al 11 ya que los numeros mas chicos se comprueban comprobando esos. Puse los numeros al reves ya que si el numero divisor es mas grande tiene menos numeros multiplos, por lo tanto al cortar al encontrar un numero no divisor en los numeros mas grandes me ahorro algunos calculos innecesarios.

cuando entre a las soluciones vi que la solucion del problema tenia que ver con multiplicar numeros, pero no los numeros en si, sino las potencias mas altas de los primos de la factorizacion del 1 al 20. (aca esta la explicacion http://mathforum.org/library/drmath/view/62527.html)

y bue, tan bueno en la matematica no soy :D

codigo en python

NUMS = [float(x) for x in range(11, 19)]
NUMS.reverse()

def first_multiple_from_1_to_20():
num = 380

while True:
for x in NUMS:
if num % x != 0:
break
else:
return num

num += 380

num = first_multiple_from_1_to_20()

print num


erlang

-module(ej_005).
-export([first_multiple_from_1_to_20/0]).

is_multiple_from_11_to_18(_Value, 10) -> true;
is_multiple_from_11_to_18(Value, Number) ->
case Value rem Number == 0 of
true -> is_multiple_from_11_to_18(Value, Number - 1);
false -> false
end.

is_multiple_from_11_to_18(Value) -> is_multiple_from_11_to_18(Value, 18).

first_multiple_from_1_to_20(Count) ->
case is_multiple_from_11_to_18(Count) of
true -> Count;
false -> first_multiple_from_1_to_20(Count + 380)
end.

first_multiple_from_1_to_20() -> first_multiple_from_1_to_20(380).



lisp

(defun is-multiple-from-11-to-18 (value)
(= (loop for i from 18 downto 11 by 1
while (= (mod value i) 0) finally (return i)) 10))

(defun first-multiple-from-1-to-20 ()
(loop for i from 380 by 380
while (not (is-multiple-from-11-to-18 i))
finally (return i)))

(print (first-multiple-from-1-to-20))

Seguidores

Archivo del Blog