Attractive numbers

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

;Example:
The number   '''20''',   whose prime decomposition is   '''2 x 2 x 5''',   is an   ''attractive number''   because the number of its prime factors   ('''3''')   is also prime.

;Task:
Show sequence items up to   '''120'''.

;Reference:
:*   The OEIS entry:   A063989: Numbers with a prime number of prime divisors.

Solution:
(() => {
    '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();
})();


Averages/Mean angle

Solution:
function sum(a) {
    var s = 0;
    for (var i = 0; i < a.length; i++) s += a[i];
    return s;
}

function degToRad(a) {
    return Math.PI / 180 * a;
}

function meanAngleDeg(a) {
    return 180 / Math.PI * Math.atan2(
        sum(a.map(degToRad).map(Math.sin)) / a.length,
        sum(a.map(degToRad).map(Math.cos)) / a.length
    );
}

var a = [350, 10], b = [90, 180, 270, 360],  c = [10, 20, 30];
console.log(meanAngleDeg(a));
console.log(meanAngleDeg(b));
console.log(meanAngleDeg(c));


Averages/Pythagorean means

Solution:
(function () {
    'use strict';

    // arithmetic_mean :: [Number] -> Number
    function arithmetic_mean(ns) {
        return (
            ns.reduce( // sum
                function (sum, n) {
                    return (sum + n);
                },
                0
            ) / ns.length
        );
    }

    // geometric_mean :: [Number] -> Number
    function geometric_mean(ns) {
        return Math.pow(
            ns.reduce( // product
                function (product, n) {
                    return (product * n);
                },
                1
            ),
            1 / ns.length
        );
    }

    // harmonic_mean :: [Number] -> Number
    function harmonic_mean(ns) {
        return (
            ns.length / ns.reduce( // sum of inverses
                function (invSum, n) {
                    return (invSum + (1 / n));
                },
                0
            )
        );
    }

    var values = [arithmetic_mean, geometric_mean, harmonic_mean]
        .map(function (f) {
            return f([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        }),
        mean = {
            Arithmetic: values[0], // arithmetic
            Geometric: values[1], // geometric
            Harmonic: values[2] // harmonic
        }

    return JSON.stringify({
        values: mean,
        test: "is A >= G >= H ? " +
            (
                mean.Arithmetic >= mean.Geometric &&
                mean.Geometric >= mean.Harmonic ? "yes" : "no"
            )
    }, null, 2);

})();


Babbage problem

Charles Babbage
Charles Babbage's analytical engine.

Charles Babbage, looking ahead to the sorts of problems his Analytical Engine would be able to solve, gave this example:
{{quote
 | What is the smallest positive integer whose square ends in the digits 269,696?
 | Babbage, letter to Lord Bowden, 1837; see Hollingdale and Tootill, Electronic Computers, second edition, 1970, p. 125.
}}
He thought the answer might be 99,736, whose square is 9,947,269,696; but he couldn't be certain.

;Task

The task is to find out if Babbage had the right answer -- and to do so, as far as your language allows it, in code that Babbage himself would have been able to read and understand.
As Babbage evidently solved the task with pencil and paper, a similar efficient solution is preferred.

For these purposes, Charles Babbage may be taken to be an intelligent person, familiar with mathematics and with the idea of a computer; he has written the first drafts of simple computer programmes in tabular form. [Babbage Archive Series L].

;Motivation

The aim of the task is to write a program that is sufficiently clear and well-documented for such a person to be able to read it and be confident that it does indeed solve the specified problem.

Solution:
// Every line starting with a double slash will be ignored by the processing machine,
// just like these two.
//
// Since the square root of 269,696 is approximately 519, we create a variable named "n"
// and give it this value.
  n = 519

// The while-condition is in parentheses
// * is for multiplication
// % is for modulo operation
// != is for "not equal"
  while ( ((n * n) % 1000000) != 269696 )
    n = n + 1

// n is incremented until the while-condition is met, so n should finally be the
// smallest positive integer whose square ends in the digits 269,696. To see n, we
// need to send it to the monitoring device (named console).
  console.log(n)


Balanced brackets

'''Task''':
* Generate a string with   '''N'''   opening brackets   '''['''   and with   '''N'''   closing brackets   ''']''',   in some arbitrary order.
* Determine whether the generated string is ''balanced''; that is, whether it consists entirely of pairs of opening/closing brackets (in that order), none of which mis-nest.

;Examples:
    (empty)      OK
    []           OK
    [][]         OK
    [[][]]       OK
    ][         NOT OK
    ][][       NOT OK
    []][[]     NOT OK

Solution:
function shuffle(str) {
  var a = str.split(''), b, c = a.length, d
  while (c) b = Math.random() * c-- | 0, d = a[c], a[c] = a[b], a[b] = d
  return a.join('')
}

function isBalanced(str) {
  var a = str, b
  do { b = a, a = a.replace(/\[\]/g, '') } while (a != b)
  return !a
}

var M = 20
while (M-- > 0) {
  var N = Math.random() * 10 | 0, bs = shuffle('['.repeat(N) + ']'.repeat(N))
  console.log('"' + bs + '" is ' + (isBalanced(bs) ? '' : 'un') + 'balanced')
}


Barnsley fern

A Barnsley fern is a fractal named after British mathematician Michael Barnsley and can be created using an iterated function system (IFS).

;Task:
Create this fractal fern, using the following transformations:
* f1   (chosen 1% of the time)
         xn + 1 = 0
         yn + 1 = 0.16 yn

* f2   (chosen 85% of the time)
         xn + 1 = 0.85 xn + 0.04 yn
         yn + 1 = -0.04 xn + 0.85 yn + 1.6

* f3   (chosen 7% of the time)
         xn + 1 = 0.2 xn - 0.26 yn
         yn + 1 = 0.23 xn + 0.22 yn + 1.6

* f4   (chosen 7% of the time)
         xn + 1 = -0.15 xn + 0.28 yn
         yn + 1 = 0.26 xn + 0.24 yn + 0.44.

Starting position: x = 0, y = 0

Solution:
// Barnsley fern fractal
//6/17/16 aev
function pBarnsleyFern(canvasId, lim) {
    // DCLs
    var canvas = document.getElementById(canvasId);
    var ctx = canvas.getContext("2d");
    var w = canvas.width;
    var h = canvas.height;
    var x = 0.,
        y = 0.,
        xw = 0.,
        yw = 0.,
        r;
    // Like in PARI/GP: return random number 0..max-1
    function randgp(max) {
        return Math.floor(Math.random() * max)
    }
    // Clean canvas
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, w, h);
    // MAIN LOOP
    for (var i = 0; i < lim; i++) {
        r = randgp(100);
        if (r <= 1) {
            xw = 0;
            yw = 0.16 * y;
        } else if (r <= 8) {
            xw = 0.2 * x - 0.26 * y;
            yw = 0.23 * x + 0.22 * y + 1.6;
        } else if (r <= 15) {
            xw = -0.15 * x + 0.28 * y;
            yw = 0.26 * x + 0.24 * y + 0.44;
        } else {
            xw = 0.85 * x + 0.04 * y;
            yw = -0.04 * x + 0.85 * y + 1.6;
        }
        x = xw;
        y = yw;
        ctx.fillStyle = "green";
        ctx.fillRect(x * 50 + 260, -y * 50 + 540, 1, 1);
    } //fend i
}


Base64 decode data

See [[Base64 encode data]].

Now write a program that takes the output of the [[Base64 encode data]] task as input and regenerate the original file.

When working on the VBA implementation I found several 'solutions' on the net, including one from the software maker himself, that showed output with incorrect padding. Obviously with incorrect padding in the output you can not decode correctly to the original file again.

Solution:
// define base64 data; in this case the data is the string: "Hello, world!"
const base64 = Buffer.from('SGVsbG8sIHdvcmxkIQ==', 'base64');
// <Buffer>.toString() is a built-in method.
console.log(base64.toString());


Benford's law

{{Wikipedia|Benford's_law}}

'''Benford's law''', also called the '''first-digit law''', refers to the frequency distribution of digits in many (but not all) real-life sources of data.

In this distribution, the number 1 occurs as the first digit about 30% of the time, while larger numbers occur in that position less frequently: 9 as the first digit less than 5% of the time. This distribution of first digits is the same as the widths of gridlines on a logarithmic scale.

Benford's law also concerns the expected distribution for digits beyond the first, which approach a uniform distribution.

This result has been found to apply to a wide variety of data sets, including electricity bills, street addresses, stock prices, population numbers, death rates, lengths of rivers, physical and mathematical constants, and processes described by power laws (which are very common in nature). It tends to be most accurate when values are distributed across multiple orders of magnitude.

A set of numbers is said to satisfy Benford's law if the leading digit d  (d \in \{1, \ldots, 9\}) occurs with probability

:::: P(d) = \log_{10}(d+1)-\log_{10}(d) = \log_{10}\left(1+\frac{1}{d}\right)

For this task, write (a) routine(s) to calculate the distribution of first significant (non-zero) digits in a collection of numbers, then display the actual vs. expected distribution in the way most convenient for your language (table / graph / histogram / whatever).

Use the first 1000 numbers from the Fibonacci sequence as your data set. No need to show how the Fibonacci numbers are obtained.

You can generate them or load them from a file; whichever is easiest.

Display your actual vs expected distribution.

''For extra credit:'' Show the distribution for one other set of numbers from a page on Wikipedia. State which Wikipedia page it can be obtained from and what the set enumerates. Again, no need to display the actual list of numbers or the code to load them.

;See also:
* numberphile.com.
* A starting page on Wolfram Mathworld is {{Wolfram|Benfords|Law}}.

Solution:
const fibseries = n => [...Array(n)]
    .reduce(
        (fib, _, i) => i < 2 ? (
            fib
        ) : fib.concat(fib[i - 1] + fib[i - 2]),
        [1, 1]
    );

const benford = array => [1, 2, 3, 4, 5, 6, 7, 8, 9]
    .map(val => [val, array
        .reduce(
            (sum, item) => sum + (
                `${item}` [0] === `${val}`
            ),
            0
        ) / array.length, Math.log10(1 + 1 / val)
    ]);

console.log(benford(fibseries(1000)))


Best shuffle

Shuffle the characters of a string in such a way that as many of the character values are in a different position as possible.

A shuffle that produces a randomized result among the best choices is to be preferred. A deterministic approach that produces the same sequence every time is acceptable as an alternative.

Display the result as follows:

 original string, shuffled string, (score)

The score gives the number of positions whose character value did ''not'' change.

;Example:
 tree, eetr, (0)

;Test cases:
 abracadabra
 seesaw
 elk
 grrrrrr
 up
 a

;Related tasks
*   [[Anagrams/Deranged anagrams]]
*   [[Permutations/Derangements]]

Solution:
function raze(a) { // like .join('') except producing an array instead of a string
    var r= [];
    for (var j= 0; j<a.length; j++)
        for (var k= 0; k<a[j].length; k++)  r.push(a[j][k]);
    return r;
}
function shuffle(y) {
    var len= y.length;
    for (var j= 0; j < len; j++) {
        var i= Math.floor(Math.random()*len);
        var t= y[i];
        y[i]= y[j];
        y[j]= t;
    }
    return y;
}
function bestShuf(txt) {
    var chs= txt.split('');
    var gr= {};
    var mx= 0;
    for (var j= 0; j<chs.length; j++) {
        var ch= chs[j];
        if (null == gr[ch])  gr[ch]= [];
        gr[ch].push(j);
        if (mx < gr[ch].length)  mx++;
    }
    var inds= [];
    for (var ch in gr)  inds.push(shuffle(gr[ch]));
    var ndx= raze(inds);
    var cycles= [];
    for (var k= 0; k < mx; k++)  cycles[k]= [];
    for (var j= 0; j<chs.length; j++)  cycles[j%mx].push(ndx[j]);
    var ref= raze(cycles);
    for (var k= 0; k < mx; k++)  cycles[k].push(cycles[k].shift());
    var prm= raze(cycles);
    var shf= [];
    for (var j= 0; j<chs.length; j++)  shf[ref[j]]= chs[prm[j]];
    return shf.join('');
}

function disp(ex) {
    var r= bestShuf(ex);
    var n= 0;
    for (var j= 0; j<ex.length; j++)
        n+= ex.substr(j, 1) == r.substr(j,1) ?1 :0;
    return ex+', '+r+', ('+n+')';
}


Bioinformatics/Sequence mutation

Given a string of characters A, C, G, and T representing a DNA sequence write a routine to mutate the sequence, (string) by:
# Choosing a random base position in the sequence.
# Mutate the sequence by  doing one of either:
## '''S'''wap the base at that position by changing it to one of A, C, G, or T. (which has a chance of swapping the base for the same base)
## '''D'''elete the chosen base at the position.
## '''I'''nsert another base randomly chosen from A,C, G, or T into the sequence at that position.
# Randomly generate a test DNA sequence of at least 200 bases
# "Pretty print" the sequence and a count of its size, and the count of each base in the sequence
# Mutate the sequence ten times.
# "Pretty print" the sequence after all mutations, and a count of its size, and the count of each base in the sequence.

;Extra credit:
* Give more information on the individual mutations applied.
* Allow mutations to be weighted and/or chosen.

Solution:
// Basic set-up
const numBases = 250
const numMutations = 30
const bases = ['A', 'C', 'G', 'T'];

// Utility functions
/**
 * Return a shallow copy of an array
 * @param {Array<*>} arr
 * @returns {*[]}
 */
const copy = arr => [...arr];

/**
 * Get a random int up to but excluding the the given number
 * @param {number} max
 * @returns {number}
 */
const randTo = max => (Math.random() * max) | 0;

/**
 * Given an array return a random element and the index of that element from
 * the array.
 * @param {Array<*>} arr
 * @returns {[*[], number]}
 */
const randSelect = arr => {
  const at = randTo(arr.length);
  return [arr[at], at];
};

/**
 * Given a number or string, return a left padded string
 * @param {string|number} v
 * @returns {string}
 */
const pad = v => ('' + v).padStart(4, ' ');

/**
 * Count the number of elements that match the given value in an array
 * @param {Array<string>} arr
 * @returns {function(string): number}
 */
const filterCount = arr => s => arr.filter(e => e === s).length;

/**
 * Utility logging function
 * @param {string|number} v
 * @param {string|number} n
 */
const print = (v, n) => console.log(`${pad(v)}:\t${n}`)

/**
 * Utility function to randomly select a new base, and an index in the given
 * sequence.
 * @param {Array<string>} seq
 * @param {Array<string>} bases
 * @returns {[string, string, number]}
 */
const getVars = (seq, bases) => {
  const [newBase, _] = randSelect(bases);
  const [extBase, randPos] = randSelect(seq);
  return [newBase, extBase, randPos];
};

// Bias the operations
/**
 * Given a map of function to ratio, return an array of those functions
 * appearing ratio number of times in the array.
 * @param weightMap
 * @returns {Array<function>}
 */
const weightedOps = weightMap => {
  return [...weightMap.entries()].reduce((p, [op, weight]) =>
      [...p, ...(Array(weight).fill(op))], []);
};

// Pretty Print functions
const prettyPrint = seq => {
  let idx = 0;
  const rem = seq.reduce((p, c) => {
    const s = p + c;
    if (s.length === 50) {
      print(idx, s);
      idx = idx + 50;
      return '';
    }
    return s;
  }, '');
  if (rem !== '') {
    print(idx, rem);
  }
}

const printBases = seq => {
  const filterSeq = filterCount(seq);
  let tot = 0;
  [...bases].forEach(e => {
    const cnt = filterSeq(e);
    print(e, cnt);
    tot = tot + cnt;
  })
  print('Σ', tot);
}

// Mutation definitions
const swap = ([hist, seq]) => {
  const arr = copy(seq);
  const [newBase, extBase, randPos] = getVars(arr, bases);
  arr.splice(randPos, 1, newBase);
  return [[...hist, `Swapped ${extBase} for ${newBase} at ${randPos}`], arr];
};

const del = ([hist, seq]) => {
  const arr = copy(seq);
  const [newBase, extBase, randPos] = getVars(arr, bases);
  arr.splice(randPos, 1);
  return [[...hist, `Deleted ${extBase} at ${randPos}`], arr];
}

const insert = ([hist, seq]) => {
  const arr = copy(seq);
  const [newBase, extBase, randPos] = getVars(arr, bases);
  arr.splice(randPos, 0, newBase);
  return [[...hist, `Inserted ${newBase} at ${randPos}`], arr];
}

// Create the starting sequence
const seq = Array(numBases).fill(undefined).map(
    () => randSelect(bases)[0]);

// Create a weighted set of mutations
const weightMap = new Map()
    .set(swap, 1)
    .set(del, 1)
    .set(insert, 1);
const operations = weightedOps(weightMap);
const mutations = Array(numMutations).fill(undefined).map(
    () => randSelect(operations)[0]);

// Mutate the sequence
const [hist, mut] = mutations.reduce((p, c) => c(p), [[], seq]);

console.log('ORIGINAL SEQUENCE:')
prettyPrint(seq);

console.log('\nBASE COUNTS:')
printBases(seq);

console.log('\nMUTATION LOG:')
hist.forEach((e, i) => console.log(`${i}:\t${e}`));

console.log('\nMUTATED SEQUENCE:')
prettyPrint(mut);

console.log('\nMUTATED BASE COUNTS:')
printBases(mut);


Bioinformatics/base count

Given this string representing ordered DNA bases:

CGTAAAAAATTACAACGTCCTTTGGCTATCTCTTAAACTCCTGCTAAATG
CTCGTGCTTTCCAATTATGTAAGCGTTCCGAGACGGGGTGGTCGATTCTG
AGGACAAAGGTCAAGATGGAGCGCATCGAACGCAATAAGGATCATTTGAT
GGGACGTTTCGTCGACAAAGTCTTGTTTCGAGAGTAACGGCTACCGTCTT
CGATTCTGCTTATAACACTATGTTCTTATGAAATGGATGTTCTGAGTTGG
TCAGTCCCAATGTGCGGGGTTTCTTTTAGTACGTCGGGAGTGGTATTATA
TTTAATTTTTCTATATAGCGATCTGTATTTAAGCAATTCATTTAGGTTAT
CGCCGCGATGCTCGGTTCGGACCGCCAAGCATCTGGCTCCACTGCTAGTG
TCCTAAATTTGAATGGCAAACACAAATAAGATTTAGCAATTCGTGTAGAC
GACCGGGGACTTGCATGATGGGAGCAGCTTTGTTAAACTACGAACGTAAT

;Task:
:*   "Pretty print" the sequence followed by a summary of the counts of each of the bases:   ('''A''', '''C''', '''G''', and '''T''')   in the sequence
:*   print the total count of each base in the string.

Solution:
const rowLength = 50;

const bases = ['A', 'C', 'G', 'T'];

// Create the starting sequence
const seq = `CGTAAAAAATTACAACGTCCTTTGGCTATCTCTTAAACTCCTGCTAAATG
CTCGTGCTTTCCAATTATGTAAGCGTTCCGAGACGGGGTGGTCGATTCTG
AGGACAAAGGTCAAGATGGAGCGCATCGAACGCAATAAGGATCATTTGAT
GGGACGTTTCGTCGACAAAGTCTTGTTTCGAGAGTAACGGCTACCGTCTT
CGATTCTGCTTATAACACTATGTTCTTATGAAATGGATGTTCTGAGTTGG
TCAGTCCCAATGTGCGGGGTTTCTTTTAGTACGTCGGGAGTGGTATTATA
TTTAATTTTTCTATATAGCGATCTGTATTTAAGCAATTCATTTAGGTTAT
CGCCGCGATGCTCGGTTCGGACCGCCAAGCATCTGGCTCCACTGCTAGTG
TCCTAAATTTGAATGGCAAACACAAATAAGATTTAGCAATTCGTGTAGAC
GACCGGGGACTTGCATGATGGGAGCAGCTTTGTTAAACTACGAACGTAAT`
    .split('')
    .filter(e => bases.includes(e))

/**
 * Convert the given array into an array of smaller arrays each with the length
 * given by n.
 * @param {number} n
 * @returns {function(!Array<*>): !Array<!Array<*>>}
 */
const chunk = n => a => a.reduce(
    (p, c, i) => (!(i % n)) ? p.push([c]) && p : p[p.length - 1].push(c) && p,
    []);
const toRows = chunk(rowLength);

/**
 * Given a number, return function that takes a string and left pads it to n
 * @param {number} n
 * @returns {function(string): string}
 */
const padTo = n => v => ('' + v).padStart(n, ' ');
const pad = padTo(5);

/**
 * Count the number of elements that match the given value in an array
 * @param {Array<string>} arr
 * @returns {function(string): number}
 */
const countIn = arr => s => arr.filter(e => e === s).length;

/**
 * Utility logging function
 * @param {string|number} v
 * @param {string|number} n
 */
const print = (v, n) => console.log(`${pad(v)}:\t${n}`)

const prettyPrint = seq => {
  const chunks = toRows(seq);
  console.log('SEQUENCE:')
  chunks.forEach((e, i) => print(i * rowLength, e.join('')))
}

const printBases = (seq, bases) => {
  const filterSeq = countIn(seq);
  const counts = bases.map(filterSeq);
  console.log('\nBASE COUNTS:')
  counts.forEach((e, i) => print(bases[i], e));
  print('Total', counts.reduce((p,c) => p + c, 0));
}

prettyPrint(seq);
printBases(seq, bases);


Box the compass

Avast me hearties!
There be many a land lubber that knows naught of the pirate ways and gives direction by degree!
They know not how to box the compass!

;Task description:
# Create a function that takes a heading in degrees and returns the correct 32-point compass heading.
# Use the function to print and display a table of Index, Compass point, and Degree; rather like the corresponding columns from, the first table of the wikipedia article, but use only the following 33 headings as input:
:[0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37, 84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75, 185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13, 270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37, 354.38]. (They should give the same order of points but are spread throughout the ranges of acceptance).

;Notes;
* The headings and indices can be calculated from this pseudocode:
for i in 0..32 inclusive:
    heading = i * 11.25
    case i %3:
      if 1: heading += 5.62; break
      if 2: heading -= 5.62; break
    end
    index = ( i mod 32) + 1
* The column of indices can be thought of as an enumeration of the thirty two cardinal points (see talk page)..

Solution:
(() => {
    'use strict';

    // GENERIC FUNCTIONS

    // toTitle :: String -> String
    let toTitle = s => s.length ? (s[0].toUpperCase() + s.slice(1)) : '';

    // COMPASS DATA AND FUNCTIONS

    // Scale invariant keys for points of the compass
    // (allows us to look up a translation for one scale of compass (32 here)
    // for use in another size of compass (8 or 16 points)
    // (Also semi-serviceable as more or less legible keys without translation)

    // compassKeys :: Int -> [String]
    let compassKeys = depth => {
        let urCompass = ['N', 'S', 'N'],
            subdivision = (compass, n) => n <= 1 ? (
                compass
            ) : subdivision( // Borders between N and S engender E and W.
                // other new boxes concatenate their parent keys.
                compass.reduce((a, x, i, xs) => {
                    if (i > 0) {
                        return (n === depth) ? (
                            a.concat([x === 'N' ? 'W' : 'E'], x)
                        ) : a.concat([xs[i - 1] + x, x]);
                    } else return a.concat(x);
                }, []),
                n - 1
            );
        return subdivision(urCompass, depth)
            .slice(0, -1);
    };

    // https://zh.wikipedia.org/wiki/%E7%BD%97%E7%9B%98%E6%96%B9%E4%BD%8D
    let lstLangs = [{
        'name': 'English',
        expansions: {
            N: 'north',
            S: 'south',
            E: 'east',
            W: 'west',
            b: ' by ',
            '-': '-'
        },
        'N': 'N',
        'NNNE': 'NbE',
        'NNE': 'N-NE',
        'NNENE': 'NEbN',
        'NE': 'NE',
        'NENEE': 'NEbE',
        'NEE': 'E-NE',
        'NEEE': 'EbN',
        'E': 'E',
        'EEES': 'EbS',
        'EES': 'E-SE',
        'EESES': 'SEbE',
        'ES': 'SE',
        'ESESS': 'SEbS',
        'ESS': 'S-SE',
        'ESSS': 'SbE',
        'S': 'S',
        'SSSW': 'SbW',
        'SSW': 'S-SW',
        'SSWSW': 'SWbS',
        'SW': 'SW',
        'SWSWW': 'SWbW',
        'SWW': 'W-SW',
        'SWWW': 'WbS',
        'W': 'W',
        'WWWN': 'WbN',
        'WWN': 'W-NW',
        'WWNWN': 'NWbW',
        'WN': 'NW',
        'WNWNN': 'NWbN',
        'WNN': 'N-NW',
        'WNNN': 'NbW'
    }, {
        'name': 'Chinese',
        'N': '北',
        'NNNE': '北微东',
        'NNE': '东北偏北',
        'NNENE': '东北微北',
        'NE': '东北',
        'NENEE': '东北微东',
        'NEE': '东北偏东',
        'NEEE': '东微北',
        'E': '东',
        'EEES': '东微南',
        'EES': '东南偏东',
        'EESES': '东南微东',
        'ES': '东南',
        'ESESS': '东南微南',
        'ESS': '东南偏南',
        'ESSS': '南微东',
        'S': '南',
        'SSSW': '南微西',
        'SSW': '西南偏南',
        'SSWSW': '西南微南',
        'SW': '西南',
        'SWSWW': '西南微西',
        'SWW': '西南偏西',
        'SWWW': '西微南',
        'W': '西',
        'WWWN': '西微北',
        'WWN': '西北偏西',
        'WWNWN': '西北微西',
        'WN': '西北',
        'WNWNN': '西北微北',
        'WNN': '西北偏北',
        'WNNN': '北微西'
    }];

    // pointIndex :: Int -> Num -> Int
    let pointIndex = (power, degrees) => {
        let nBoxes = (power ? Math.pow(2, power) : 32);
        return Math.ceil(
            (degrees + (360 / (nBoxes * 2))) % 360 * nBoxes / 360
        ) || 1;
    };

    // pointNames :: Int -> Int -> [String]
    let pointNames = (precision, iBox) => {
        let k = compassKeys(precision)[iBox - 1];
        return lstLangs.map(dctLang => {
            let s = dctLang[k] || k, // fallback to key if no translation
                dctEx = dctLang.expansions;

            return dctEx ? toTitle(s.split('')
                    .map(c => dctEx[c])
                    .join(precision > 5 ? ' ' : ''))
                .replace(/  /g, ' ') : s;
        });
    };

    // maximumBy :: (a -> a -> Ordering) -> [a] -> a
    let maximumBy = (f, xs) =>
        xs.reduce((a, x) => a === undefined ? x : (
            f(x, a) > 0 ? x : a
        ), undefined);

    // justifyLeft :: Int -> Char -> Text -> Text
    let justifyLeft = (n, cFiller, strText) =>
        n > strText.length ? (
            (strText + replicate(n, cFiller)
                .join(''))
            .substr(0, n)
        ) : strText;

    // justifyRight :: Int -> Char -> Text -> Text
    let justifyRight = (n, cFiller, strText) =>
        n > strText.length ? (
            (replicate(n, cFiller)
                .join('') + strText)
            .slice(-n)
        ) : strText;

    // replicate :: Int -> a -> [a]
    let replicate = (n, a) => {
        let v = [a],
            o = [];
        if (n < 1) return o;
        while (n > 1) {
            if (n & 1) o = o.concat(v);
            n >>= 1;
            v = v.concat(v);
        }
        return o.concat(v);
    };

    // transpose :: [[a]] -> [[a]]
    let transpose = xs =>
        xs[0].map((_, iCol) => xs.map((row) => row[iCol]));

    // length :: [a] -> Int
    // length :: Text -> Int
    let length = xs => xs.length;

    // compareByLength = (a, a) -> (-1 | 0 | 1)
    let compareByLength = (a, b) => {
        let [na, nb] = [a, b].map(length);
        return na < nb ? -1 : na > nb ? 1 : 0;
    };

    // maxLen :: [String] -> Int
    let maxLen = xs => maximumBy(compareByLength, xs)
        .length;

    // compassTable :: Int -> [Num] -> Maybe String
    let compassTable = (precision, xs) => {
        if (precision < 1) return undefined;
        else {
            let intPad = 2;

            let lstIndex = xs.map(x => pointIndex(precision, x)),
                lstStrIndex = lstIndex.map(x => x.toString()),
                nIndexWidth = maxLen(lstStrIndex),
                colIndex = lstStrIndex.map(
                    x => justifyRight(nIndexWidth, ' ', x)
                );

            let lstAngles = xs.map(x => x.toFixed(2) + '°'),
                nAngleWidth = maxLen(lstAngles) + intPad,
                colAngles = lstAngles.map(x => justifyRight(nAngleWidth, ' ', x));

            let lstTrans = transpose(
                    lstIndex.map(i => pointNames(precision, i))
                ),
                lstTransWidths = lstTrans.map(x => maxLen(x) + 2),
                colsTrans = lstTrans
                .map((lstLang, i) => lstLang
                    .map(x => justifyLeft(lstTransWidths[i], ' ', x))
                );

            return transpose([colIndex]
                    .concat([colAngles], [replicate(lstIndex.length, "  ")])
                    .concat(colsTrans))
                .map(x => x.join(''))
                .join('\n');
        }
    }

    // TEST
    let xs = [0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37,
        84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75,
        185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13,
        270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37,
        354.38
    ];

    // If we supply other precisions, like 4 or 6, (2^n -> 16 or 64 boxes)
    // the bearings will be divided amongst smaller or larger numbers of boxes,
    // either using name translations retrieved by the generic hash
    // or using the hash itself (combined with any expansions)
    // to substitute for missing names for very finely divided boxes.

    return compassTable(5, xs); // 2^5 -> 32 boxes
})();


CSV data manipulation

CSV spreadsheet files are suitable for storing tabular data in a relatively portable way.

The CSV format is flexible but somewhat ill-defined.

For present purposes, authors may assume that the data fields contain no commas, backslashes, or quotation marks.

;Task:
Read a CSV file, change some values and save the changes back to a file.

For this task we will use the following CSV file:

 C1,C2,C3,C4,C5
 1,5,9,13,17
 2,6,10,14,18
 3,7,11,15,19
 4,8,12,16,20

Suggestions

 Show how to add a column, headed 'SUM', of the sums of the rows.
 If possible, illustrate the use of built-in or standard functions, methods, or libraries, that handle generic CSV files.

Solution:
(function () {
    'use strict';

    // splitRegex :: Regex -> String -> [String]
    function splitRegex(rgx, s) {
        return s.split(rgx);
    }

    // lines :: String -> [String]
    function lines(s) {
        return s.split(/[\r\n]/);
    }

    // unlines :: [String] -> String
    function unlines(xs) {
        return xs.join('\n');
    }

    // macOS JavaScript for Automation version of readFile.
    // Other JS contexts will need a different definition of this function,
    // and some may have no access to the local file system at all.

    // readFile :: FilePath -> maybe String
    function readFile(strPath) {
        var error = $(),
            str = ObjC.unwrap(
                $.NSString.stringWithContentsOfFileEncodingError(
                    $(strPath)
                    .stringByStandardizingPath,
                    $.NSUTF8StringEncoding,
                    error
                )
            );
        return error.code ? error.localizedDescription : str;
    }

    // macOS JavaScript for Automation version of writeFile.
    // Other JS contexts will need a different definition of this function,
    // and some may have no access to the local file system at all.

    // writeFile :: FilePath -> String -> IO ()
    function writeFile(strPath, strText) {
        $.NSString.alloc.initWithUTF8String(strText)
            .writeToFileAtomicallyEncodingError(
                $(strPath)
                .stringByStandardizingPath, false,
                $.NSUTF8StringEncoding, null
            );
    }

    // EXAMPLE - appending a SUM column

    var delimCSV = /,\s*/g;

    var strSummed = unlines(
        lines(readFile('~/csvSample.txt'))
        .map(function (x, i) {
            var xs = x ? splitRegex(delimCSV, x) : [];

            return (xs.length ? xs.concat(
                // 'SUM' appended to first line, others summed.
                i > 0 ? xs.reduce(
                    function (a, b) {
                        return a + parseInt(b, 10);
                    }, 0
                ).toString() : 'SUM'
            ) : []).join(',');
        })
    );

    return (
        writeFile('~/csvSampleSummed.txt', strSummed),
        strSummed
    );

})();


CSV to HTML translation

Consider a simplified CSV format where all rows are separated by a newline
and all columns are separated by commas.

No commas are allowed as field data, but the data may contain
other characters and character sequences that would
normally be   ''escaped''   when converted to HTML

;Task:
Create a function that takes a string representation of the CSV data
and returns a text string of an HTML table representing the CSV data.

Use the following  data as the CSV text to convert, and show your output.
: Character,Speech
: The multitude,The messiah! Show us the messiah!
: Brians mother,Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!
: The multitude,Who are you?
: Brians mother,I'm his mother; that's who!
: The multitude,Behold his mother! Behold his mother!

;Extra credit:
''Optionally'' allow special formatting for the first row of the table as if it is the tables header row
(via  preferably; CSS if you must).

Solution:
var csv = "Character,Speech\n" +
	   "The multitude,The messiah! Show us the messiah!\n" +
	   "Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>\n" +
	   "The multitude,Who are you?\n" +
	   "Brians mother,I'm his mother; that's who!\n" +
	   "The multitude,Behold his mother! Behold his mother!";

var lines = csv.replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/"/g, '"')
    .split(/[\n\r]/)
    .map(function(line) { return line.split(',')})
    .map(function(row) {return '\t\t
' + row[0] + '	' + row[1] + '
';});

console.log('
\n\t
\n'      + lines[0] +
            '\n\t
\n\t
\n' + lines.slice(1).join('\n') +
            '\t
\n
');


Calculating the value of e

Calculate the value of   ''e''.

(''e''   is also known as   ''Euler's number''   and   ''Napier's constant''.)

See details: Calculating the value of e

Solution:
(() => {
    "use strict";

    // - APPROXIMATION OF E OBTAINED AFTER N ITERATIONS --

    // eApprox : Int -> Float
    const eApprox = n =>
        sum(
            scanl(mul)(1)(
                enumFromTo(1)(n)
            )
            .map(x => 1 / x)
        );

    // ---------------------- TEST -----------------------
    const main = () =>
        eApprox(20);

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

    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = m =>
        n => Array.from({
            length: 1 + n - m
        }, (_, i) => m + i);

    // mul (*) :: Num a => a -> a -> a
    const mul = a =>
        // The arithmetic product of a and b.
        b => a * b;

    // scanl :: (b -> a -> b) -> b -> [a] -> [b]
    const scanl = f => startValue => xs =>
        // The series of interim values arising
        // from a catamorphism. Parallel to foldl.
        xs.reduce((a, x) => {
            const v = f(a[0])(x);

            return [v, a[1].concat(v)];
        }, [startValue, [startValue]])[1];

    // sum :: [Num] -> Num
    const sum = xs =>
        // The numeric sum of all values in xs.
        xs.reduce((a, x) => a + x, 0);

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


Call a function

Demonstrate the different syntax and semantics provided for calling a function.

This may include:
:*   Calling a function that requires no arguments
:*   Calling a function with a fixed number of arguments
:*   Calling a function with optional arguments
:*   Calling a function with a variable number of arguments
:*   Calling a function with named arguments
:*   Using a function in statement context
:*   Using a function in first-class context within an expression
:*   Obtaining the return value of a function
:*   Distinguishing built-in functions and user-defined functions
:*   Distinguishing subroutines and functions
;*   Stating whether arguments are passed by value or by reference
;*   Is partial application possible and how

This task is ''not'' about defining functions.

Solution:
var mutate = function(victim) {
    victim[0] = null;
    victim = 42;
};
var foo = [1, 2, 3];
mutate(foo) // foo is now [null, 2, 3], not 42


Canonicalize CIDR

Implement a function or program that, given a range of IPv4 addresses in CIDR notation (dotted-decimal/network-bits), will return/output the same range in canonical form.

That is, the IP address portion of the output CIDR block must not contain any set (1) bits in the host part of the address.

;Example:
Given   '''87.70.141.1/22''',    your code should output    '''87.70.140.0/22'''

;Explanation:
An Internet Protocol version 4 address is a 32-bit value, conventionally represented as a number in base 256 using dotted-decimal notation, where each base-256 digit is given in decimal and the digits are separated by periods. Logically, this 32-bit value represents two components: the leftmost (most-significant) bits determine the network portion of the address, while the rightmost (least-significant) bits determine the host portion. Classless Internet Domain Routing block notation indicates where the boundary between these two components is for a given address by adding a slash followed by the number of bits in the network portion.

In general, CIDR blocks stand in for the entire set of IP addresses sharing the same network component, so it's common to see access control lists that specify individual IP addresses using /32 to indicate that only the one address is included. Software accepting this notation as input often expects it to be entered in canonical form, in which the host bits are all zeroes. But network admins sometimes skip this step and just enter the address of a specific host on the subnet with the network size, resulting in a non-canonical entry.

The example address, 87.70.141.1/22, represents binary 0101011101000110100011 / 0100000001, with the / indicating the network/host division. To canonicalize, clear all the bits to the right of the / and convert back to dotted decimal: 0101011101000110100011 / 0000000000 - 87.70.140.0.

;More examples for testing

        36.18.154.103/12    -  36.16.0.0/12
        62.62.197.11/29     -  62.62.197.8/29
        67.137.119.181/4    -  64.0.0.0/4
        161.214.74.21/24    -  161.214.74.0/24
        184.232.176.184/18  -  184.232.128.0/18

Solution:
const canonicalize = s => {

    // Prepare a DataView over a 16 Byte Array buffer.
    // Initialised to all zeros.
    const dv = new DataView(new ArrayBuffer(16));

    // Get the ip-address and cidr components
    const [ip, cidr] = s.split('/');

    // Make sure the cidr component is a usable int, and
    // default to 32 if it does not exist.
    const cidrInt = parseInt(cidr || 32, 10);

    // Populate the buffer with uint8 ip address components.
    // Use zero as the default for shorthand pool definitions.
    ip.split('.').forEach(
        (e, i) => dv.setUint8(i, parseInt(e || 0, 10))
    );

    // Grab the whole buffer as a uint32
    const ipAsInt = dv.getUint32(0);

    // Zero out the lower bits as per the CIDR number.
    const normIpInt = (ipAsInt >> 32 - cidrInt) << 32 - cidrInt;

    // Plonk it back into the buffer
    dv.setUint32(0, normIpInt);

    // Read each of the uint8 slots in the buffer and join them with a dot.
    const canonIp = [...'0123'].map((e, i) => dv.getUint8(i)).join('.');

    // Attach the cidr number to the back of the normalised IP address.
    return [canonIp, cidrInt].join('/');
  }

  const test = s => console.log(s, '->', canonicalize(s));
  [
    '255.255.255.255/10',
    '87.70.141.1/22',
    '36.18.154.103/12',
    '62.62.197.11/29',
    '67.137.119.181/4',
    '161.214.74.21/24',
    '184.232.176.184/18',
    '10.207.219.251/32',
    '10.207.219.251',
    '110.200.21/4',
    '10..55/8',
    '10.../8'
  ].forEach(test)


Cantor set

Draw a Cantor set.

See details at this Wikipedia webpage:   Cantor set

Solution:
(() => {
    "use strict";

    // -------------- CANTOR RATIONAL PAIRS --------------

    // cantor :: [(Rational, Rational)] ->
    //           [(Rational, Rational)]
    const cantor = xs => {
        const go = ab => {
            const [r1, r2] = Array.from(ab).map(rational);
            const third = ratioDiv(ratioMinus(r2)(r1))(3);

            return [
                Tuple(r1)(ratioPlus(r1)(third)),
                Tuple(ratioMinus(r2)(third))(r2)
            ];
        };

        return xs.flatMap(go);
    };

    // ---------------------- TEST -----------------------
    // main :: IO ()
    const main = () => {
        const
            xs = take(4)(
                iterate(cantor)([Tuple(0)(1)])
            );

        return [
                `${unlines(xs.map(intervalRatios))}\n`,
                intervalBars(xs)
            ]
            .join("\n\n");
    };

    // --------------------- DISPLAY ---------------------

    // intervalRatios :: [(Rational, Rational)] -> String
    const intervalRatios = xs => {
        const go = ab =>
            Array.from(ab).map(
                compose(showRatio, rational)
            )
            .join(", ");

        return `(${xs.map(go).join(") (")})`;
    };

    // intervalBars :: [[(Rational, Rational)]] -> String
    const intervalBars = rs => {
        const go = w => xs =>
            snd(mapAccumL(
                a => ab => {
                    const [wx, wy] = Array.from(ab).map(
                        r => ratioMult(w)(
                            rational(r)
                        )
                    );

                    return Tuple(wy)(
                        replicateString(
                            floor(ratioMinus(wx)(a))
                        )(" ") + replicateString(
                            floor(ratioMinus(wy)(wx))
                        )("█")
                    );
                }
            )(0)(xs)).join("");
        const d = maximum(
            last(rs).map(x => fst(x).d)
        );

        return unlines(rs.map(
            go(Ratio(d)(1))
        ));
    };

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

    // Ratio :: Integral a => a -> a -> Ratio a
    const Ratio = a => b => {
        const go = (x, y) =>
            0 !== y ? (() => {
                const d = gcd(x)(y);

                return {
                    type: "Ratio",
                    // numerator
                    "n": Math.trunc(x / d),
                    // denominator
                    "d": Math.trunc(y / d)
                };
            })() : undefined;

        return go(a * signum(b), abs(b));
    };

    // Tuple (,) :: a -> b -> (a, b)
    const Tuple = a =>
        b => ({
            type: "Tuple",
            "0": a,
            "1": b,
            length: 2
        });

    // abs :: Num -> Num
    const abs =
        // Absolute value of a given number
        // without the sign.
        x => 0 > x ? (
            -x
        ) : x;

    // approxRatio :: Float -> Float -> Ratio
    const approxRatio = eps =>
        n => {
            const
                gcde = (e, x, y) => {
                    const _gcd = (a, b) =>
                        b < e ? (
                            a
                        ) : _gcd(b, a % b);

                    return _gcd(Math.abs(x), Math.abs(y));
                },
                c = gcde(Boolean(eps) ? (
                    eps
                ) : (1 / 10000), 1, n);

            return Ratio(
                Math.floor(n / c)
            )(
                Math.floor(1 / c)
            );
        };

    // floor :: Num -> Int
    const floor = x => {
        const
            nr = (
                "Ratio" !== x.type ? (
                    properFraction
                ) : properFracRatio
            )(x),
            n = nr[0];

        return 0 > nr[1] ? n - 1 : n;
    };

    // fst :: (a, b) -> a
    const fst = ab =>
        // First member of a pair.
        ab[0];

    // gcd :: Integral a => a -> a -> a
    const gcd = x =>
        y => {
            const zero = x.constructor(0);
            const go = (a, b) =>
                zero === b ? (
                    a
                ) : go(b, a % b);

            return go(abs(x), abs(y));
        };

    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (...fs) =>
        // A function defined by the right-to-left
        // composition of all the functions in fs.
        fs.reduce(
            (f, g) => x => f(g(x)),
            x => x
        );

    // iterate :: (a -> a) -> a -> Gen [a]
    const iterate = f =>
        // An infinite list of repeated
        // applications of f to x.
        function* (x) {
            let v = x;

            while (true) {
                yield v;
                v = f(v);
            }
        };

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

    // lcm :: Int -> Int -> Int
    const lcm = x =>
        // The smallest positive integer divisible
        // without remainder by both x and y.
        y => (x === 0 || y === 0) ? (
            0
        ) : Math.abs(Math.floor(x / gcd(x)(y)) * y);

    // mapAccumL :: (acc -> x -> (acc, y)) ->
    // acc -> [x] -> (acc, [y])
    const mapAccumL = f =>
        // A tuple of an accumulation and a list
        // obtained by a combined map and fold,
        // with accumulation from left to right.
        acc => xs => [...xs].reduce(
            (a, x) => {
                const ab = f(a[0])(x);

                return [ab[0], a[1].concat(ab[1])];
            },
            [acc, []]
        );

    // maximum :: Ord a => [a] -> a
    const maximum = xs => (
        // The largest value in a non-empty list.
        ys => 0 < ys.length ? (
            ys.slice(1).reduce(
                (a, y) => y > a ? (
                    y
                ) : a, ys[0]
            )
        ) : undefined
    )(xs);

    // properFracRatio :: Ratio -> (Int, Ratio)
    const properFracRatio = nd => {
        const [q, r] = Array.from(quotRem(nd.n)(nd.d));

        return Tuple(q)(Ratio(r)(nd.d));
    };

    // properFraction :: Real -> (Int, Real)
    const properFraction = n => {
        const i = Math.floor(n) + (n < 0 ? 1 : 0);

        return Tuple(i)(n - i);
    };

    // quotRem :: Integral a => a -> a -> (a, a)
    const quotRem = m =>
        // The quotient, tupled with the remainder.
        n => Tuple(
            Math.trunc(m / n)
        )(
            m % n
        );

    // ratioDiv :: Rational -> Rational -> Rational
    const ratioDiv = n1 => n2 => {
        const [r1, r2] = [n1, n2].map(rational);

        return Ratio(r1.n * r2.d)(
            r1.d * r2.n
        );
    };

    // ratioMinus :: Rational -> Rational -> Rational
    const ratioMinus = n1 => n2 => {
        const [r1, r2] = [n1, n2].map(rational);
        const d = lcm(r1.d)(r2.d);

        return Ratio(
            (r1.n * (d / r1.d)) - (r2.n * (d / r2.d))
        )(d);
    };

    // ratioMult :: Rational -> Rational -> Rational
    const ratioMult = n1 => n2 => {
        const [r1, r2] = [n1, n2].map(rational);

        return Ratio(r1.n * r2.n)(
            r1.d * r2.d
        );
    };

    // ratioPlus :: Rational -> Rational -> Rational
    const ratioPlus = n1 =>
        n2 => {
            const [r1, r2] = [n1, n2].map(rational);
            const d = lcm(r1.d)(r2.d);

            return Ratio(
                (r1.n * (d / r1.d)) + (
                    r2.n * (d / r2.d)
                )
            )(d);
        };

    // rational :: Num a => a -> Rational
    const rational = x =>
        isNaN(x) ? x : Number.isInteger(x) ? (
            Ratio(x)(1)
        ) : approxRatio(undefined)(x);

    // replicateString :: Int -> String -> String
    const replicateString = n =>
        s => s.repeat(n);

    // showRatio :: Ratio -> String
    const showRatio = r =>
        "Ratio" !== r.type ? (
            r.toString()
        ) : r.n.toString() + (
            1 !== r.d ? (
                `/${r.d}`
            ) : ""
        );

    // signum :: Num -> Num
    const signum = n =>
        // | Sign of a number.
        n.constructor(
            0 > n ? (
                -1
            ) : (
                0 < n ? 1 : 0
            )
        );

    // snd :: (a, b) -> b
    const snd = ab =>
        // Second member of a pair.
        ab[1];

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n =>
        // The first n elements of a list,
        // string of characters, or stream.
        xs => "GeneratorFunction" !== xs
        .constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat(...Array.from({
            length: n
        }, () => {
            const x = xs.next();

            return x.done ? [] : [x.value];
        }));

    // 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");

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


Cartesian product of two or more lists

Show one or more idiomatic ways of generating the Cartesian product of two arbitrary lists in your language.

Demonstrate that your function/method correctly returns:
::{1, 2} x {3, 4} = {(1, 3), (1, 4), (2, 3), (2, 4)}

and, in contrast:
::{3, 4} x {1, 2} = {(3, 1), (3, 2), (4, 1), (4, 2)}

Also demonstrate, using your function/method, that the product of an empty list with any other list is empty.
:: {1, 2} x {} = {}
:: {} x {1, 2} = {}

For extra credit, show or write a function returning the n-ary product of an arbitrary number of lists, each of arbitrary length. Your function might, for example, accept a single argument which is itself a list of lists, and return the n-ary product of those lists.

Use your n-ary Cartesian product function to show the following products:
:: {1776, 1789} x {7, 12} x {4, 14, 23} x {0, 1}
:: {1, 2, 3} x {30} x {500, 100}
:: {1, 2, 3} x {} x {500, 100}

Solution:
(() => {
    // CARTESIAN PRODUCT OF TWO LISTS ---------------------

    // cartProd :: [a] -> [b] -> [[a, b]]
    const cartProd = xs => ys =>
        xs.flatMap(x => ys.map(y => [x, y]))

    // TEST -----------------------------------------------
    return [
        cartProd([1, 2])([3, 4]),
        cartProd([3, 4])([1, 2]),
        cartProd([1, 2])([]),
        cartProd([])([1, 2]),
    ].map(JSON.stringify).join('\n');
})();


Casting out nines

Task   (in three parts):

;Part 1
Write a procedure (say \mathit{co9}(x)) which implements Casting Out Nines as described by returning the checksum for x. Demonstrate the procedure using the examples given there, or others you may consider lucky.

Note that this function does nothing more than calculate the least positive residue, modulo 9. Many of the solutions omit Part 1 for this reason. Many languages have a modulo operator, of which this is a trivial application.

With that understanding, solutions to Part 1, if given, are encouraged to follow the naive pencil-and-paper or mental arithmetic of repeated digit addition understood to be "casting out nines", or some approach other than just reducing modulo 9 using a built-in operator. Solutions for part 2 and 3 are not required to make use of the function presented in part 1.

;Part 2
Notwithstanding past Intel microcode errors, checking computer calculations like this would not be sensible. To find a computer use for your procedure:
: Consider the statement "318682 is 101558 + 217124 and squared is 101558217124" (see: [[Kaprekar numbers#Casting Out Nines (fast)]]).
: note that 318682 has the same checksum as (101558 + 217124);
: note that 101558217124 has the same checksum as (101558 + 217124) because for a Kaprekar they are made up of the same digits (sometimes with extra zeroes);
: note that this implies that for Kaprekar numbers the checksum of k equals the checksum of k^2.

Demonstrate that your procedure can be used to generate or filter a range of numbers with the property \mathit{co9}(k) = \mathit{co9}(k^2) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;Part 3
Considering this MathWorld page, produce a efficient algorithm based on the more mathematical treatment of Casting Out Nines, and realizing:
: \mathit{co9}(x) is the residual of x mod 9;
: the procedure can be extended to bases other than 9.

Demonstrate your algorithm by generating or filtering a range of numbers with the property k%(\mathit{Base}-1) == (k^2)%(\mathit{Base}-1) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;related tasks
* [[First perfect square in base N with N unique digits]]
* [[Kaprekar numbers]]

Solution:
function main(s, e, bs, pbs) {
    bs = bs || 10;
    pbs = pbs || 10
    document.write('start:', toString(s), ' end:', toString(e),
        ' base:', bs, ' printBase:', pbs)
    document.write('
castOutNine: ');
    castOutNine()
    document.write('
kaprekar: ');
    kaprekar()
    document.write('

')

    function castOutNine() {
        for (var n = s, k = 0, bsm1 = bs - 1; n <= e; n += 1)
            if (n % bsm1 == (n * n) % bsm1) k += 1,
                document.write(toString(n), ' ')
        document.write('
trying ', k, ' numbers instead of ', n = e - s + 1,
            ' numbers saves ', (100 - k / n * 100)
            .toFixed(3), '%')
    }

    function kaprekar() {
        for (var n = s; n <= e; n += 1)
            if (isKaprekar(n)) document.write(toString(n), ' ')

        function isKaprekar(n) {
            if (n < 1) return false
            if (n == 1) return true
            var s = (n * n)
                .toString(bs)
            for (var i = 1, e = s.length; i < e; i += 1) {
                var a = parseInt(s.substr(0, i), bs)
                var b = parseInt(s.substr(i), bs)
                if (b && a + b == n) return true
            }
            return false
        }
    }

    function toString(n) {
        return n.toString(pbs)
            .toUpperCase()
    }
}
main(1, 10 * 10 - 1)
main(1, 16 * 16 - 1, 16)
main(1, 17 * 17 - 1, 17)
main(parseInt('10', 17), parseInt('gg', 17), 17, 17)


Casting out nines

Solution:
(() => {
    'use strict';

    // co9 :: Int -> Int
    const co9 = n =>
        n <= 8 ? n : co9(
            digits(10, n)
            .reduce((a, x) => x !== 9 ? a + x : a, 0)
        );

    // GENERIC FUNCTIONS

    // digits :: Int -> Int -> [Int]
    const digits = (base, n) => {
        if (n < base) return [n];
        const [q, r] = quotRem(n, base);
        return [r].concat(digits(base, q));
    };

    // quotRem :: Integral a => a -> a -> (a, a)
    const quotRem = (m, n) => [Math.floor(m / n), m % n];

    // range :: Int -> Int -> [Int]
    const range = (m, n) =>
        Array.from({
            length: Math.floor(n - m) + 1
        }, (_, i) => m + i);

    // squared :: Num a => a -> a
    const squared = n => Math.pow(n, 2);

    // show :: a -> String
    const show = x => JSON.stringify(x, null, 2);

    // TESTS
    return show({
        test1: co9(232345), //-> 1
        test2: co9(34234234), //-> 7
        test3: co9(232345 + 34234234) === co9(232345) + co9(34234234), //-> true
        test4: co9(232345 * 34234234) === co9(232345) * co9(34234234), //-> true,
        task2: range(1, 100)
            .filter(n => co9(n) === co9(squared(n))),
        task3: (k => range(1, 100)
            .filter(n => (n % k) === (squared(n) % k)))(16)
    });
})();


Catalan numbers/Pascal's triangle

Print out the first   '''15'''   Catalan numbers by extracting them from Pascal's triangle.

;See:
*   Catalan Numbers and the Pascal Triangle.      This method enables calculation of Catalan Numbers using only addition and subtraction.

*   Catalan's Triangle for a Number Triangle that generates Catalan Numbers using only addition.
*   Sequence A000108 on OEIS has a lot of information on Catalan Numbers.

;Related Tasks:
[[Pascal's triangle]]

Solution:
var n = 15;
for (var t = [0, 1], i = 1; i <= n; i++) {
    for (var j = i; j > 1; j--) t[j] += t[j - 1];
    t[i + 1] = t[i];
    for (var j = i + 1; j > 1; j--) t[j] += t[j - 1];
    document.write(i == 1 ? '' : ', ', t[i + 1] - t[i]);
}


Catalan numbers/Pascal's triangle

Solution:
(() => {
    'use strict';

    // CATALAN

    // catalanSeries :: Int -> [Int]
    let catalanSeries = n => {
        let alternate = xs => xs.reduce(
                (a, x, i) => i % 2 === 0 ? a.concat([x]) : a, []
            ),
            diff = xs => xs.length > 1 ? xs[0] - xs[1] : xs[0];

        return alternate(pascal(n * 2))
            .map((xs, i) => diff(drop(i, xs)));
    }

    // PASCAL

    // pascal :: Int -> [[Int]]
    let pascal = n => until(
            m => m.level <= 1,
            m => {
                let nxt = zipWith(
                    (a, b) => a + b, [0].concat(m.row), m.row.concat(0)
                );
                return {
                    row: nxt,
                    triangle: m.triangle.concat([nxt]),
                    level: m.level - 1
                }
            }, {
                level: n,
                row: [1],
                triangle: [
                    [1]
                ]
            }
        )
        .triangle;

    // GENERIC FUNCTIONS

    // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    let zipWith = (f, xs, ys) =>
        xs.length === ys.length ? (
            xs.map((x, i) => f(x, ys[i]))
        ) : undefined;

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

    // drop :: Int -> [a] -> [a]
    let drop = (n, xs) => xs.slice(n);

    // tail :: [a] -> [a]
    let tail = xs => xs.length ? xs.slice(1) : undefined;

    return tail(catalanSeries(16));
})();


Catamorphism

''Reduce'' is a function or method that is used to take the values in an array or a list and apply a function to successive members of the list to produce (or reduce them to), a single value.

;Task:
Show how ''reduce'' (or ''foldl'' or ''foldr'' etc), work (or would be implemented) in your language.

;See also:
* Wikipedia article:   Fold
* Wikipedia article:   Catamorphism

Solution:
(function (xs) {
    'use strict';

    // foldl :: (b -> a -> b) -> b -> [a] -> b
    function foldl(f, acc, xs) {
        return xs.reduce(f, acc);
    }

    // foldr :: (b -> a -> b) -> b -> [a] -> b
    function foldr(f, acc, xs) {
        return xs.reduceRight(f, acc);
    }

    // Test folds in both directions
    return [foldl, foldr].map(function (f) {
        return f(function (acc, x) {
            return acc + (x * 2).toString() + ' ';
        }, [], xs);
    });

})([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);


Chaocipher

Description:
The Chaocipher was invented by J.F.Byrne in 1918 and, although simple by modern cryptographic standards, does not appear to have been broken until the algorithm was finally disclosed by his family in 2010.

The algorithm is described in this paper by M.Rubin in 2010 and there is a C# implementation here.

;Task:
Code the algorithm in your language and to test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.

Solution:
const L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";

const ENCRYPT = 0;
const DECRYPT = 1;

function setCharAt(str, index, chr) {
    if (index > str.length - 1) return str;
    return str.substr(0, index) + chr + str.substr(index + 1);
}

function chao(text, mode, show_steps) {
    var left = L_ALPHABET;
    var right = R_ALPHABET;
    var out = text;
    var temp = "01234567890123456789012345";
    var i = 0;
    var index, j, store;

    if (show_steps) {
        console.log("The left and right alphabets after each permutation during encryption are :");
    }
    while (i < text.length) {
        if (show_steps) {
            console.log(left + "  " + right);
        }
        if (mode == ENCRYPT) {
            index = right.indexOf(text[i]);
            out = setCharAt(out, i, left[index]);
        } else {
            index = left.indexOf(text[i]);
            out = setCharAt(out, i, right[index]);
        }
        if (i == text.length - 1) {
            break;
        }

        //permute left
        j = index;
        while (j < 26) {
            temp = setCharAt(temp, j - index, left[j])
            j += 1;
        }
        j = 0;
        while (j < index) {
            temp = setCharAt(temp, 26 - index + j, left[j]);
            j += 1;
        }
        store = temp[1];
        j = 2;
        while (j < 14) {
            temp = setCharAt(temp, j - 1, temp[j]);
            j += 1;
        }
        temp = setCharAt(temp, 13, store);
        left = temp;

        //permute right
        j = index;
        while (j < 26) {
            temp = setCharAt(temp, j - index, right[j]);
            j += 1;
        }
        j = 0;
        while (j < index) {
            temp = setCharAt(temp, 26 - index + j, right[j]);
            j += 1;
        }
        store = temp[0];
        j = 1;
        while (j < 26) {
            temp = setCharAt(temp, j - 1, temp[j]);
            j += 1;
        }
        temp = setCharAt(temp, 25, store);
        store = temp[2];
        j = 3;
        while (j < 14) {
            temp = setCharAt(temp, j - 1, temp[j]);
            j += 1;
        }
        temp = setCharAt(temp, 13, store);
        right = temp;

        i += 1;
    }

    return out;
}

function main() {
    var out = document.getElementById("content");
    const plain_text = "WELLDONEISBETTERTHANWELLSAID";

    out.innerHTML = "
The original plaintext is : " + plain_text + "
";
    var cipher_text = chao(plain_text, ENCRYPT, true);
    out.innerHTML += "
The ciphertext is : " + cipher_text + "
";
    var decipher_text = chao(cipher_text, DECRYPT, false);
    out.innerHTML += "
The recovered plaintext is : " + decipher_text + "
";
}


Chaos game

The Chaos Game is a method of generating the attractor of an iterated function system (IFS).

One of the best-known and simplest examples creates a fractal, using a polygon and an initial point selected at random.

;Task
Play the Chaos Game using the corners of an equilateral triangle as the reference points.   Add a starting point at random (preferably inside the triangle).   Then add the next point halfway between the starting point and one of the reference points.   This reference point is chosen at random.

After a sufficient number of iterations, the image of a Sierpinski Triangle should emerge.

;See also
* The Game of Chaos

Solution:
<meta charset="UTF-8">

<title>Chaos Game</title>

<canvas id="sierpinski" width=400 height=346></canvas>

<button onclick="chaosGame()">Click here to see a Sierpiński triangle</button>


Cheryl's birthday

Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is.

Cheryl gave them a list of ten possible dates:
      May 15,     May 16,     May 19
      June 17,    June 18
      July 14,    July 16
      August 14,  August 15,  August 17

Cheryl then tells Albert the   ''month''   of birth,   and Bernard the   ''day''   (of the month)   of birth.
  1)  Albert:   I don't know when Cheryl's birthday is, but I know that Bernard does not know too.
  2)  Bernard:  At first I don't know when Cheryl's birthday is, but I know now.
  3)  Albert:   Then I also know when Cheryl's birthday is.

;Task
Write a computer program to deduce, by successive elimination, Cheryl's birthday.

;Related task:
* [[Sum and Product Puzzle]]

;References
* Wikipedia article of the same name.
* Tuple Relational Calculus

Solution:
(() => {
    'use strict';

    // main :: IO ()
    const main = () => {
        const
            month = fst,
            day = snd;
        showLog(
            map(x => Array.from(x), (

                // The month with only one remaining day,

                // (A's month contains only one remaining day)
                // (3 :: A "Then I also know")
                uniquePairing(month)(

                    // among the days with unique months,

                    // (B's day is paired with only one remaining month)
                    // (2 :: B "I know now")
                    uniquePairing(day)(

                        // excluding months with unique days,

                        // (A's month is not among those with unique days)
                        // (1 :: A "I know that Bernard does not know")
                        monthsWithUniqueDays(false)(

                            // from the given month-day pairs:

                            // (0 :: Cheryl's list)
                            map(x => tupleFromList(words(strip(x))),
                                splitOn(/,\s+/,
                                    `May 15, May 16, May 19,
                                        June 17, June 18, July 14, July 16,
                                        Aug 14, Aug 15, Aug 17`
                                )
                            )
                        )
                    )
                )
            ))
        );
    };

    // monthsWithUniqueDays :: Bool -> [(Month, Day)] -> [(Month, Day)]
    const monthsWithUniqueDays = blnInclude => xs => {
        const months = map(fst, uniquePairing(snd)(xs));
        return filter(
            md => (blnInclude ? id : not)(
                elem(fst(md), months)
            ),
            xs
        );
    };

    // uniquePairing :: ((a, a) -> a) ->
    //      -> [(Month, Day)] -> [(Month, Day)]
    const uniquePairing = f => xs =>
        bindPairs(xs,
            md => {
                const
                    dct = f(md),
                    matches = filter(
                        k => 1 === length(dct[k]),
                        Object.keys(dct)
                    );
                return filter(tpl => elem(f(tpl), matches), xs);
            }
        );

    // bindPairs :: [(Month, Day)] -> (Dict, Dict) -> [(Month, Day)]
    const bindPairs = (xs, f) => f(
        Tuple(
            dictFromPairs(fst)(snd)(xs),
            dictFromPairs(snd)(fst)(xs)
        )
    );

    // dictFromPairs :: ((a, a) -> a) -> ((a, a) -> a) -> [(a, a)] -> Dict
    const dictFromPairs = f => g => xs =>
        foldl((a, tpl) => Object.assign(
            a, {
                [f(tpl)]: (a[f(tpl)] || []).concat(g(tpl).toString())
            }
        ), {}, xs);

    // GENERIC ABSTRACTIONS -------------------------------

    // Tuple (,) :: a -> b -> (a, b)
    const Tuple = (a, b) => ({
        type: 'Tuple',
        '0': a,
        '1': b,
        length: 2
    });

    // elem :: Eq a => a -> [a] -> Bool
    const elem = (x, xs) => xs.includes(x);

    // filter :: (a -> Bool) -> [a] -> [a]
    const filter = (f, xs) => xs.filter(f);

    // foldl :: (a -> b -> a) -> a -> [b] -> a
    const foldl = (f, a, xs) => xs.reduce(f, a);

    // fst :: (a, b) -> a
    const fst = tpl => tpl[0];

    // id :: a -> a
    const id = x => x;

    // intersect :: (Eq a) => [a] -> [a] -> [a]
    const intersect = (xs, ys) =>
        xs.filter(x => -1 !== ys.indexOf(x));

    // 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

    // length :: [a] -> Int
    const length = xs =>
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) => xs.map(f);

    // not :: Bool -> Bool
    const not = b => !b;

    // showLog :: a -> IO ()
    const showLog = (...args) =>
        console.log(
            args
            .map(JSON.stringify)
            .join(' -> ')
        );

    // snd :: (a, b) -> b
    const snd = tpl => tpl[1];

    // splitOn :: String -> String -> [String]
    const splitOn = (pat, src) =>
        src.split(pat);

    // strip :: String -> String
    const strip = s => s.trim();

    // tupleFromList :: [a] -> (a, a ...)
    const tupleFromList = xs =>
        TupleN.apply(null, xs);

    // TupleN :: a -> b ...  -> (a, b ... )
    function TupleN() {
        const
            args = Array.from(arguments),
            lng = args.length;
        return lng > 1 ? Object.assign(
            args.reduce((a, x, i) => Object.assign(a, {
                [i]: x
            }), {
                type: 'Tuple' + (2 < lng ? lng.toString() : ''),
                length: lng
            })
        ) : args[0];
    };

    // words :: String -> [String]
    const words = s => s.split(/\s+/);

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


Chinese remainder theorem

Suppose   n_1,   n_2,   \ldots,   n_k   are positive [[integer]]s that are pairwise co-prime.

Then, for any given sequence of integers   a_1,   a_2,   \dots,   a_k,   there exists an integer   x   solving the following system of simultaneous congruences:

::: \begin{align}
  x &\equiv a_1 \pmod{n_1} \\
  x &\equiv a_2 \pmod{n_2} \\
    &{}\  \  \vdots \\
  x &\equiv a_k \pmod{n_k}
\end{align}

Furthermore, all solutions   x   of this system are congruent modulo the product,    N=n_1n_2\ldots n_k.

;Task:
Write a program to solve a system of linear congruences by applying the   Chinese Remainder Theorem.

If the system of equations cannot be solved, your program must somehow indicate this.

(It may throw an exception or return a special false value.)

Since there are infinitely many solutions, the program should return the unique solution   s   where   0 \leq s \leq n_1n_2\ldots n_k.

''Show the functionality of this program'' by printing the result such that the   n's   are   [3,5,7]   and the   a's   are   [2,3,2].

'''Algorithm''':   The following algorithm only applies if the   n_i's   are pairwise co-prime.

Suppose, as above, that a solution is required for the system of congruences:

::: x \equiv a_i \pmod{n_i} \quad\mathrm{for}\; i = 1, \ldots, k

Again, to begin, the product   N = n_1n_2 \ldots n_k   is defined.

Then a solution   x   can be found as follows:

For each   i,   the integers   n_i   and   N/n_i   are co-prime.

Using the   Extended Euclidean algorithm,   we can find integers   r_i   and   s_i   such that   r_i n_i + s_i N/n_i = 1.

Then, one solution to the system of simultaneous congruences is:

::: x = \sum_{i=1}^k a_i s_i N/n_i

and the minimal solution,

::: x \pmod{N}.

Solution:
function crt(num, rem) {
  let sum = 0;
  const prod = num.reduce((a, c) => a * c, 1);

  for (let i = 0; i < num.length; i++) {
    const [ni, ri] = [num[i], rem[i]];
    const p = Math.floor(prod / ni);
    sum += ri * p * mulInv(p, ni);
  }
  return sum % prod;
}

function mulInv(a, b) {
  const b0 = b;
  let [x0, x1] = [0, 1];

  if (b === 1) {
    return 1;
  }
  while (a > 1) {
    const q = Math.floor(a / b);
    [a, b] = [b, a % b];
    [x0, x1] = [x1 - q * x0, x0];
  }
  if (x1 < 0) {
    x1 += b0;
  }
  return x1;
}

console.log(crt([3,5,7], [2,3,2]))


Chinese zodiac

Determine the Chinese zodiac sign and related associations for a given year.
Traditionally, the Chinese have counted years using two lists of labels, one of length 10 (the "celestial stems") and one of length 12 (the "terrestrial branches"). The labels do not really have any meaning outside their positions in the two lists; they're simply a traditional enumeration device, used much as Westerners use letters and numbers. They were historically used for months and days as well as years, and the stems are still sometimes used for school grades.

Years cycle through both lists concurrently, so that both stem and branch advance each year; if we used Roman letters for the stems and numbers for the branches, consecutive years would be labeled A1, B2, C3, etc. Since the two lists are different lengths, they cycle back to their beginning at different points: after J10 we get A11, and then after B12 we get C1. The result is a repeating 60-year pattern within which each pair of names occurs only once.

Mapping the branches to twelve traditional animal deities results in the well-known "Chinese zodiac", assigning each year to a given animal. For example, Sunday, January 22, 2023 CE (in the common Gregorian calendar) began the lunisolar Year of the Rabbit.

The celestial stems do not have a one-to-one mapping like that of the branches to animals; however, the five pairs of consecutive stems are each associated with one of the five traditional Chinese elements (Wood, Fire, Earth, Metal, and Water). Further, one of the two years within each element is assigned to yin, the other to yang.

Thus, the Chinese year beginning in 2023 CE is also the yin year of Water. Since 12 is an even number, the association between animals and yin/yang doesn't change; consecutive Years of the Rabbit will cycle through the five elements, but will always be yin.

;Task: Create a subroutine or program that will return or output the animal, yin/yang association, and element for the lunisolar year that begins in a given CE year.

You may optionally provide more information in the form of the year's numerical position within the 60-year cycle and/or its actual Chinese stem-branch name (in Han characters or Pinyin transliteration).

;Requisite information:
* The animal cycle runs in this order: Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Goat, Monkey, Rooster, Dog, Pig.
* The element cycle runs in this order: Wood, Fire, Earth, Metal, Water.
* Each element gets two consecutive years; a yang followed by a yin.
* The current 60-year cycle began in 1984; any multiple of 60 years from that point may be used to reckon from.

Thus, year 1 of a cycle is the year of the Wood Rat (yang), year 2 the Wood Ox (yin), and year 3 the Fire Tiger (yang). The year 2023 - which, as already noted, is the year of the Water Rabbit (yin) - is the 40th year of the current cycle.

;Information for optional task:
* The ten celestial stems are '''Jia ''' ''jia'', '''Yi ''' ''yi'', '''Bing ''' ''bing'', '''Ding ''' ''ding'', '''Wu ''' ''wu'', '''Ji ''' ''ji'', '''Geng ''' ''geng'', '''Xin ''' ''xin'', '''Ren ''' ''ren'', and '''Gui ''' ''gui''. With the ASCII version of Pinyin tones, the names are written "jia3", "yi3", "bing3", "ding1", "wu4", "ji3", "geng1", "xin1", "ren2", and "gui3".
* The twelve terrestrial branches are '''Zi ''' ''zi'', '''Chou ''' ''chou'', '''Yin ''' ''yin'', '''Mao ''' ''mao'', '''Chen ''' ''chen'', '''Si ''' ''si'', '''Wu ''' ''wu'', '''Wei ''' ''wei'', '''Shen ''' ''shen'', '''You ''' ''you'', '''Xu ''' ''xu'', '''Hai ''' ''hai''. In ASCII Pinyin, those are "zi3", "chou3", "yin2", "mao3", "chen2", "si4", "wu3", "wei4", "shen1", "you3", "xu1", and "hai4".

Therefore 1984 was '''Jia Zi ''' (''jia-zi'', or jia3-zi3).  2023 is '''Gui Mao ''' (''gui-mao'' or gui3-mao3).

Solution:
(() => {
    "use strict";

    // ---------- TRADITIONAL CALENDAR STRINGS -----------

    // ats :: Array Int (String, String)
    const ats = () =>
        // 天干 tiangan – 10 heavenly stems
        zip(
            chars("甲乙丙丁戊己庚辛壬癸")
        )(
            words("jiă yĭ bĭng dīng wù jĭ gēng xīn rén gŭi")
        );

    // ads :: Array Int (String, String)
    const ads = () =>
        // 地支 dizhi – 12 terrestrial branches
        zip(
            chars("子丑寅卯辰巳午未申酉戌亥")
        )(
            words(
                "zĭ chŏu yín măo chén sì " + (
                    "wŭ wèi shēn yŏu xū hài"
                )
            )
        );

    // aws :: Array Int (String, String, String)
    const aws = () =>
        // 五行 wuxing – 5 elements
        zip3(
            chars("木火土金水")
        )(
            words("mù huǒ tǔ jīn shuǐ")
        )(
            words("wood fire earth metal water")
        );

    // axs :: Array Int (String, String, String)
    const axs = () =>
        // 十二生肖 shengxiao – 12 symbolic animals
        zip3(
            chars("鼠牛虎兔龍蛇馬羊猴鸡狗豬")
        )(
            words(
                "shǔ niú hǔ tù lóng shé " + (
                    "mǎ yáng hóu jī gǒu zhū"
                )
            )
        )(
            words(
                "rat ox tiger rabbit dragon snake " + (
                    "horse goat monkey rooster dog pig"
                )
            )
        );

    // ays :: Array Int (String, String)
    const ays = () =>
        // 阴阳 yinyang
        zip(
            chars("阳阴")
        )(
            words("yáng yīn")
        );

    // --------------- TRADITIONAL CYCLES ----------------
    const zodiac = y => {
        const
            iYear = y - 4,
            iStem = iYear % 10,
            iBranch = iYear % 12,
            [hStem, pStem] = ats()[iStem],
            [hBranch, pBranch] = ads()[iBranch],
            [hElem, pElem, eElem] = aws()[quot(iStem)(2)],
            [hAnimal, pAnimal, eAnimal] = axs()[iBranch],
            [hYinyang, pYinyang] = ays()[iYear % 2];

        return [
            [
                show(y), hStem + hBranch, hElem,
                hAnimal, hYinyang
            ],
            ["", pStem + pBranch, pElem, pAnimal, pYinyang],
            [
                "", `${show((iYear % 60) + 1)}/60`,
                eElem, eAnimal, ""
            ]
        ];
    };

    // ---------------------- TEST -----------------------
    const main = () => [
            1935, 1938, 1968, 1972, 1976, 1984,
            new Date().getFullYear()
        ]
        .map(showYear)
        .join("\n\n");

    // ------------------- FORMATTING --------------------
    // fieldWidths :: [[Int]]
    const fieldWidths = [
        [6, 10, 7, 8, 3],
        [6, 11, 8, 8, 4],
        [6, 11, 8, 8, 4]
    ];

    // showYear :: Int -> String
    const showYear = y =>
        zipWith(zip)(fieldWidths)(zodiac(y))
        .map(
            row => row.map(
                ([n, s]) => s.padEnd(n, " ")
            )
            .join("")
        )
        .join("\n");

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

    // chars :: String -> [Char]
    const chars = s => [...s];

    // quot :: Integral a => a -> a -> a
    const quot = n =>
        m => Math.trunc(n / m);

    // show :: Int -> a -> Indented String
    // show :: a -> String
    const show = (...x) =>
        JSON.stringify.apply(
            null, x.length > 1 ? [
                x[1], null, x[0]
            ] : x
        );

    // words :: String -> [String]
    const words = s =>
        // List of space-delimited sub-strings.
        s.split(/\s+/u);

    // zip :: [a] -> [b] -> [(a, b)]
    const zip = xs =>
        // The paired members of xs and ys, up to
        // the length of the shorter of the two lists.
        ys => Array.from({
            length: Math.min(xs.length, ys.length)
        }, (_, i) => [xs[i], ys[i]]);

    // zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
    const zip3 = xs =>
        ys => zs => xs.slice(
            0,
            Math.min(...[xs, ys, zs].map(x => x.length))
        )
        .map((x, i) => [x, ys[i], zs[i]]);

    // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    const zipWith = f =>
        // A list constructed by zipping with a
        // custom function, rather than with the
        // default tuple constructor.
        xs => ys => xs.map(
            (x, i) => f(x)(ys[i])
        ).slice(
            0, Math.min(xs.length, ys.length)
        );

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


Church numerals

In the Church encoding of natural numbers, the number N is encoded by a function that applies its first argument N times to its second argument.

* '''Church zero''' always returns the identity function, regardless of its first argument. In other words, the first argument is not applied to the second argument at all.
* '''Church one''' applies its first argument f just once to its second argument x, yielding '''f(x)'''
* '''Church two''' applies its first argument f twice to its second argument x, yielding '''f(f(x))'''
* and each successive Church numeral applies its first argument one additional time to its second argument, '''f(f(f(x)))''', '''f(f(f(f(x))))''' ...  The Church numeral 4, for example, returns a quadruple composition of the function supplied as its first argument.

Arithmetic operations on natural numbers can be similarly represented as functions on Church numerals.

In your language define:

* Church Zero,
* a Church successor function (a function on a Church numeral which returns the next Church numeral in the series),
* functions for Addition, Multiplication and Exponentiation over Church numerals,
* a function to convert integers to corresponding Church numerals,
* and a function to convert Church numerals to corresponding integers.

You should:

* Derive Church numerals three and four in terms of Church zero and a Church successor function.
* use Church numeral arithmetic to obtain the the sum and the product of Church 3 and Church 4,
* similarly obtain 4^3 and 3^4 in terms of Church numerals, using a Church numeral exponentiation function,
* convert each result back to an integer, and return it or print it to the console.

Solution:
(() => {
    'use strict';

    // ----------------- CHURCH NUMERALS -----------------

    const churchZero = f =>
        identity;

    const churchSucc = n =>
        f => compose(f)(n(f));

    const churchAdd = m =>
        n => f => compose(n(f))(m(f));

    const churchMult = m =>
        n => f => n(m(f));

    const churchExp = m =>
        n => n(m);

    const intFromChurch = n =>
        n(succ)(0);

    const churchFromInt = n =>
        compose(
            foldl(compose)(identity)
        )(
            replicate(n)
        );

    // Or, by explicit recursion:
    const churchFromInt_ = x => {
        const go = i =>
            0 === i ? (
                churchZero
            ) : churchSucc(go(pred(i)));
        return go(x);
    };

    // ---------------------- TEST -----------------------
    // main :: IO ()
    const main = () => {
        const [cThree, cFour] = map(churchFromInt)([3, 4]);

        return map(intFromChurch)([
            churchAdd(cThree)(cFour),
            churchMult(cThree)(cFour),
            churchExp(cFour)(cThree),
            churchExp(cThree)(cFour),
        ]);
    };

    // --------------------- GENERIC ---------------------

    // compose (>>>) :: (a -> b) -> (b -> c) -> a -> c
    const compose = f =>
        g => x => f(g(x));

    // foldl :: (a -> b -> a) -> a -> [b] -> a
    const foldl = f =>
        a => xs => [...xs].reduce(
            (x, y) => f(x)(y),
            a
        );

    // identity :: a -> a
    const identity = x => x;

    // 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 => [...xs].map(f);

    // pred :: Enum a => a -> a
    const pred = x =>
        x - 1;

    // replicate :: Int -> a -> [a]
    const replicate = n =>
        // n instances of x.
        x => Array.from({
            length: n
        }, () => x);

    // succ :: Enum a => a -> a
    const succ = x =>
        1 + x;

    // MAIN ---
    console.log(JSON.stringify(main()));
})();


Circles of given radius through two points

2 circles with a given radius through 2 points in 2D space.

Given two points on a plane and a radius, usually two circles of given radius can be drawn through the points.
;Exceptions:
# r==0.0 should be treated as never describing circles (except in the case where the points are coincident).
# If the points are coincident then an infinite number of circles with the point on their circumference can be drawn, unless r==0.0 as well which then collapses the circles to a point.
# If the points form a diameter then return two identical circles ''or'' return a single circle, according to which is the most natural mechanism for the implementation language.
# If the points are too far apart then no circles can be drawn.

;Task detail:
* Write a function/subroutine/method/... that takes two points and a radius and returns the two circles through those points, ''or some indication of special cases where two, possibly equal, circles cannot be returned''.
* Show here the output for the following inputs:

      p1                p2           r
0.1234, 0.9876    0.8765, 0.2345    2.0
0.0000, 2.0000    0.0000, 0.0000    1.0
0.1234, 0.9876    0.1234, 0.9876    2.0
0.1234, 0.9876    0.8765, 0.2345    0.5
0.1234, 0.9876    0.1234, 0.9876    0.0

;Related task:
*   [[Total circles area]].

;See also:
*   Finding the Center of a Circle from 2 Points and Radius from Math forum @ Drexel

Solution:
const hDist = (p1, p2) => Math.hypot(...p1.map((e, i) => e - p2[i])) / 2;
const pAng = (p1, p2) => Math.atan(p1.map((e, i) => e - p2[i]).reduce((p, c) => c / p, 1));
const solveF = (p, r) => t => [r*Math.cos(t) + p[0], r*Math.sin(t) + p[1]];
const diamPoints = (p1, p2) => p1.map((e, i) => e + (p2[i] - e) / 2);

const findC = (...args) => {
  const [p1, p2, s] = args;
  const solve = solveF(p1, s);
  const halfDist = hDist(p1, p2);

  let msg = `p1: ${p1}, p2: ${p2}, r:${s} Result: `;
  switch (Math.sign(s - halfDist)) {
    case 0:
      msg += s ? `Points on diameter. Circle at: ${diamPoints(p1, p2)}` :
        'Radius Zero';
      break;
    case 1:
      if (!halfDist) {
        msg += 'Coincident point. Infinite solutions';
      }
      else {
        let theta = pAng(p1, p2);
        let theta2 = Math.acos(halfDist / s);
        [1, -1].map(e => solve(theta + e * theta2)).forEach(
          e => msg += `Circle at ${e} `);
      }
      break;
    case -1:
      msg += 'No intersection. Points further apart than circle diameter';
      break;
  }
  return msg;
};

[
  [[0.1234, 0.9876], [0.8765, 0.2345], 2.0],
  [[0.0000, 2.0000], [0.0000, 0.0000], 1.0],
  [[0.1234, 0.9876], [0.1234, 0.9876], 2.0],
  [[0.1234, 0.9876], [0.8765, 0.2345], 0.5],
  [[0.1234, 0.9876], [0.1234, 0.9876], 0.0]
].forEach((t,i) => console.log(`Test: ${i}: ${findC(...t)}`));


Cistercian numerals

Cistercian numerals were used across Europe by Cistercian monks during the Late Medieval Period as an alternative to Roman numerals. They were used to represent base 10 integers from '''0''' to '''9999'''.

;How they work
All Cistercian numerals begin with a vertical line segment, which by itself represents the number '''0'''. Then, glyphs representing the digits '''1''' through '''9''' are optionally added to the four quadrants surrounding the vertical line segment. These glyphs are drawn with vertical and horizontal symmetry about the initial line segment. Each quadrant corresponds to a digit place in the number:

:* The '''upper-right''' quadrant represents the '''ones''' place.
:* The '''upper-left''' quadrant represents the '''tens''' place.
:* The '''lower-right''' quadrant represents the '''hundreds''' place.
:* The '''lower-left''' quadrant represents the '''thousands''' place.

Please consult the following image for examples of Cistercian numerals showing each glyph: [https://upload.wikimedia.org/wikipedia/commons/6/67/Cistercian_digits_%28vertical%29.svg]

;Task

:* Write a function/procedure/routine to display any given Cistercian numeral. This could be done by drawing to the display, creating an image, or even as text (as long as it is a reasonable facsimile).

:* Use the routine to show the following Cistercian numerals:

::* 0
::* 1
::* 20
::* 300
::* 4000
::* 5555
::* 6789
::* And a number of your choice!

;Notes
Due to the inability to upload images to Rosetta Code as of this task's creation, showing output here on this page is not required. However, it is welcomed -- especially for text output.

;See also

:* '''Numberphile - The Forgotten Number System'''
:* '''dcode.fr - Online Cistercian numeral converter'''

Solution:
// html
document.write(`

<input id="num" type="number" min="0" max="9999" value="0" onchange="showCist()">

<canvas id="cist" width="200" height="300"></canvas>

    <button onclick="set(0)">0</button>
    <button onclick="set(1)">1</button>
    <button onclick="set(20)">20</button>
    <button onclick="set(300)">300</button>
    <button onclick="set(4000)">4000</button>
    <button onclick="set(5555)">5555</button>
    <button onclick="set(6789)">6789</button>
    <button onclick="set(Math.floor(Math.random()*1e4))">Random</button>

`);

// to show given examples
// can be deleted for normal use
function set(num) {
  document.getElementById('num').value = num;
  showCist();
}

const SW = 10; // stroke width
let canvas = document.getElementById('cist'),
    cx = canvas.getContext('2d');

function showCist() {
  // reset canvas
  cx.clearRect(0, 0, canvas.width, canvas.height);
  cx.lineWidth = SW;
  cx.beginPath();
  cx.moveTo(100, 0+.5*SW);
  cx.lineTo(100, 300-.5*SW);
  cx.stroke();

  let num = document.getElementById('num').value;
  while (num.length < 4) num = '0' + num;  // fills leading zeros to $num

  /***********************\
  |        POINTS:        |
  | ********************* |
  |                       |
  |     a --- b --- c     |
  |     |     |     |     |
  |     d --- e --- f     |
  |     |     |     |     |
  |     g --- h --- i     |
  |     |     |     |     |
  |     j --- k --- l     |
  |                       |
  \***********************/
  let
  a = [0+SW,   0+SW],   b = [100,   0+SW],   c = [200-SW,   0+SW],
  d = [0+SW,    100],   e = [100,    100],   f = [200-SW,    100],
  g = [0+SW,    200],   h = [100,    200],   i = [200-SW,    200],
  j = [0+SW, 300-SW],   k = [100, 300-SW],   l = [200-SW, 300-SW];

  function draw() {
    let x = 1;
    cx.beginPath();
    cx.moveTo(arguments[0][0], arguments[0][1]);
    while (x < arguments.length) {
      cx.lineTo(arguments[x][0], arguments[x][1]);
      x++;
    }
    cx.stroke();
  }

  // 1000s
  switch (num[0]) {
    case '1': draw(j, k);       break;       case '2': draw(g, h);    break;
    case '3': draw(g, k);       break;       case '4': draw(j, h);    break;
    case '5': draw(k, j, h);    break;       case '6': draw(g, j);    break;
    case '7': draw(g, j, k);    break;       case '8': draw(j, g, h); break;
    case '9': draw(h, g, j, k); break;
  }
  // 100s
  switch (num[1]) {
    case '1': draw(k, l);       break;       case '2': draw(h, i);    break;
    case '3': draw(k, i);       break;       case '4': draw(h, l);    break;
    case '5': draw(h, l, k);    break;       case '6': draw(i, l);    break;
    case '7': draw(k, l, i);    break;       case '8': draw(h, i, l); break;
    case '9': draw(h, i, l, k); break;
  }
  // 10s
  switch (num[2]) {
    case '1': draw(a, b);       break;       case '2': draw(d, e);    break;
    case '3': draw(d, b);       break;       case '4': draw(a, e);    break;
    case '5': draw(b, a, e);    break;       case '6': draw(a, d);    break;
    case '7': draw(d, a, b);    break;       case '8': draw(a, d, e); break;
    case '9': draw(b, a, d, e); break;
  }
  // 1s
  switch (num[3]) {
    case '1': draw(b, c);       break;       case '2': draw(e, f);    break;
    case '3': draw(b, f);       break;       case '4': draw(e, c);    break;
    case '5': draw(b, c, e);    break;       case '6': draw(c, f);    break;
    case '7': draw(b, c, f);    break;       case '8': draw(e, f, c); break;
    case '9': draw(b, c, f, e); break;
  }
}


Closures/Value capture

Create a list of ten functions, in the simplest manner possible   (anonymous functions are encouraged),   such that the function at index   '' i ''    (you may choose to start    '' i ''    from either    '''0'''    or    '''1'''),     when run, should return the square of the index,   that is,    '' i '' 2.

Display the result of running any but the last function, to demonstrate that the function indeed remembers its value.

;Goal:
Demonstrate how to create a series of independent closures based on the same template but maintain separate copies of the variable closed over.

In imperative languages, one would generally use a loop with a mutable counter variable.

For each function to maintain the correct number, it has to capture the ''value'' of the variable at the time it was created, rather than just a reference to the variable, which would have a different value by the time the function was run.

See also: [[Multiple distinct objects]]

Solution:
var funcs = [];
for (var i = 0; i < 10; i++) {
    funcs.push( (function(i) {
                     return function() { return i * i; }
                })(i) );
}
window.alert(funcs[3]()); // alerts "9"


Closures/Value capture

Solution:
<script type="application/javascript;version=1.7">
var funcs = [];
for (var i = 0; i < 10; i++) {
    let (i = i) {
        funcs.push( function() { return i * i; } );
    }
}
window.alert(funcs[3]()); // alerts "9"
</script>


Closures/Value capture

Solution:
(function () {
    'use strict';

    // Int -> Int -> [Int]
    function range(m, n) {
        return Array.apply(null, Array(n - m + 1))
            .map(function (x, i) {
                return m + i;
            });
    }

    var lstFns = range(0, 10)
        .map(function (i) {
            return function () {
                return i * i;
            };
        })

    return lstFns[3]();

})();


Comma quibbling

Comma quibbling is a task originally set by Eric Lippert in his blog.

;Task:

Write a function to generate a string output which is the concatenation of input words from a list/sequence where:
# An input of no words produces the output string of just the two brace characters "{}".
# An input of just one word, e.g. ["ABC"], produces the output string of the word inside the two braces, e.g. "{ABC}".
# An input of two words, e.g. ["ABC", "DEF"], produces the output string of the two words inside the two braces with the words separated by the string " and ", e.g. "{ABC and DEF}".
# An input of three or more words, e.g. ["ABC", "DEF", "G", "H"], produces the output string of all but the last word separated by ", " with the last word separated by " and " and all within braces; e.g. "{ABC, DEF, G and H}".

Test your function with the following series of inputs showing your output here on this page:
* []                       # (No input words).
* ["ABC"]
* ["ABC", "DEF"]
* ["ABC", "DEF", "G", "H"]

Note: Assume words are non-empty strings of uppercase characters for this task.

Solution:
function quibble(words) {
  return "{" +
    words.slice(0, words.length-1).join(",") +
   (words.length > 1 ? " and " : "") +
   (words[words.length-1] || '') +
  "}";
}

[[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]].forEach(
  function(s) {
    console.log(quibble(s));
  }
);