How to resolve the algorithm Attractive numbers step by step in the JavaScript programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Attractive numbers step by step in the JavaScript programming language

Table of Contents

Problem Statement

A number is an   attractive number   if the number of its prime factors (whether distinct or not) is also prime.

The number   20,   whose prime decomposition is   2 × 2 × 5,   is an   attractive number   because the number of its prime factors   (3)   is also prime.

Show sequence items up to   120.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Attractive numbers step by step in the JavaScript programming language

The given script is written in JavaScript and implements a function called attractiveNumbers that generates a sequence of attractive numbers. An attractive number is a positive integer that satisfies the following conditions:

  • It is a prime number.
  • The number of prime factors of the number is prime.

The script also includes several utility functions, such as isPrime check if a number is prime, primeFactors to find the prime factors of a number, and other generic functions like enumFrom, enumFromThenTo, filter, ge, justifyRight, last, length, map, showCols, str, takeWhile, unlines, and until.

Here's a breakdown of the code:

  1. attractiveNumbers: This function generates an infinite series of attractive numbers using the isPrime and primeFactors functions. It returns a generator that yields attractive numbers.

  2. isPrime: This function checks whether a given number is prime. It uses a series of checks to efficiently determine if a number is prime or not.

  3. primeFactors: This function finds the prime factors of a given number. It uses a loop to iteratively find the prime factors and returns a list of those factors.

  4. enumFrom: This function generates an infinite succession of enumerable values starting from a given value. It is used to generate the sequence of attractive numbers.

  5. enumFromThenTo: This function generates a finite range of values from a starting value to an ending value. It is used to generate the sequence of attractive numbers within a specific range.

  6. filter: This function filters a list of values based on a predicate function. It returns a new list containing only the values that satisfy the predicate.

  7. ge: This function checks if one value is greater than or equal to another.

  8. justifyRight: This function justifies a string to the right by adding padding characters. It is used to align the output of the attractive numbers.

  9. last: This function returns the last item of a list.

  10. length: This function returns the length of a list.

  11. map: This function applies a function to each element of a list and returns a new list with the transformed values.

  12. showCols: This function displays a list of values in columns. It is used to format the output of the attractive numbers.

  13. str: This function converts a value to a string.

  14. takeWhile: This function takes a list and a predicate function and returns a new list containing the elements from the original list while the predicate function returns true.

  15. unlines: This function concatenates a list of strings into a single string, with each string separated by a newline character.

  16. until: This function takes a predicate function and a function that takes a value and returns a new value and applies the function repeatedly to the value until the predicate function returns true.

In the main function, the attractiveNumbers function is called to generate a sequence of attractive numbers. The sequence is then filtered to include only numbers greater than or equal to 120 using the takeWhile function. Finally, the showCols function is used to format and display the attractive numbers in columns.

Source code in the javascript programming language

