Project Euler problem 53
Combinatoric selections
There are exactly ten ways of selecting three from five, 12345:
123, 124, 125, 134, 135, 145, 234, 235, 245, and 345
In combinatorics, we use the notation, C(3,5) = 10.
In general, C(N,R) = N! / (R!*(N-R)!)
It is not until n = 23, that a value exceeds one-million: C(10,23) = 1144066.
How many, not necessarily distinct, values of C(N,R), for 1 ≤ n ≤ 100, are greater than one-million?
Link to original description
Source code examples on Github
Brutforce python solution:
1 2 3 4 5 6 7 8 9 | import math count = 0 for n in range(1,101): for r in range(1,n+1): if math.factorial(n) / (math.factorial(r) * math.factorial(n-r)) >= 1000000: count += 1 print("Answer %s" % count) |
and same thing with erlang:
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 | #!/usr/bin/env escript %% -*- erlang -*- %%! -smp enable -sname p53 % vim:syn=erlang -mode(compile). main(_) -> io:format("Answer ~p ~n",[ p53() ]). c(N, R) -> f(N) / (f(R)*f(N-R)). f(0) -> 1; f(1) -> 1; f(N) -> N*f(N-1). p53() -> Fun = fun(N,A) -> lists:foldl(fun(R,B)-> case c(N,R) >= 1000000 of true -> B + 1 ;_ -> B end end, 0, lists:seq(1,N)) + A end, lists:foldl(Fun, 0, lists:seq(1,100)). |
For optimization i tryed to memoize factorial function values:
for python i did it with lru_cache decorator
1 2 3 4 5 6 7 8 9 10 11 12 | import math, functools count = 0 @functools.lru_cache(maxsize = 1000) def f(n,r): return math.factorial(n) / (math.factorial(r) * math.factorial(n-r)) for n in range(1,101): for r in range(1,n+1): if f(n,r) >= 1000000: count += 1 print("Answer %s" % count) |
for erlang i did it with process dictionary:
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 | #!/usr/bin/env escript %% -*- erlang -*- %%! -smp enable -sname p53 % vim:syn=erlang -mode(compile). main(_) -> io:format("Answer ~p ~n",[ p53() ]). c(N, R) -> f(N) / (f(R)*f(N-R)). f(0) -> 1; f(1) -> 1; f(N) -> case get({'f', N}) of undefined -> R = N*f(N-1), put({'f', N}, R), R; Ret -> Ret end. p53() -> Fun = fun(N,A) -> lists:foldl(fun(R,B)-> case c(N,R) >= 1000000 of true -> B + 1 ;_ -> B end end, 0, lists:seq(1,N)) + A end, lists:foldl(Fun, 0, lists:seq(1,100)). |
but for these calculations it is didn’t make any performance increment.