Project-Euler-005

Problem

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?

Answer

1
232792560

The critical insight of this problem is this:

$$divisibleto(x) = n \times divisibleto(x-1)$$

This means that when searching for the smallest number divisible to 20,
we can increment by the smallest number divisible to 19 each time (since the
smallest number divisible to 19 is inherently a factor of the smallest number
divisible to 20).

This insight is used in the python solution on line 14:

step = divisible_to(x-1)

This is a recursive solution to the problem, and yields incredible performance. It can calculate
the smallest number divisible to 500 in a fraction of a second.

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
def is_divisible_to(number, x):
for i in reversed(list(range(1, x+1))):
if number % i != 0:
return False
return True

def divisible_to(x):
if x < 1:
return False
elif x == 1:
return 1
else:
step = divisible_to(x-1)
number = 0
found = False
while not found:
number += step
found = is_divisible_to(number, x)
return number

print(divisible_to(20))


JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function isDivisibleTo(x, n) {
for (; n > 0; n -= 1) {
if (x % n !== 0) {
return false
}
}
return true
}

function divisibleTo(n) {
if (n === 1) return 1
for (var step = divisibleTo(n - 1), i = step; !isDivisibleTo(i, n); i += step);
return i
}

console.log(divisibleTo(20))


Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func GCD(a, b int) int {
for b != 0 {
a, b = b, a%b
}
return a
}

func main() {
lcm := 1
for i := 2; i <= 20; i++ {
lcm *= i / GCD(i, lcm)
}
fmt.Println(lcm)
}


Ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env ruby

class Numeric
def divisible_to?(x)
self > 0 and x.downto(1).all? { |i| self % i == 0 }
end
end

def divisible_to(x)
if x < 1
return false
elsif x == 1
return 1
else
n = 0
step = divisible_to(x-1)
until n.divisible_to? x
n += step
end
return n
end
end

puts divisible_to(20)


Rust

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn gcd(mut a: u64, mut b: u64) -> u64 {
while b != 0 {
let t = a;
a = b;
b = t % b;
}
a
}

fn main() {
let lcm = (2..21).fold(1, |acc, i| {
acc * i / gcd(i, acc)
});
println!("{}", lcm);
}


Haskell

1
2
3
4
5
6
7
8
9
10
isDivisibleTo ::  Integer -> Integer -> Bool
isDivisibleTo x n = all (\i -> n `mod` i == 0) (reverse [1..x])

divisibleTo :: Integer -> Integer
divisibleTo 1 = 1
divisibleTo x = let step = divisibleTo (x-1)
in head $ filter (isDivisibleTo x) [step,2*step..]

main :: IO ()
main = print $ divisibleTo 20


Clojure

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env clojure
(defn divisible-to-x? [n x]
(every? #(= (rem n %) 0) (reverse (range 1 (+ x 1)))))

(defn divisible-to [x]
(if (= x 1)
x
(first (filter #(divisible-to-x? % x) (iterate inc (divisible-to (- x 1)))))))

(println (divisible-to 20))


Mathematica

1
2
3
4
5
6
7
8
(* 
* The smallest number n that is evenly divisible by every number in a set {k1, k2, ..., k_m}
* is also known as the lowest common multiple (LCM) of the set of numbers.
* The LCM of two natural numbers x and y is given by LCM(x, y) = x * y / GCD(x, y).
* When LCM is applied to a collection of numbers, it is commutative, associative, and idempotent.
* Hence LCM(k1, k2, ..., k_m) = LCM(...(LCM(LCM(k1, k2), k3)...), k_m).
*)
Apply[LCM, Range[20]]


Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.math.BigInteger;


public final class p005 implements EulerSolution {

public static void main(String[] args) {
System.out.println(new p005().run());
}


/*
* The smallest number n that is evenly divisible by every number in a set {k1, k2, ..., k_m}
* is also known as the lowest common multiple (LCM) of the set of numbers.
* The LCM of two natural numbers x and y is given by LCM(x, y) = x * y / GCD(x, y).
* When LCM is applied to a collection of numbers, it is commutative, associative, and idempotent.
* Hence LCM(k1, k2, ..., k_m) = LCM(...(LCM(LCM(k1, k2), k3)...), k_m).
*/
public String run() {
BigInteger allLcm = BigInteger.ONE;
for (int i = 1; i <= 20; i++)
allLcm = lcm(BigInteger.valueOf(i), allLcm);
return allLcm.toString();
}


private static BigInteger lcm(BigInteger x, BigInteger y) {
return x.divide(x.gcd(y)).multiply(y);
}

}

文章作者: Monad Kai
文章链接: onlookerliu.github.io/2018/02/12/Project-Euler-005/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Code@浮生记
支付宝打赏
微信打赏