(() => {
    'use strict';

    // attractiveNumbers :: () -> Gen [Int]
    const attractiveNumbers = () =>
        // An infinite series of attractive numbers.
        filter(
            compose(isPrime, length, primeFactors)
        )(enumFrom(1));


    // ----------------------- TEST -----------------------
    // main :: IO ()
    const main = () =>
        showCols(10)(
            takeWhile(ge(120))(
                attractiveNumbers()
            )
        );


    // ---------------------- PRIMES ----------------------

    // isPrime :: Int -> Bool
    const isPrime = n => {
        // True if n is prime.
        if (2 === n || 3 === n) {
            return true
        }
        if (2 > n || 0 === n % 2) {
            return false
        }
        if (9 > n) {
            return true
        }
        if (0 === n % 3) {
            return false
        }
        return !enumFromThenTo(5)(11)(
            1 + Math.floor(Math.pow(n, 0.5))
        ).some(x => 0 === n % x || 0 === n % (2 + x));
    };


    // primeFactors :: Int -> [Int]
    const primeFactors = n => {
        // A list of the prime factors of n.
        const
            go = x => {
                const
                    root = Math.floor(Math.sqrt(x)),
                    m = until(
                        ([q, _]) => (root < q) || (0 === (x % q))
                    )(
                        ([_, r]) => [step(r), 1 + r]
                    )([
                        0 === x % 2 ? (
                            2
                        ) : 3,
                        1
                    ])[0];
                return m > root ? (
                    [x]
                ) : ([m].concat(go(Math.floor(x / m))));
            },
            step = x => 1 + (x << 2) - ((x >> 1) << 1);
        return go(n);
    };


    // ---------------- GENERIC FUNCTIONS -----------------

    // chunksOf :: Int -> [a] -> [[a]]
    const chunksOf = n =>
        xs => enumFromThenTo(0)(n)(
            xs.length - 1
        ).reduce(
            (a, i) => a.concat([xs.slice(i, (n + i))]),
            []
        );


    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (...fs) =>
        fs.reduce(
            (f, g) => x => f(g(x)),
            x => x
        );


    // enumFrom :: Enum a => a -> [a]
    function* enumFrom(x) {
        // A non-finite succession of enumerable
        // values, starting with the value x.
        let v = x;
        while (true) {
            yield v;
            v = 1 + v;
        }
    }


    // enumFromThenTo :: Int -> Int -> Int -> [Int]
    const enumFromThenTo = x1 =>
        x2 => y => {
            const d = x2 - x1;
            return Array.from({
                length: Math.floor(y - x2) / d + 2
            }, (_, i) => x1 + (d * i));
        };


    // filter :: (a -> Bool) -> Gen [a] -> [a]
    const filter = p => xs => {
        function* go() {
            let x = xs.next();
            while (!x.done) {
                let v = x.value;
                if (p(v)) {
                    yield v
                }
                x = xs.next();
            }
        }
        return go(xs);
    };


    // ge :: Ord a => a -> a -> Bool
    const ge = x =>
        // True if x >= y
        y => x >= y;


    // justifyRight :: Int -> Char -> String -> String
    const justifyRight = n =>
        // The string s, preceded by enough padding (with
        // the character c) to reach the string length n.
        c => s => n > s.length ? (
            s.padStart(n, c)
        ) : s;


    // last :: [a] -> a
    const last = xs =>
        // The last item of a list.
        0 < xs.length ? xs.slice(-1)[0] : undefined;


    // length :: [a] -> Int
    const length = xs =>
        // Returns Infinity over objects without finite
        // length. This enables zip and zipWith to choose
        // the shorter argument when one is non-finite,
        // like cycle, repeat etc
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;


    // map :: (a -> b) -> [a] -> [b]
    const map = f =>
        // The list obtained by applying f
        // to each element of xs.
        // (The image of xs under f).
        xs => (
            Array.isArray(xs) ? (
                xs
            ) : xs.split('')
        ).map(f);


    // showCols :: Int -> [a] -> String
    const showCols = w => xs => {
        const
            ys = xs.map(str),
            mx = last(ys).length;
        return unlines(chunksOf(w)(ys).map(
            row => row.map(justifyRight(mx)(' ')).join(' ')
        ))
    };


    // str :: a -> String
    const str = x =>
        x.toString();


    // takeWhile :: (a -> Bool) -> Gen [a] -> [a]
    const takeWhile = p => xs => {
        const ys = [];
        let
            nxt = xs.next(),
            v = nxt.value;
        while (!nxt.done && p(v)) {
            ys.push(v);
            nxt = xs.next();
            v = nxt.value
        }
        return ys;
    };


    // unlines :: [String] -> String
    const unlines = xs =>
        // A single string formed by the intercalation
        // of a list of strings with the newline character.
        xs.join('\n');


    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = p => f => x => {
        let v = x;
        while (!p(v)) v = f(v);
        return v;
    };

    // MAIN ---
    return main();
})();


  

You may also check:How to resolve the algorithm Literals/Integer step by step in the Kotlin programming language
You may also check:How to resolve the algorithm Thue-Morse step by step in the XLISP programming language
You may also check:How to resolve the algorithm Inheritance/Single step by step in the Clojure programming language
You may also check:How to resolve the algorithm Stern-Brocot sequence step by step in the Factor programming language
You may also check:How to resolve the algorithm Imaginary base numbers step by step in the C# programming language