Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calculate time to process combinations javascript

Tags:

javascript

I have this function from : https://rosettacode.org/wiki/Combinations#ES6

In my environementt console.log(show(comb(3,15))); (same as this snippet bellow) take aprox. 4 seconds to process

If I try console.log(show(comb(3,16))); that take aprox. 16 seconds

If I try console.log(show(comb(3,17))); that take aprox. 90 seconds

But If I tryed : console.log(show(comb(3,20))); After one hour of process are not yet finish and I have stopped it.

The question is:

How to calculate beforehand the time to process comb(3,50) or comb(3,80) ?

(() => {
    'use strict';

 
    // COMBINATIONS -----------------------------------------------------------
 
    // comb :: Int -> Int -> [[Int]]
    const comb = (m, n) => combinations(m, enumFromTo(0, n - 1));
 
    // combinations :: Int -> [a] -> [[a]]
    const combinations = (k, xs) =>
        sort(filter(xs => k === xs.length, subsequences(xs)));
 
 
    // GENERIC FUNCTIONS -----------------------------------------------------
 
    // cons :: a -> [a] -> [a]
    const cons = (x, xs) => [x].concat(xs);
 
    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = (m, n) =>
        Array.from({
            length: Math.floor(n - m) + 1
        }, (_, i) => m + i);
 
    // filter :: (a -> Bool) -> [a] -> [a]
    const filter = (f, xs) => xs.filter(f);
 
    // foldr (a -> b -> b) -> b -> [a] -> b
    const foldr = (f, a, xs) => xs.reduceRight(f, a);
 
    // isNull :: [a] -> Bool
    const isNull = xs => (xs instanceof Array) ? xs.length < 1 : undefined;
 
    // show :: a -> String
    const show = x => JSON.stringify(x) //, null, 2);
 
    // sort :: Ord a => [a] -> [a]
    const sort = xs => xs.sort();
 
    // stringChars :: String -> [Char]
    const stringChars = s => s.split('');
 
    // subsequences :: [a] -> [[a]]
    const subsequences = xs => {
 
        // nonEmptySubsequences :: [a] -> [[a]]
        const nonEmptySubsequences = xxs => {
            if (isNull(xxs)) return [];
            const [x, xs] = uncons(xxs);
            const f = (r, ys) => cons(ys, cons(cons(x, ys), r));
 
            return cons([x], foldr(f, [], nonEmptySubsequences(xs)));
        };
 
        return nonEmptySubsequences(
            (typeof xs === 'string' ? stringChars(xs) : xs)
        );
    };
 
    // uncons :: [a] -> Maybe (a, [a])
    const uncons = xs => xs.length ? [xs[0], xs.slice(1)] : undefined;
 
 
    // TEST -------------------------------------------------------------------
    // return show(
        // comb(3, 5)
    // );
    
    console.log(show(comb(3,15)));
})();
like image 837
MTK Avatar asked Mar 18 '19 13:03

MTK


1 Answers

Use binomial coefficients. The time to process comb(3,n) is n choose 3 which works out to n*(n-1)*(n-2)/6 hence is O(n^3). For example, increasing n by a factor of 10 should increase the runtime by a factor of roughly 1000.

20 choose 3 is only 1140, so if it takes over an hour to generate them, the algorithm in question isn't particularly good. Furthermore, the gap between 20 choose 3 and 17 choose 3 is not so large that it really explains the time difference. Thus, the asymptotic analysis is only suggestive of what is happening. The actual runtime seems to be much worse.

like image 166
John Coleman Avatar answered Oct 25 '22 08:10

John Coleman