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 positive number that is evenly divisible by all of the numbers from 1 to 20?

Project Euler Problem 5

Let’s build a more generalized version of it for arbitrary ranges using a) a brute force (BF) approach, b) prime factorization (PF) and c) Julia’s lcm (least common multiple) function:


function reduceDivisors(rangeMin::UInt64, rangeMax::UInt64)
	divisorsForRemoval = Array{UInt64,1}();
	for i in rangeMax:-1:rangeMin
		for j in rangeMax:-1:rangeMin
			if i!=j && i!=1  && j!=1 && mod(j,i) ==0 && (i in divisorsForRemoval) == false
				push!(divisorsForRemoval,i);
			end

		end
	end
	listOfDivisors = collect(rangeMin:rangeMax);
	reducedListOfDivisors = setdiff(listOfDivisors, divisorsForRemoval);
	return reducedListOfDivisors
end



function getSmallestNumberBF(rangeMin::UInt64, rangeMax::UInt64)
	divisors = reduceDivisors(rangeMin, rangeMax);
	number::Bool = false;
	i::UInt64 = rangeMax; # testing multiples of rangeMax which is the highest number in divisors by definition
	while number == false
		currentNumber::UInt64 = i;
		testResult = Array{UInt64,1}();
		for divisor in divisors
			push!(testResult, mod(currentNumber, divisor))
		end
		if sum(testResult) == 0
			smallestNumber::UInt64 = currentNumber;
			number = true;
			return smallestNumber
		end
		i += rangeMax;
	end

end

function isPrime(n::UInt64)
	isPrimeNumber::Bool = true;
	for i in 2:1:(n-1)
		if n%i == 0
			isPrimeNumber = false;
			return isPrimeNumber
		end
	end
	return isPrimeNumber
end

function getAllPrimes(rangeMax::UInt64)
	listOfPrimesInRange = Array{UInt64,1}()
	for i in 2:1:rangeMax
		if isPrime(i)
			push!(listOfPrimesInRange,i);
		end
	end
	return listOfPrimesInRange

end

function primeDecomposition(n::UInt64, listOfPrimesInRange::Array{UInt64,1}, dictOfPrimesInRange::Dict{UInt64,UInt64})
	for prime in listOfPrimesInRange
		power = 0
		while mod(n,prime) == 0
			power += 1
			n = div(n,prime)
		end
		if dictOfPrimesInRange[prime] < power
			dictOfPrimesInRange[prime] = power
		end
	end
	return dictOfPrimesInRange
end

function getSmallestNumberPF(rangeMin::UInt64, rangeMax::UInt64)
	listOfPrimesInRange = getAllPrimes(rangeMax);
	dictOfPrimesInRange = Dict{UInt64,UInt64}(i => 0 for i in listOfPrimesInRange);
	for i in rangeMin:1:rangeMax
		dictOfPrimesInRange = primeDecomposition(i, listOfPrimesInRange, dictOfPrimesInRange);
	end
	smallestNumber = prod([key^dictOfPrimesInRange[key] for key in keys(dictOfPrimesInRange)]);
	return smallestNumber
	# lcm is the product of primes with the highest power

end


function JuliaLCM(rangeMin::UInt64,rangeMax::UInt64)
	numbers = collect(rangeMin:rangeMax);
	leastCommonMultiple = lcm(numbers);
	return leastCommonMultiple
end

function parseARGS()
	if isempty(ARGS)
		rangeMin::UInt64 = 1;
		rangeMax::UInt64 = 20;
		method::String = "PF";
	else
		rangeMin = tryparse(UInt64, ARGS[1])
		rangeMax = tryparse(UInt64, ARGS[2])
		method = ARGS[3]
	end
	return rangeMin, rangeMax, method
end

function main()
	rangeMin, rangeMax, method = parseARGS();
	if method == "BF"
		smallestNumber = getSmallestNumberBF(rangeMin,rangeMax);
	elseif method == "PF"
		smallestNumber = getSmallestNumberPF(rangeMin,rangeMax);
	else
		smallestNumber = JuliaLCM(rangeMin,rangeMax);
	end
	println(smallestNumber);
end

main()
$ julia ProjectEuler0005.jl 1 10 BF
2520
  0.000077 seconds (788 allocations: 53.125 KiB)

$ julia ProjectEuler0005.jl 1 20 BF
232792560
  2.534551 seconds (46.56 M allocations: 3.816 GiB, 5.87% gc time)

$ julia ProjectEuler0005.jl 20 30 BF
3605401800
 26.114736 seconds (480.72 M allocations: 39.398 GiB, 5.84% gc time)



$ julia ProjectEuler0005.jl 1 10 PF
2520
  0.000058 seconds (33 allocations: 1.891 KiB)

$ julia ProjectEuler0005.jl 1 20 PF
232792560
  0.000061 seconds (34 allocations: 2.000 KiB)

$ julia ProjectEuler0005.jl 20 30 PF
3605401800
  0.000061 seconds (35 allocations: 2.156 KiB)



$ julia ProjectEuler0005.jl 1 10 lcm
2520
  0.000045 seconds (21 allocations: 1.109 KiB)

$ julia ProjectEuler0005.jl 1 20 lcm
232792560
  0.000045 seconds (21 allocations: 1.188 KiB)

$ julia ProjectEuler0005.jl 20 30 lcm
3605401800
  0.000111 seconds (21 allocations: 1.125 KiB)

$ julia ProjectEuler0005.jl 1 34578920 lcm
4934319942519488512
  3.981096 seconds (22 allocations: 263.817 MiB, 0.35% gc time)

Using Julia’s lcm is so much more efficient than my quick and dirty implementations. Note: my manual PF approach didn’t reached any result for the range of 1 to 34578920 within 5 minutes.