var fizzBuzz = function () {
  var i, output;
  for (i = 1; i < 101; i += 1) {
    output = '';
    if (!(i % 3)) { output += 'Fizz'; }
    if (!(i % 5)) { output += 'Buzz'; }
    console.log(output || i);//empty string is false, so we short-circuit
  }
};

for (var i = 1; i <= 100; i++) {
  console.log({
    truefalse: 'Fizz',
    falsetrue: 'Buzz',
    truetrue: 'FizzBuzz'
  }[(i%3==0) + '' + (i%5==0)] || i)
}

for(i=1;i<101;i++)console.log((x=(i%3?'':'Fizz')+(i%5?'':'Buzz'))?x:i);

for(i=1;i<101;i++)console.log((i%3?'':'Fizz')+(i%5?'':'Buzz')||i)

(function rng(i) {
    return i ? rng(i - 1).concat(i) : []
})(100).map(
    function (n) {
        return n % 3 ? (
            n % 5 ? n : "Buzz"
        ) : (
            n % 5 ? "Fizz" : "FizzBuzz"
        )
    }
).join(' ')
(() => {

    // FIZZBUZZ --------------------------------------------------------------

    // fizzBuzz :: Int -> String
    const fizzBuzz = n =>
        caseOf(n, [
            [x => x % 15 === 0, "FizzBuzz"],
            [x => x % 3 === 0, "Fizz"],
            [x => x % 5 === 0, "Buzz"]
        ], n.toString());

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

    // caseOf :: a -> [(a -> Bool, b)] -> b -> b
    const caseOf = (e, pvs, otherwise) =>
        pvs.reduce((a, [p, v]) =>
            a !== otherwise ? a : (p(e) ? v : a), otherwise);

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

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

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // TEST ------------------------------------------------------------------
    return unlines(
        map(fizzBuzz, enumFromTo(1, 100))
    );
})();

const factors = [[3, 'Fizz'], [5, 'Buzz']]
const fizzBuzz = num => factors.map(([factor,text]) => (num % factor)?'':text).join('') || num
const range1 = x => [...Array(x+1).keys()].slice(1)
const outputs = range1(100).map(fizzBuzz)

console.log(outputs.join('\n'))
(() => {
    'use strict';

    // main :: IO ()
    const main = () => {

        // FIZZBUZZ ---------------------------------------

        // fizzBuzz :: Generator [String]
        const fizzBuzz = () => {
            const fb = n => k => cycle(
                replicate(n - 1)('').concat(k)
            );
            return zipWith(
                liftA2(flip)(bool)(isNull)
            )(
                zipWith(append)(fb(3)('fizz'))(fb(5)('buzz'))
            )(fmap(str)(enumFrom(1)));
        };

        // TEST -------------------------------------------
        console.log(
            unlines(
                take(100)(
                    fizzBuzz()
                )
            )
        );
    };

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

    // Just :: a -> Maybe a
    const Just = x => ({
        type: 'Maybe',
        Nothing: false,
        Just: x
    });

    // Nothing :: Maybe a
    const Nothing = () => ({
        type: 'Maybe',
        Nothing: true,
    });

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

    // append (++) :: [a] -> [a] -> [a]
    // append (++) :: String -> String -> String
    const append = xs => ys => xs.concat(ys);

    // bool :: a -> a -> Bool -> a
    const bool = f => t => p =>
        p ? t : f;

    // cycle :: [a] -> Generator [a]
    function* cycle(xs) {
        const lng = xs.length;
        let i = 0;
        while (true) {
            yield(xs[i])
            i = (1 + i) % lng;
        }
    }

    // enumFrom :: Int => Int -> [Int]
    function* enumFrom(x) {
        let v = x;
        while (true) {
            yield v;
            v = 1 + v;
        }
    }

    // flip :: (a -> b -> c) -> b -> a -> c
    const flip = f =>
        x => y => f(y)(x);

    // fmap <$> :: (a -> b) -> Gen [a] -> Gen [b]
    const fmap = f =>
        function*(gen) {
            let v = take(1)(gen);
            while (0 < v.length) {
                yield(f(v[0]))
                v = take(1)(gen)
            }
        };

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

    // isNull :: [a] -> Bool
    // isNull :: String -> Bool
    const isNull = xs =>
        1 > xs.length;

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

    // liftA2 :: (a0 -> b -> c) -> (a -> a0) -> (a -> b) -> a -> c
    const liftA2 = op => f => g =>
        // Lift a binary function to a composition
        // over two other functions.
        // liftA2 (*) (+ 2) (+ 3) 7 == 90
        x => op(f(x))(g(x));

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

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

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

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n => xs =>
        'GeneratorFunction' !== xs.constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // The first argument is a sample of the type
    // allowing the function to make the right mapping

    // uncons :: [a] -> Maybe (a, [a])
    const uncons = xs => {
        const lng = length(xs);
        return (0 < lng) ? (
            lng < Infinity ? (
                Just(Tuple(xs[0])(xs.slice(1))) // Finite list
            ) : (() => {
                const nxt = take(1)(xs);
                return 0 < nxt.length ? (
                    Just(Tuple(nxt[0])(xs))
                ) : Nothing();
            })() // Lazy generator
        ) : Nothing();
    };

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // zipWith :: (a -> b -> c) Gen [a] -> Gen [b] -> Gen [c]
    const zipWith = f => ga => gb => {
        function* go(ma, mb) {
            let
                a = ma,
                b = mb;
            while (!a.Nothing && !b.Nothing) {
                let
                    ta = a.Just,
                    tb = b.Just
                yield(f(fst(ta))(fst(tb)));
                a = uncons(snd(ta));
                b = uncons(snd(tb));
            }
        }
        return go(uncons(ga), uncons(gb));
    };

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

print numbers from 1 to 100, replacing multiples of three with 'Fizz', multiples of five with 'Buzz', and multiples of both three and five with 'FizzBuzz'.


Works with: Firefox version 3.5.11

function mandelIter(cx, cy, maxIter) {
  var x = 0.0;
  var y = 0.0;
  var xx = 0;
  var yy = 0;
  var xy = 0;

  var i = maxIter;
  while (i-- && xx + yy <= 4) {
    xy = x * y;
    xx = x * x;
    yy = y * y;
    x = xx - yy + cx;
    y = xy + xy + cy;
  }
  return maxIter - i;
}

function mandelbrot(canvas, xmin, xmax, ymin, ymax, iterations) {
  var width = canvas.width;
  var height = canvas.height;

  var ctx = canvas.getContext('2d');
  var img = ctx.getImageData(0, 0, width, height);
  var pix = img.data;

  for (var ix = 0; ix < width; ++ix) {
    for (var iy = 0; iy < height; ++iy) {
      var x = xmin + (xmax - xmin) * ix / (width - 1);
      var y = ymin + (ymax - ymin) * iy / (height - 1);
      var i = mandelIter(x, y, iterations);
      var ppos = 4 * (width * iy + ix);

      if (i > iterations) {
        pix[ppos] = 0;
        pix[ppos + 1] = 0;
        pix[ppos + 2] = 0;
      } else {
        var c = 3 * Math.log(i) / Math.log(iterations - 1.0);

        if (c < 1) {
          pix[ppos] = 255 * c;
          pix[ppos + 1] = 0;
          pix[ppos + 2] = 0;
        }
        else if ( c < 2 ) {
          pix[ppos] = 255;
          pix[ppos + 1] = 255 * (c - 1);
          pix[ppos + 2] = 0;
        } else {
          pix[ppos] = 255;
          pix[ppos + 1] = 255;
          pix[ppos + 2] = 255 * (c - 2);
        }
      }
      pix[ppos + 3] = 255;
    }
  }

  ctx.putImageData(img, 0, 0);
}

var canvas = document.createElement('canvas');
canvas.width = 900;
canvas.height = 600;

document.body.insertBefore(canvas, document.body.childNodes[0]);

mandelbrot(canvas, -2, 1, -1, 1, 1000);

generate and draw the Mandelbrot set using various algorithms and functions. The code is compatible with modern browsers supporting HTML 5 canvas tag and can be executed directly from the Javascript console. It also utilizes ES6 and WebAssembly for improved performance, requiring a compiled WASM file.


var array = [1, 2, 3, 4, 5],
    sum = 0,
    prod = 1,
    i;
for (i = 0; i < array.length; i += 1) {
    sum += array[i];
    prod *= array[i];
}
alert(sum + ' ' + prod);

Works with: Javascript version 1.8

var array = [1, 2, 3, 4, 5],
    sum = array.reduce(function (a, b) {
        return a + b;
    }, 0),
    prod = array.reduce(function (a, b) {
        return a * b;
    }, 1);
alert(sum + ' ' + prod);

(() => {
    'use strict';

    // sum :: (Num a) => [a] -> a
    const sum = xs => xs.reduce((a, x) => a + x, 0);

    // product :: (Num a) => [a] -> a
    const product = xs => xs.reduce((a, x) => a * x, 1);

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

    return show(
        [sum, product]
        .map(f => f([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
    );
})();

Calculates the sum and product of all integers in an array.


var isLeapYear = function (year) { return (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0); };

// Month values start at 0, so 1 is for February
var isLeapYear = function (year) { return new Date(year, 1, 29).getDate() === 29; };

determine if a given year is a leap year in the Gregorian calendar by setting the day to the 29th and checking if the day remains.


(function () {
    'use strict';

    // concatMap :: (a -> [b]) -> [a] -> [b]
    function concatMap(f, xs) {
        return [].concat.apply([], xs.map(f));
    };

    return '(Police, Sanitation, Fire)\n' +
        concatMap(function (x) {
            return concatMap(function (y) {
                return concatMap(function (z) {
                    return z !== y && 1 <= z && z <= 7 ? [
                        [x, y, z]
                    ] : [];
                }, [12 - (x + y)]);
            }, [1, 2, 3, 4, 5, 6, 7]);
        }, [2, 4, 6])
        .map(JSON.stringify)
        .join('\n');
})();

generate all possible unique combinations of numbers between 1 and 7 for three departments - police, sanitation, and fire, such that the sum of the numbers is 12 and the number for the police department is even.


var container = {myString: "Hello"};
var containerCopy = container; // Now both identifiers refer to the same object

containerCopy.myString = "Goodbye"; // container.myString will also return "Goodbye"

var a = "Hello";
var b = a; // Same as saying window.b = window.a

b = "Goodbye" // b contains a copy of a's value and a will still return "Hello"

demonstrate how to copy a string in JavaScript, distinguishing between copying the string's content and creating an additional reference to the existing string. It also illustrates that changes to one string will reflect in the other when copied via reassignment, and only the value, not the reference, will be copied when copying properties of global objects like window in browsers.


function f(num) {
 return (num === 0) ? 1 : num - m(f(num - 1));
}

function m(num) {
 return (num === 0) ? 0 : num - f(m(num - 1));
}

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

var a = range(0, 19);

//return a new array of the results and join with commas to print
console.log(a.map(function (n) { return f(n); }).join(', '));
console.log(a.map(function (n) { return m(n); }).join(', '));

implement two mutually recursive functions to compute the Hofstadter Female and Male sequences. The functions follow the defined rules: F(0) = 1, M(0) = 0, F(n) = n - M(F(n - 1)) for n > 0, and M(n) = n - F(M(n - 1)) for n > 0. If the programming language does not support mutual recursion, it is stated instead of providing a different solution.


var array = [1,2,3];
return array[Math.floor(Math.random() * array.length)];

demonstrate how to select a random element from a list.


provide a function to convert URL-encoded strings back into their original unencoded form. It includes test cases for strings like "http%3A%2F%2Ffoo%20bar%2F", "google.com/search?q=%60Abdu%27l-Bah%C3%A1", and "%25%32%35".


function binary_search_recursive(a, value, lo, hi) {
  if (hi < lo) { return null; }

  var mid = Math.floor((lo + hi) / 2);

  if (a[mid] > value) {
    return binary_search_recursive(a, value, lo, mid - 1);
  }
  if (a[mid] < value) {
    return binary_search_recursive(a, value, mid + 1, hi);
  }
  return mid;
}

function binary_search_iterative(a, value) {
  var mid, lo = 0,
      hi = a.length - 1;

  while (lo <= hi) {
    mid = Math.floor((lo + hi) / 2);

    if (a[mid] > value) {
      hi = mid - 1;
    } else if (a[mid] < value) {
      lo = mid + 1;
    } else {
      return mid;
    }
  }
  return null;
}

(() => {
    'use strict';

    const main = () => {

        // findRecursive :: a -> [a] -> Either String Int
        const findRecursive = (x, xs) => {
            const go = (lo, hi) => {
                if (hi < lo) {
                    return Left('not found');
                } else {
                    const
                        mid = div(lo + hi, 2),
                        v = xs[mid];
                    return v > x ? (
                        go(lo, mid - 1)
                    ) : v < x ? (
                        go(mid + 1, hi)
                    ) : Right(mid);
                }
            };
            return go(0, xs.length);
        };

        // findRecursive :: a -> [a] -> Either String Int
        const findIter = (x, xs) => {
            const [m, l, h] = until(
                ([mid, lo, hi]) => lo > hi || lo === mid,
                ([mid, lo, hi]) => {
                    const
                        m = div(lo + hi, 2),
                        v = xs[m];
                    return v > x ? [
                        m, lo, m - 1
                    ] : v < x ? [
                        m, m + 1, hi
                    ] : [m, m, hi];
                },
                [div(xs.length / 2), 0, xs.length - 1]
            );
            return l > h ? (
                Left('not found')
            ) : Right(m);
        };

        // TESTS ------------------------------------------

        const
            // (pre-sorted AZ)
            xs = ["alpha", "beta", "delta", "epsilon", "eta", "gamma",
                "iota", "kappa", "lambda", "mu", "nu", "theta", "zeta"
            ];
        return JSON.stringify([
            'Recursive',
            map(x => either(
                    l => "'" + x + "' " + l,
                    r => "'" + x + "' found at index " + r,
                    findRecursive(x, xs)
                ),
                knuthShuffle(['cape'].concat(xs).concat('cairo'))
            ),
            '',
            'Iterative:',
            map(x => either(
                    l => "'" + x + "' " + l,
                    r => "'" + x + "' found at index " + r,
                    findIter(x, xs)
                ),
                knuthShuffle(['cape'].concat(xs).concat('cairo'))
            )
        ], null, 2);
    };

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

    // Left :: a -> Either a b
    const Left = x => ({
        type: 'Either',
        Left: x
    });

    // Right :: b -> Either a b
    const Right = x => ({
        type: 'Either',
        Right: x
    });

    // div :: Int -> Int -> Int
    const div = (x, y) => Math.floor(x / y);

    // either :: (a -> c) -> (b -> c) -> Either a b -> c
    const either = (fl, fr, e) =>
        'Either' === e.type ? (
            undefined !== e.Left ? (
                fl(e.Left)
            ) : fr(e.Right)
        ) : undefined;

    // Abbreviation for quick testing

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

    // FOR TESTS

    // knuthShuffle :: [a] -> [a]
    const knuthShuffle = xs => {
        const swapped = (iFrom, iTo, xs) =>
            xs.map(
                (x, i) => iFrom !== i ? (
                    iTo !== i ? x : xs[iFrom]
                ) : xs[iTo]
            );
        return enumFromTo(0, xs.length - 1)
            .reduceRight((a, i) => {
                const iRand = randomRInt(0, i)();
                return i !== iRand ? (
                    swapped(i, iRand, a)
                ) : a;
            }, xs);
    };

    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) =>
        (Array.isArray(xs) ? (
            xs
        ) : xs.split('')).map(f);

    // FOR TESTS

    // randomRInt :: Int -> Int -> IO () -> Int
    const randomRInt = (low, high) => () =>
        low + Math.floor(
            (Math.random() * ((high - low) + 1))
        );

    // reverse :: [a] -> [a]
    const reverse = xs =>
        'string' !== typeof xs ? (
            xs.slice(0).reverse()
        ) : xs.split('').reverse().join('');

    // 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();
})();

The code implements a binary search algorithm that searches for a specific "secret" value within a sorted integer array. The search can be performed both recursively and iteratively. The algorithm divides the search range in half repeatedly until the secret value is found or the range is exhausted. The code also handles multiple values equal to the given value and indicates whether the element was found or not. It returns the index of the secret value if found, otherwise, it returns the insertion point. The code also includes variations of the binary search algorithm that return the leftmost and rightmost insertion points. Additionally, the code avoids overflow bugs during the calculation of the mid-point of the search range.


Works with: Node.js
process.argv.forEach((val, index) => {
  console.log(`${index}: ${val}`);
});

Works with: JScript
var objArgs = WScript.Arguments;
for (var i = 0; i < objArgs.length; i++)
   WScript.Echo(objArgs.Item(i));

Works with: JScript.NET (compiled with jsc.exe)
import System;
var argv:String[] = Environment.GetCommandLineArgs();
for (var i in argv)
  print(argv[i]);

Works with: Rhino
Works with: SpiderMonkey
for (var i = 0; i < arguments.length; i++)
    print(arguments[i]);

The code retrieves and prints the list of command-line arguments provided to the program, such as 'myprogram -c "alpha beta" -h "gamma"'. It also includes functionalities for intelligent parsing of these arguments.


  <title>Pendulum</title>

<canvas id="canvas" width="600" height="600">

Sorry, your browser does not support the <canvas> used to display the pendulum animation.

</canvas>

<svg height="100%" width="100%" viewBox="-2 0 4 4" xmlns="http://www.w3.org/2000/svg">
  <line id="string" x1="0" y1="0" x2="1" y2="0" stroke="grey" stroke-width="0.05" />
  <circle id="ball" cx="0" cy="0" r="0.1" fill="black" />

</svg>

simulate and animate a simple gravity pendulum using SVG. The animation is created using a stereographic projection of the circle and the Euler-Lagrange equations are integrated using the Runge-Kutta method. The problem is formulated in a dimensionless manner, assuming unit values for mass and length.


var data = JSON.parse('{ "foo": 1, "bar": [10, "apples"] }');

var sample = { "blue": [1,2], "ocean": "water" };
var json_string = JSON.stringify(sample);

The code loads a JSON string into a data structure and creates a new data structure, serializing it into valid JSON using objects and arrays. It requires a JSON library, which is available in all major browsers. The JSON used is different from JavaScript object literal.


function nthRoot(num, nArg, precArg) {
  var n = nArg || 2;
  var prec = precArg || 12;

  var x = 1; // Initial guess.
  for (var i=0; i<prec; i++) {
    x = 1/n * ((n-1)*x + (num / Math.pow(x, n-1)));
  }

  return x;
}

Implement the algorithm to compute the principal nth root of a positive real number with a default precision of 12 and n defaulting to 2.


Works with: JScript
var network = new ActiveXObject('WScript.Network');
var hostname = network.computerName;
WScript.echo(hostname);

"Determines and outputs the hostname of the current system where the routine is running."


generates the first 25 Leonardo numbers starting from L(0), allows customization of the first two Leonardo numbers and the add number, and can also generate the Fibonacci sequence by setting 0 and 1 for L(0) and L(1), and 0 for the add number.


function twentyfour(numbers, input) {
    var invalidChars = /[^\d\+\*\/\s-\(\)]/;

    var validNums = function(str) {
        // Create a duplicate of our input numbers, so that
        // both lists will be sorted.
        var mnums = numbers.slice();
        mnums.sort();

        // Sort after mapping to numbers, to make comparisons valid.
        return str.replace(/[^\d\s]/g, " ")
            .trim()
            .split(/\s+/)
            .map(function(n) { return parseInt(n, 10); })
            .sort()
            .every(function(v, i) { return v === mnums[i]; });
    };

    var validEval = function(input) {
        try {
            return eval(input);
        } catch (e) {
            return {error: e.toString()};
        }
    };

    if (input.trim() === "") return "You must enter a value.";
    if (input.match(invalidChars)) return "Invalid chars used, try again. Use only:\n + - * / ( )";
    if (!validNums(input)) return "Wrong numbers used, try again.";
    var calc = validEval(input);
    if (typeof calc !== 'number') return "That is not a valid input; please try again.";
    if (calc !== 24) return "Wrong answer: " + String(calc) + "; please try again.";
    return input + " == 24.  Congratulations!";
};

// I/O below.

while (true) {
    var numbers = [1, 2, 3, 4].map(function() {
        return Math.floor(Math.random() * 8 + 1);
    });

    var input = prompt(
        "Your numbers are:\n" + numbers.join(" ") +
        "\nEnter expression. (use only + - * / and parens).\n", +"'x' to exit.", "");

    if (input === 'x') {
        break;
    }
    alert(twentyfour(numbers, input));
}

"Generate a game that randomly selects four digits and prompts the user to create an arithmetic expression with these digits that equals 24. The code checks and evaluates the user's expression, allowing for addition, subtraction, multiplication, and division operations. The code does not allow the formation of multiple digit numbers from the given digits."


function encode(input) {
    var encoding = [];
    var prev, count, i;
    for (count = 1, prev = input[0], i = 1; i < input.length; i++) {
        if (input[i] != prev) {
            encoding.push([count, prev]);
            count = 1;
            prev = input[i];
        }
        else
            count ++;
    }
    encoding.push([count, prev]);
    return encoding;
}

Here's an encoding method that uses a regular expression to grab the character runs (Works with: JavaScript version 1.6 for the forEach method)
function encode_re(input) {
    var encoding = [];
    input.match(/(.)\1*/g).forEach(function(substr){ encoding.push([substr.length, substr[0]]) });
    return encoding;
}

function decode(encoded) {
    var output = "";
    encoded.forEach(function(pair){ output += new Array(1+pair[0]).join(pair[1]) })
    return output;
}

(() => {
    'use strict';

    // runLengthEncode :: String -> [(Int, Char)]
    const runLengthEncoded = s =>
        group(s.split('')).map(
            cs => [cs.length, cs[0]]
        );

    // runLengthDecoded :: [(Int, Char)] -> String
    const runLengthDecoded = pairs =>
        pairs.map(([n, c]) => c.repeat(n)).join('');

    // ------------------------TEST------------------------
    const main = () => {
        const
            xs = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWW' +
            'WWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW',
            ys = runLengthEncoded(xs);

        console.log('From: ', show(xs));
        [ys, runLengthDecoded(ys)].forEach(
            x => console.log('  ->  ', show(x))
        )
    };

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

    // group :: [a] -> [[a]]
    const group = xs => {
        // A list of lists, each containing only equal elements,
        // such that the concatenation of these lists is xs.
        const go = xs =>
            0 < xs.length ? (() => {
                const
                    h = xs[0],
                    i = xs.findIndex(x => h !== x);
                return i !== -1 ? (
                    [xs.slice(0, i)].concat(go(xs.slice(i)))
                ) : [xs];
            })() : [];
        return go(xs);
    };

    // show :: a -> String
    const show = JSON.stringify;

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

implement a run-length encoding and decoding system. It compresses strings by counting the number of repeated characters and then reverses the compression. The input is a string of uppercase characters, and the output is a string representing the count and character. The code also includes a method that traverses the input string character by character for encoding, and a function for decoding. A generic group function and a .reduce() based one-liner are also defined.


Initializes two string variables, one with a text value and the other as a concatenation of the first variable and a string literal, then displays their content.


var normal = 'http://foo/bar/';
var encoded = encodeURIComponent(normal);

The code provides a function to convert a given string into URL encoding representation. It converts all characters except 0-9, A-Z, and a-z into a percent symbol followed by a two-digit hexadecimal code. It also handles ASCII control codes, symbols, and extended characters. The code also supports variations like lowercase escapes and different encoding standards like RFC 3986, HTML 5, and encodeURI function in Javascript. An optional feature to use an exception string is also provided.


generates a common sorted list with unique elements from multiple integer arrays.


Works with: Node.js
var fs = require('fs');
var words = fs.readFileSync('unixdict.txt', 'UTF-8').split('\n');

var i, item, max = 0,
    anagrams = {};

for (i = 0; i < words.length; i += 1) {
  var key = words[i].split('').sort().join('');
  if (!anagrams.hasOwnProperty(key)) {//check if property exists on current obj only
      anagrams[key] = [];
  }
  var count = anagrams[key].push(words[i]); //push returns new array length
  max = Math.max(count, max);
}

//note, this returns all arrays that match the maximum length
for (item in anagrams) {
  if (anagrams.hasOwnProperty(item)) {//check if property exists on current obj only
    if (anagrams[item].length === max) {
        console.log(anagrams[item].join(' '));
    }
  }
}

Code summarization: The code uses JavaScript for Automation on macOS to find sets of words from a given word list that are anagrams, i.e., they share the same characters but in different orders. The code specifically identifies the sets with the most words.


Works with: JavaScript version 1.6
Works with: Firefox version 1.5+

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Sierpinski Carpet</title>

generate a graphical or ASCII-art representation of a Sierpinski carpet of a given order N. The representation is created using a N by N array of boolean values, which are then mapped to lines of characters for output. The code also allows for the generation of a graphical representation via HTML and CSS in a browser environment. The placement of whitespace and non-whitespace characters is crucial in the representation.


Works with: SpiderMonkey for the print() function.

function HuffmanEncoding(str) {
    this.str = str;

    var count_chars = {};
    for (var i = 0; i < str.length; i++)
        if (str[i] in count_chars)
            count_chars[str[i]] ++;
        else
            count_chars[str[i]] = 1;

    var pq = new BinaryHeap(function(x){return x[0];});
    for (var ch in count_chars)
        pq.push([count_chars[ch], ch]);

    while (pq.size() > 1) {
        var pair1 = pq.pop();
        var pair2 = pq.pop();
        pq.push([pair1[0]+pair2[0], [pair1[1], pair2[1]]]);
    }

    var tree = pq.pop();
    this.encoding = {};
    this._generate_encoding(tree[1], "");

    this.encoded_string = ""
    for (var i = 0; i < this.str.length; i++) {
        this.encoded_string += this.encoding[str[i]];
    }
}

HuffmanEncoding.prototype._generate_encoding = function(ary, prefix) {
    if (ary instanceof Array) {
        this._generate_encoding(ary[0], prefix + "0");
        this._generate_encoding(ary[1], prefix + "1");
    }
    else {
        this.encoding[ary] = prefix;
    }
}

HuffmanEncoding.prototype.inspect_encoding = function() {
    for (var ch in this.encoding) {
        print("'" + ch + "': " + this.encoding[ch])
    }
}

HuffmanEncoding.prototype.decode = function(encoded) {
    var rev_enc = {};
    for (var ch in this.encoding)
        rev_enc[this.encoding[ch]] = ch;

    var decoded = "";
    var pos = 0;
    while (pos < encoded.length) {
        var key = ""
        while (!(key in rev_enc)) {
            key += encoded[pos];
            pos++;
        }
        decoded += rev_enc[key];
    }
    return decoded;
}

var s = "this is an example for huffman encoding";
print(s);

var huff = new HuffmanEncoding(s);
huff.inspect_encoding();

var e = huff.encoded_string;
print(e);

var t = huff.decode(e);
print(t);

print("is decoded string same as original? " + (s==t));

The code implements Huffman encoding for a given string. It first calculates the frequency of each character in the string. It then uses a binary heap to create a tree of nodes, where each node represents a character and its frequency. The tree is constructed such that nodes with lower frequencies are higher up in the tree. The code then traverses the tree from root to leaves, assigning a '0' for one branch and a '1' for the other at each node. The accumulated zeros and ones at each leaf constitute a Huffman encoding for the corresponding character. The output is a table of characters and their Huffman encodings.


    <title>Simple Window Application</title>

 &nbsp &nbsp &nbsp &nbsp

    <button type="button" onclick="count_clicks()"> Click me</button>

    Clicks: 0

create a windowed application with a label and a button. The label initially displays "There have been no clicks yet". The button is labeled "click me". The label updates to show the number of times the button has been clicked when the button is clicked.


for (var i=10; i>=0; --i) print(i);

for (var i = 11; i--;) console.log(i);

var i = 11;
while (i--) console.log(i);

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

range(0, 10).reverse().forEach(
  function (x) {
    console.log(x);
  }
);

console.log(
  range(0, 10).reverse().map(
    function (x) {
      return x;
    }
  ).join('\n')
);

console.log(
    range(0, 10).reverse().join('\n')
);

utilize a for loop to perform a countdown from 10 to 0. The code may be optimized for longer reversed iterations by moving the mutation into the test and omitting the third term of the for() statement. The code can also be written in a functional idiom of JavaScript using Array.map() instead of Array.forEach() for a composable expression with a value.


// helpers
// helper
function ordA(a) {
  return a.charCodeAt(0) - 65;
}

// vigenere
function vigenere(text, key, decode) {
  var i = 0, b;
  key = key.toUpperCase().replace(/[^A-Z]/g, '');
  return text.toUpperCase().replace(/[^A-Z]/g, '').replace(/[A-Z]/g, function(a) {
    b = key[i++ % key.length];
    return String.fromCharCode(((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65));
  });
}

// example
var text = "The quick brown fox Jumped over the lazy Dog the lazy dog lazy dog dog";
var key = 'alex';
var enc = vigenere(text,key);
var dec = vigenere(enc,key,true);

console.log(enc);
console.log(dec);

Implement both encryption and decryption of a Vigenère cipher. The codes handle keys and text of unequal length, capitalize all characters, and discard non-alphabetic characters. If non-alphabetic characters are handled differently, it is noted.


var output = '',
    i;
for (i = 2; i <= 8; i += 2) {
   output += i + ', ';
}
output += 'who do we appreciate?';
document.write(output);

// range(iMax)
// range(iMin, iMax)
// range(iMin, iMax, dI)
function range() {
  var lngArgs = arguments.length,
    lngMore = lngArgs - 1;

  iMin = lngMore ? arguments[0] : 1;
  iMax = arguments[lngMore ? 1 : 0];
  dI = lngMore > 1 ? arguments[2] : 1;

  return lngArgs ? Array.apply(null, Array(
    Math.floor((iMax - iMin) / dI) + 1
  )).map(function (_, i) {
    return iMin + (dI * i);
  }) : [];
}

console.log(
  range(2, 8, 2).join(', ') + ', who do we appreciate ?'
);

2, 4, 6, 8, who do we appreciate ?

demonstrate a for-loop in JavaScript with a step-value greater than one, using a functional idiom. The computation is composed within the superordinate expressions of the program, returning a value rather than firing off side-effects. The stepped series is generated as an expression, replacing a state-changing loop with a non-mutating map or fold.


var obj;

function sum(o, lo, hi, term) {
  var tmp = 0;
  for (o.val = lo; o.val <= hi; o.val++)
    tmp += term();
  return tmp;
}

obj = {val: 0};
alert(sum(obj, 1, 100, function() {return 1 / obj.val}));

The code implements Jensen's Device, a programming technique that exploits the call by name mechanism. It calculates the 100th harmonic number using a sum procedure, which takes in four parameters: an integer, two range values, and a term passed by name. The sum procedure iteratively adds the term to a temporary variable, which is then returned as the result. The calculation depends on the re-evaluation of the passed expression in the caller's context each time the formal parameter's value is needed. The first parameter, representing the bound variable of the summation, is also passed by name to ensure changes to it are visible in the caller's context. The result is displayed as '5.187377517639621'.


function maze(x,y) {
	var n=x*y-1;
	if (n<0) {alert("illegal maze dimensions");return;}
	var horiz =[]; for (var j= 0; j<x+1; j++) horiz[j]= [],
	    verti =[]; for (var j= 0; j<x+1; j++) verti[j]= [],
	    here = [Math.floor(Math.random()*x), Math.floor(Math.random()*y)],
	    path = [here],
	    unvisited = [];
	for (var j = 0; j<x+2; j++) {
		unvisited[j] = [];
		for (var k= 0; k<y+1; k++)
			unvisited[j].push(j>0 && j<x+1 && k>0 && (j != here[0]+1 || k != here[1]+1));
	}
	while (0<n) {
		var potential = [[here[0]+1, here[1]], [here[0],here[1]+1],
		    [here[0]-1, here[1]], [here[0],here[1]-1]];
		var neighbors = [];
		for (var j = 0; j < 4; j++)
			if (unvisited[potential[j][0]+1][potential[j][1]+1])
				neighbors.push(potential[j]);
		if (neighbors.length) {
			n = n-1;
			next= neighbors[Math.floor(Math.random()*neighbors.length)];
			unvisited[next[0]+1][next[1]+1]= false;
			if (next[0] == here[0])
				horiz[next[0]][(next[1]+here[1]-1)/2]= true;
			else
				verti[(next[0]+here[0]-1)/2][next[1]]= true;
			path.push(here = next);
		} else
			here = path.pop();
	}
	return {x: x, y: y, horiz: horiz, verti: verti};
}

function display(m) {
	var text= [];
	for (var j= 0; j<m.x*2+1; j++) {
		var line= [];
		if (0 == j%2)
			for (var k=0; k<m.y*4+1; k++)
				if (0 == k%4)
					line[k]= '+';
				else
					if (j>0 && m.verti[j/2-1][Math.floor(k/4)])
						line[k]= ' ';
					else
						line[k]= '-';
		else
			for (var k=0; k<m.y*4+1; k++)
				if (0 == k%4)
					if (k>0 && m.horiz[(j-1)/2][k/4-1])
						line[k]= ' ';
					else
						line[k]= '|';
				else
					line[k]= ' ';
		if (0 == j) line[1]= line[2]= line[3]= ' ';
		if (m.x*2-1 == j) line[4*m.y]= ' ';
		text.push(line.join('')+'\r\n');
	}
	return text.join('');
}

x,y — dimensions of maze
n — number of openings to be generated
horiz — two dimensional array of locations of horizontal openings (true means wall is open)
verti — two dimensional array of locations of vertical openings (true means wall is open)
here — current location under consideration
path — history (stack) of locations that might need to be revisited
unvisited — two dimensional array of locations that have not been visited, padded to avoid need for boundary tests (true means location needs to be visited)
potential — locations adjacent to here
neighbors — unvisited locations adjacent to here

m — maze to be drawn
text — lines of text representing maze
line — characters of current line

Example use:
<title></title>

+   +---+---+---+---+---+---+---+---+---+---+
|                   |                   |   |
+---+---+   +   +---+   +   +---+---+   +   +
|       |   |   |       |   |           |   |
+   +   +   +---+   +---+   +---+---+   +   +
|   |   |               |           |   |   |
+   +---+   +---+---+---+---+---+   +   +   +
|       |   |               |       |       |
+---+   +---+   +---+---+   +   +---+---+   +
|   |   |       |               |       |   |
+   +   +   +---+---+---+---+---+   +   +   +
|       |                   |       |   |   |
+   +---+---+   +---+---+   +   +---+---+   +
|   |       |   |           |       |       |
+   +   +   +---+   +---+---+   +   +   +---+
|       |           |           |
+---+---+---+---+---+---+---+---+---+---+---+

	function step() {
		if (0<n) {

			document.getElementById('out').innerHTML= display({x: x, y: y, horiz: horiz, verti: verti, here: here});
			setTimeout(step, 100);
		}
	}
	step();

				if (m.here && m.here[0]*2+1 == j && m.here[1]*4+2 == k)
					line[k]= '#'
				else if (0 == k%4) {

			here= next;
			if (1 < neighbors.length)
				path.push(here);

<title>Maze maker</title>

<form><fieldset>
rows <input id='rows' size="3"/>
colums <input id='cols' size="3"/>
Generate
Solve
</fieldset></form>

The code generates and displays a maze using the Depth-first search algorithm. It starts from a random cell, marks it as visited, and proceeds to its neighbors. If a neighbor hasn't been visited, the wall between the current cell and that neighbor is removed and the process is repeated for that neighbor. The code relies on JavaScript arrays' ability to be treated as infinite in size with null values appearing as needed. The progress of the maze creation can be animated by using a display function in each iteration of the main loop. The code also suggests an optimization to save processing, but it will still need to backtrack through locations with no unvisited neighbors. The maze is displayed using HTML, CSS, and table cells.


The code continuously calculates and outputs the next decimal digit of Pi, starting from 3.14159265... until manually stopped by the user. It can be adapted to work in both Node.js and browser environments. It also includes a feature to load the code into a webpage without freezing the browser. The code uses BigInt and may consume significant memory. It returns an approximation of Pi, calculated one digit at a time.


"Function to compare and order two numerical lists based on lexicographic order, returning true if the first list should be ordered before the second, false otherwise."


function ack(m, n) {
 return m === 0 ? n + 1 : ack(m - 1, n === 0  ? 1 : ack(m, n - 1));
}

function ack(M,N) {
  for (; M > 0; M--) {
    N = N === 0 ? 1 : ack(M,N-1);
  }
  return N+1;
}

function stackermann(M, N) {
  const stack = [];
  for (;;) {
    if (M === 0) {
      N++;
      if (stack.length === 0) return N;
      const r = stack[stack.length-1];
      if (r[1] === 1) stack.length--;
      else r[1]--;
      M = r[0];
    } else if (N === 0) {
      M--;
      N = 1;
    } else {
      M--
      stack.push([M, N]);
      N = 1;
    }
  }
}

#!/usr/bin/env nodejs
function ack(M, N){
	const next = new Float64Array(M + 1);
	const goal = new Float64Array(M + 1).fill(1, 0, M);
	const n = N + 1;

	// This serves as a sentinel value;
	// next[M] never equals goal[M] == -1,
	// so we don't need an extra check for
	// loop termination below.
	goal[M] = -1;

	let v;
	do {
		v = next[0] + 1;
		let m = 0;
		while (next[m] === goal[m]) {
			goal[m] = v;
			next[m++]++;
		}
		next[m]++;
	} while (next[M] !== n);
	return v;
}
var args = process.argv;
console.log(ack(parseInt(args[2]), parseInt(args[3])));

Implement the Ackermann function which is a recursive function that takes two non-negative arguments and returns a value based on the specified conditions. The function should ideally support arbitrary precision due to its rapid growth.


Implement and compare the Gamma function using built-in/library function and self-implemented algorithms. The function is defined through numerical integration, and methods include Lanczos and Stirling's approximation.


function queenPuzzle(rows, columns) {
    if (rows <= 0) {
        return [[]];
    } else {
        return addQueen(rows - 1, columns);
    }
}

function addQueen(newRow, columns, prevSolution) {
    var newSolutions = [];
    var prev = queenPuzzle(newRow, columns);
    for (var i = 0; i < prev.length; i++) {
        var solution = prev[i];
        for (var newColumn = 0; newColumn < columns; newColumn++) {
            if (!hasConflict(newRow, newColumn, solution))
                newSolutions.push(solution.concat([newColumn]))
        }
    }
    return newSolutions;
}

function hasConflict(newRow, newColumn, solution) {
    for (var i = 0; i < newRow; i++) {
        if (solution[i]     == newColumn          ||
            solution[i] + i == newColumn + newRow ||
            solution[i] - i == newColumn - newRow) {
                return true;
        }
    }
    return false;
}

console.log(queenPuzzle(8,8));

(() => {
    "use strict";

    // ---------------- N QUEENS PROBLEM -----------------

    // queenPuzzle :: Int -> Int -> [[Int]]
    const queenPuzzle = intCols => {
        // All solutions for a given number
        // of columns and rows.
        const go = nRows =>
            nRows <= 0 ? [
                []
            ] : go(nRows - 1).reduce(
                (a, solution) => [
                    ...a, ...(
                        enumFromTo(0)(intCols - 1)
                        .reduce((b, iCol) =>
                            safe(
                                nRows - 1, iCol, solution
                            ) ? (
                                [...b, [...solution, iCol]]
                            ) : b, [])
                    )
                ], []
            );

        return go;
    };

    // safe : Int -> Int -> [Int] -> Bool
    const safe = (iRow, iCol, solution) =>
        !zip(solution)(
            enumFromTo(0)(iRow - 1)
        )
        .some(
            ([sc, sr]) => (iCol === sc) || (
                sc + sr === iCol + iRow
            ) || (sc - sr === iCol - iRow)
        );

    // ---------------------- TEST -----------------------
    // Ten columns of solutions to the 7*7 board

    // main :: IO ()
    const main = () =>
        // eslint-disable-next-line no-console
        console.log(
            showSolutions(10)(7)
        );

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

    // showSolutions :: Int -> Int -> String
    const showSolutions = nCols =>
        // Display of solutions, in nCols columns
        // for a board of size N * N.
        n => chunksOf(nCols)(
            queenPuzzle(n)(n)
        )
        .map(xs => transpose(
                xs.map(
                    rows => rows.map(
                        r => enumFromTo(1)(rows.length)
                        .flatMap(
                            x => r === x ? (
                                "♛"
                            ) : "."
                        )
                        .join("")
                    )
                )
            )
            .map(cells => cells.join("  "))
        )
        .map(x => x.join("\n"))
        .join("\n\n");

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

    // chunksOf :: Int -> [a] -> [[a]]
    const chunksOf = n => {
        // xs split into sublists of length n.
        // The last sublist will be short if n
        // does not evenly divide the length of xs .
        const go = xs => {
            const chunk = xs.slice(0, n);

            return Boolean(chunk.length) ? [
                chunk, ...go(xs.slice(n))
            ] : [];
        };

        return go;
    };

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

    // transpose_ :: [[a]] -> [[a]]
    const transpose = rows =>
        // The columns of the input transposed
        // into new rows.
        // Simpler version of transpose, assuming input
        // rows of even length.
        Boolean(rows.length) ? rows[0].map(
            (_, i) => rows.flatMap(
                v => v[i]
            )
        ) : [];

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

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

implement a solution to the N-queens problem using recursive backtracking. The algorithm checks for the correct position on subfields to save position checks. It also includes a function to display columns of solutions. The code is a translation of an ES5 version. It can solve the puzzle for a board of any size NxN and provides the number of solutions for small values of N.


var a = [1,2,3],
    b = [4,5,6],
    c = a.concat(b); //=> [1,2,3,4,5,6]

(function () {
    'use strict';

    // concat :: [[a]] -> [a]
    function concat(xs) {
        return [].concat.apply([], xs);
    }

   return concat(
      [["alpha", "beta", "gamma"],
      ["delta", "epsilon", "zeta"],
      ["eta", "theta", "iota"]]
  );

})();

demonstrate how to concatenate two arrays using the Array.concat() method or a generic function, as per the programming task.


/*global portviz:false, _:false */
/*
 * 0-1 knapsack solution, recursive, memoized, approximate.
 *
 * credits:
 *
 * the Go implementation here:
 *   http://rosettacode.org/mw/index.php?title=Knapsack_problem/0-1
 *
 * approximation details here:
 *   http://math.mit.edu/~goemans/18434S06/knapsack-katherine.pdf
 */
portviz.knapsack = {};
(function() {
  this.combiner = function(items, weightfn, valuefn) {
    // approximation guarantees result >= (1-e) * optimal
    var _epsilon = 0.01;
    var _p = _.max(_.map(items,valuefn));
    var _k = _epsilon * _p / items.length;

    var _memo = (function(){
      var _mem = {};
      var _key = function(i, w) {
        return i + '::' + w;
      };
      return {
        get: function(i, w) {
          return _mem[_key(i,w)];
        },
        put: function(i, w, r) {
          _mem[_key(i,w)]=r;
          return r;
        }
      };
    })();

    var _m = function(i, w) {

      i = Math.round(i);
      w = Math.round(w);

      if (i < 0 || w === 0) {
        // empty base case
        return {items: [], totalWeight: 0, totalValue: 0};
      }

      var mm = _memo.get(i,w);
      if (!_.isUndefined(mm)) {
        return mm;
      }

      var item = items[i];
      if (weightfn(item) > w) {
        //item does not fit, try the next item
        return _memo.put(i, w, _m(i-1, w));
      }
      // this item could fit.
      // are we better off excluding it?
      var excluded = _m(i-1, w);
      // or including it?
      var included = _m(i-1, w - weightfn(item));
      if (included.totalValue + Math.floor(valuefn(item)/_k) > excluded.totalValue) {
        // better off including it
        // make a copy of the list
        var i1 = included.items.slice();
        i1.push(item);
        return _memo.put(i, w,
          {items: i1,
           totalWeight: included.totalWeight + weightfn(item),
           totalValue: included.totalValue + Math.floor(valuefn(item)/_k)});
      }
      //better off excluding it
      return _memo.put(i,w, excluded);
    };
    return {
      /* one point */
      one: function(maxweight) {
        var scaled = _m(items.length - 1, maxweight);
        return {
          items: scaled.items,
          totalWeight: scaled.totalWeight,
          totalValue: scaled.totalValue * _k
        };
      },
      /* the entire EF */
      ef: function(maxweight, step) {
        return _.map(_.range(0, maxweight+1, step), function(weight) {
          var scaled = _m(items.length - 1, weight);
          return {
            items: scaled.items,
            totalWeight: scaled.totalWeight,
            totalValue: scaled.totalValue * _k
          };
        });
      }
    };
  };
}).apply(portviz.knapsack);

/*global portviz:false, _:false */
/*
 * after rosettacode.org/mw/index.php?title=Knapsack_problem/0-1
 */
var allwants = [
  {name:"map", weight:9, value: 150},
  {name:"compass", weight:13, value: 35},
  {name:"water", weight:153, value: 200},
  {name:"sandwich", weight: 50, value: 160},
  {name:"glucose", weight:15, value: 60},
  {name:"tin", weight:68, value: 45},
  {name:"banana", weight:27, value: 60},
  {name:"apple", weight:39, value: 40},
  {name:"cheese", weight:23, value: 30},
  {name:"beer", weight:52, value: 10},
  {name:"suntan cream", weight:11, value: 70},
  {name:"camera", weight:32, value: 30},
  {name:"T-shirt", weight:24, value: 15},
  {name:"trousers", weight:48, value: 10},
  {name:"umbrella", weight:73, value: 40},
  {name:"waterproof trousers", weight:42, value: 70},
  {name:"waterproof overclothes", weight:43, value: 75},
  {name:"note-case", weight:22, value: 80},
  {name:"sunglasses", weight:7, value: 20},
  {name:"towel", weight:18, value: 12},
  {name:"socks", weight:4, value: 50},
  {name:"book", weight:30, value: 10}
];

var near = function(actual, expected, tolerance) {
  if (expected === 0 && actual === 0) return true;
  if (expected === 0) {
    return Math.abs(expected - actual) / actual < tolerance;
  }
  return Math.abs(expected - actual) / expected < tolerance;
};

test("one knapsack", function() {
  var combiner =
    portviz.knapsack.combiner(allwants,
      function(x){return x.weight;},
      function(x){return x.value;});
  var oneport = combiner.one(400);
  ok(near(oneport.totalValue, 1030, 0.01), "correct total value");
  ok(near(oneport.totalValue, 1030, 0.01), "correct total value");
  equal(oneport.totalWeight, 396, "correct total weight");
});

test("frontier", function() {
  var combiner =
    portviz.knapsack.combiner(allwants,
      function(x){return x.weight;},
      function(x){return x.value;});
  var ef = combiner.ef(400, 1);
  equal(ef.length, 401, "401 because it includes the endpoints");
  ef = combiner.ef(400, 40);
  equal(ef.length, 11, "11 because it includes the endpoints");
  var expectedTotalValue = [
    0,
    330,
    445,
    590,
    685,
    755,
    810,
    860,
    902,
    960,
    1030
  ] ;
  _.each(ef, function(element, index) {
    // 15% error!  bleah!
    ok(near(element.totalValue, expectedTotalValue[index], 0.15),
      'actual ' + element.totalValue + ' expected ' + expectedTotalValue[index]);
  });
  deepEqual(_.pluck(ef, 'totalWeight'), [
    0,
    39,
    74,
    118,
    158,
    200,
    236,
    266,
    316,
    354,
    396
  ]);
  deepEqual(_.map(ef, function(x){return x.items.length;}), [
    0,
    4,
    6,
    7,
    9,
    10,
    10,
    12,
    14,
    11,
    12
   ]);
});

The code determines the optimal combination of items a tourist can carry in his knapsack, given a maximum weight limit of 4kg (400 dag), where each item has a specific weight and value. The goal is to maximize the total value without exceeding the weight limit. The items cannot be divided or reduced.


function Person(name) {

    var candidateIndex = 0;

    this.name = name;
    this.fiance = null;
    this.candidates = [];

    this.rank = function(p) {
        for (i = 0; i < this.candidates.length; i++)
            if (this.candidates[i] === p) return i;
        return this.candidates.length + 1;
    }

    this.prefers = function(p) {
        return this.rank(p) < this.rank(this.fiance);
    }

    this.nextCandidate = function() {
        if (candidateIndex >= this.candidates.length) return null;
        return this.candidates[candidateIndex++];
    }

    this.engageTo = function(p) {
        if (p.fiance) p.fiance.fiance = null;
        p.fiance = this;
        if (this.fiance) this.fiance.fiance = null;
        this.fiance = p;
    }

    this.swapWith = function(p) {
        console.log("%s & %s swap partners", this.name, p.name);
        var thisFiance = this.fiance;
        var pFiance = p.fiance;
        this.engageTo(pFiance);
        p.engageTo(thisFiance);
    }
}

function isStable(guys, gals) {
    for (var i = 0; i < guys.length; i++)
        for (var j = 0; j < gals.length; j++)
            if (guys[i].prefers(gals[j]) && gals[j].prefers(guys[i]))
                return false;
    return true;
}

function engageEveryone(guys) {
    var done;
    do {
        done = true;
        for (var i = 0; i < guys.length; i++) {
            var guy = guys[i];
            if (!guy.fiance) {
                done = false;
                var gal = guy.nextCandidate();
                if (!gal.fiance || gal.prefers(guy))
                    guy.engageTo(gal);
            }
        }
    } while (!done);
}

function doMarriage() {

    var abe  = new Person("Abe");
    var bob  = new Person("Bob");
    var col  = new Person("Col");
    var dan  = new Person("Dan");
    var ed   = new Person("Ed");
    var fred = new Person("Fred");
    var gav  = new Person("Gav");
    var hal  = new Person("Hal");
    var ian  = new Person("Ian");
    var jon  = new Person("Jon");
    var abi  = new Person("Abi");
    var bea  = new Person("Bea");
    var cath = new Person("Cath");
    var dee  = new Person("Dee");
    var eve  = new Person("Eve");
    var fay  = new Person("Fay");
    var gay  = new Person("Gay");
    var hope = new Person("Hope");
    var ivy  = new Person("Ivy");
    var jan  = new Person("Jan");

    abe.candidates  = [abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay];
    bob.candidates  = [cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay];
    col.candidates  = [hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan];
    dan.candidates  = [ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi];
    ed.candidates   = [jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay];
    fred.candidates = [bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay];
    gav.candidates  = [gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay];
    hal.candidates  = [abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee];
    ian.candidates  = [hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve];
    jon.candidates  = [abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope];
    abi.candidates  = [bob, fred, jon, gav, ian, abe, dan, ed, col, hal];
    bea.candidates  = [bob, abe, col, fred, gav, dan, ian, ed, jon, hal];
    cath.candidates = [fred, bob, ed, gav, hal, col, ian, abe, dan, jon];
    dee.candidates  = [fred, jon, col, abe, ian, hal, gav, dan, bob, ed];
    eve.candidates  = [jon, hal, fred, dan, abe, gav, col, ed, ian, bob];
    fay.candidates  = [bob, abe, ed, ian, jon, dan, fred, gav, col, hal];
    gay.candidates  = [jon, gav, hal, fred, bob, abe, col, ed, dan, ian];
    hope.candidates = [gav, jon, bob, abe, ian, dan, hal, ed, col, fred];
    ivy.candidates  = [ian, col, hal, gav, fred, bob, abe, ed, jon, dan];
    jan.candidates  = [ed, hal, gav, abe, bob, jon, col, ian, fred, dan];

    var guys = [abe, bob, col, dan, ed, fred, gav, hal, ian, jon];
    var gals = [abi, bea, cath, dee, eve, fay, gay, hope, ivy, jan];

    engageEveryone(guys);

    for (var i = 0; i < guys.length; i++) {
        console.log("%s is engaged to %s", guys[i].name, guys[i].fiance.name);
    }
    console.log("Stable = %s", isStable(guys, gals) ? "Yes" : "No");
    jon.swapWith(fred);
    console.log("Stable = %s", isStable(guys, gals) ? "Yes" : "No");
}

doMarriage();

"Implement the Gale-Shapley algorithm to solve the Stable Marriage problem. The program takes as input the preferences of ten men and ten women, and outputs a stable set of engagements. It then perturbs this set to form an unstable set of engagements and checks this new set for stability."


(function () {
    'use strict';

    function a(bool) {
        console.log('a -->', bool);

        return bool;
    }

    function b(bool) {
        console.log('b -->', bool);

        return bool;
    }

    var x = a(false) && b(true),
        y = a(true) || b(false),
        z = true ? a(true) : b(false);

  return [x, y, z];
})();

The code defines two functions, 'a' and 'b', both of which accept and return the same boolean value and print their respective names when called. The code then calculates and assigns the values of two equations, using short-circuit evaluation to ensure that function 'b' is only called when necessary. If the programming language does not support short-circuit evaluation, nested 'if' statements are used to achieve the same result. The code demonstrates the concept of short-circuit evaluation in boolean expressions, a feature present in JavaScript since its early versions.


var globalAudioContext = new webkitAudioContext();

function morsecode(text, unit, freq) {
	'use strict';

	// defaults
	unit = unit ? unit : 0.05;
	freq = freq ? freq : 700;
	var cont = globalAudioContext;
	var time = cont.currentTime;

	// morsecode
	var code = {
		a: '._',    b: '_...',  c: '_._.',  d: '_..',   e: '.',     f: '.._.',
		g: '__.',   h: '....',  i: '..',    j: '.___',  k: '_._',   l: '._..',
		m: '__',    n: '_.',    o: '___',   p: '.__.',  q: '__._',  r: '._.',
		s: '...',   t: '_',     u: '.._',   v: '..._',  w: '.__',   x: '_.._',
		y: '_.__',  z: '__..',  0: '_____', 1: '.____', 2: '..___', 3: '...__',
		4: '...._', 5: '.....', 6: '_....', 7: '__...', 8: '___..', 9: '____.'
	};

	// generate code for text
	function makecode(data) {
		for (var i = 0; i <= data.length; i ++) {
			var codedata = data.substr(i, 1).toLowerCase();
			codedata = code[codedata];
			// recognised character
			if (codedata !== undefined) {
				maketime(codedata);
			}
			// unrecognised character
			else {
				time += unit * 7;
			}
		}
	}

	// generate time for code
	function maketime(data) {
		for (var i = 0; i <= data.length; i ++) {
			var timedata = data.substr(i, 1);
			timedata = (timedata === '.') ? 1 : (timedata === '_') ? 3 : 0;
			timedata *= unit;
			if (timedata > 0) {
				maketone(timedata);
				time += timedata;
				// tone gap
				time += unit * 1;
			}
		}
		// char gap
		time += unit * 2;
	}

	// generate tone for time
	function maketone(data) {
		var start = time;
		var stop = time + data;
		// filter: envelope the tone slightly
		gain.gain.linearRampToValueAtTime(0, start);
		gain.gain.linearRampToValueAtTime(1, start + (unit / 8));
		gain.gain.linearRampToValueAtTime(1, stop - (unit / 16));
		gain.gain.linearRampToValueAtTime(0, stop);
	}

	// create: oscillator, gain, destination
	var osci = cont.createOscillator();
	osci.frequency.value = freq;
	var gain = cont.createGainNode();
	gain.gain.value = 0;
	var dest = cont.destination;
	// connect: oscillator -> gain -> destination
	osci.connect(gain);
	gain.connect(dest);
	// start oscillator
	osci.start(time);

	// begin encoding: text -> code -> time -> tone
	makecode(text);

	// return web audio context for reuse / control
	return cont;
}

morsecode('Hello World');

The code translates a given string into Morse code, handles unknown characters, and outputs the Morse code as audible tones through an audio device using the Web Audio API. It is divided into three modules: character to Morse code translation, Morse code timing creation, and tone generation based on the timings.


var blocks = "BO XK DQ CP NA GT RE TG QD FS JW HU VI AN OB ER FS LY PC ZM";

function CheckWord(blocks, word) {
   // Makes sure that word only contains letters.
   if(word !== /([a-z]*)/i.exec(word)[1]) return false;
   // Loops through each character to see if a block exists.
   for(var i = 0; i < word.length; ++i)
   {
      // Gets the ith character.
      var letter = word.charAt(i);
      // Stores the length of the blocks to determine if a block was removed.
      var length = blocks.length;
      // The regexp gets constructed by eval to allow more browsers to use the function.
      var reg = eval("/([a-z]"+letter+"|"+letter+"[a-z])/i");
      // This does the same as above, but some browsers do not support...
      //var reg = new RegExp("([a-z]"+letter+"|"+letter+"[a-z])", "i");
      // Removes all occurrences of the match.
      blocks = blocks.replace(reg, "");
      // If the length did not change then a block did not exist.
      if(blocks.length === length) return false;
   }
   // If every character has passed then return true.
   return true;
};

var words = [
   "A",
   "BARK",
   "BOOK",
   "TREAT",
   "COMMON",
   "SQUAD",
   "CONFUSE"
];

for(var i = 0;i<words.length;++i)
   console.log(words[i] + ": " + CheckWord(blocks, words[i]));

A: true
BARK: true
BOOK: false
TREAT: true
COMMON: false
SQUAD: true
CONFUSE: true

(function (strWords) {

    var strBlocks =
        'BO XK DQ CP NA GT RE TG QD FS JW HU VI AN OB ER FS LY PC ZM',
        blocks = strBlocks.split(' ');

    function abc(lstBlocks, strWord) {
        var lngChars = strWord.length;

        if (!lngChars) return [];

        var b = lstBlocks[0],
            c = strWord[0];

        return chain(lstBlocks, function (b) {
            return (b.indexOf(c.toUpperCase()) !== -1) ? [
                (b + ' ').concat(
                    abc(removed(b, lstBlocks), strWord.slice(1)))
            ] : [];
        })
    }

    // Monadic bind (chain) for lists
    function chain(xs, f) {
        return [].concat.apply([], xs.map(f));
    }

    // a -> [a] -> [a]
    function removed(x, xs) {
        var h = xs.length ? xs[0] : null,
            t = h ? xs.slice(1) : [];

        return h ? (
            h === x ? t : [h].concat(removed(x, t))
        ) : [];
    }

    function solution(strWord) {
        var strAttempt = abc(blocks, strWord)[0].split(',')[0];

        // two chars per block plus one space -> 3
        return strWord + ((strAttempt.length === strWord.length * 3) ?
            ' -> ' + strAttempt : ': [no solution]');
    }

    return strWords.split(' ').map(solution).join('\n');

})('A bark BooK TReAT COMMON squAD conFUSE');

The code defines a function that determines if a given word can be spelled using a specific collection of ABC blocks. Each block contains two letters and can only be used once. The function is case-insensitive. It also includes examples of the function's usage with seven different words. The method utilizes regular expressions and the string replace function for better compatibility with older browsers.


for (var n = 0; n < 1e14; n++) { // arbitrary limit that's not too big
    document.writeln(n.toString(8)); // not sure what's the best way to output it in JavaScript
}

generate a sequential count in octal, starting from zero and incrementing by one on each line until the program is terminated or the maximum numeric type value is reached.


function swap(arr) {
  var tmp = arr[0];
  arr[0] = arr[1];
  arr[1] = tmp;
}

function swap(aName, bName) {
  eval('(function(){ arguments[0] = aName; aName = bName; bName = arguments[0] })()'
    .replace(/aName/g, aName)
    .replace(/bName/g, bName)
  )
}
var x = 1
var y = 2
swap('x', 'y')

function swap(a, b) {
  var tmp = window[a];
  window[a] = window[b];
  window[b] = tmp;
}
var x = 1;
var y = 2;
swap('x', 'y');

const arr = [1, 2, 3, 4, 5];
[arr[0], arr[1]] = [arr[1], arr[0]]

implement a generic swap function or operator that can exchange the values of two variables or storage places, regardless of their types. In statically typed languages, the function describes how the language provides genericity. The variables should have a mutually compatible type to avoid type violation. The function also addresses issues in programming language semantics, including difficulties in generic programming and destructive operations. In JavaScript, the function can swap values by wrapping the variables in an object or array. It also provides a metaprogramming solution using code generation and eval. The function can also swap array items using destructing assignment.


function isPalindrome(str) {
  return str === str.split("").reverse().join("");
}

console.log(isPalindrome("ingirumimusnocteetconsumimurigni"));

var isPal = str => str === str.split("").reverse().join("");

(() => {

    // isPalindrome :: String -> Bool
    const isPalindrome = s => {
        const cs = filter(c => ' ' !== c, s.toLocaleLowerCase());
        return cs.join('') === reverse(cs).join('');
    };

    // TEST -----------------------------------------------
    const main = () =>
        isPalindrome(
            'In girum imus nocte et consumimur igni'
        )

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

    // filter :: (a -> Bool) -> [a] -> [a]
    const filter = (f, xs) => (
        'string' !== typeof xs ? (
            xs
        ) : xs.split('')
    ).filter(f);

    // reverse :: [a] -> [a]
    const reverse = xs =>
        'string' !== typeof xs ? (
            xs.slice(0).reverse()
        ) : xs.split('').reverse().join('');

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

implement a function to check if a given sequence of characters is a palindrome. It supports Unicode characters and also detects inexact palindromes by ignoring white-space, punctuation, and case sensitivity. The function may also reverse a string and be used to test other functions.


Works with: JScript
var shell = new ActiveXObject("WScript.Shell");
var env = shell.Environment("PROCESS");
WScript.echo('SYSTEMROOT=' + env.item('SYSTEMROOT'));

demonstrate how to access a process's environment variables such as PATH, HOME, or USER in a Unix system using JavaScript, relying on the host environment for access.


/**
 * @param {bigint} n
 * @param {bigint} x
 * @param {bigint} y
 * @returns {bigint}
 */
function F(n, x, y) {
  if (n === 0) {
    return x + y;
  }

  if (y === 0) {
    return x;
  }

  return F(n - 1, F(n, x, y - 1), F(n, x, y - 1) + y);
}

Implement the Sudan function, a non-primitive recursive function. The function takes two arguments, x and y, and returns a value based on the defined recursive rules.


% push( ELEMENT, STACK, NEW )
% True if NEW is [ELEMENT|STACK]
push(ELEMENT,STACK,[ELEMENT|STACK]).

% pop( STACK, TOP, NEW )
% True if TOP and NEW are head and tail, respectively, of STACK
pop([TOP|STACK],TOP,STACK).

% empty( STACK )
% True if STACK is empty
empty([]).

implement a stack with basic operations such as push, pop, and empty. The stack follows a last in, first out (LIFO) access policy. The topmost element can be accessed without modifying the stack. The stack can be used for resource management, implementing local variables in recursive subprograms, and in various algorithms.


The code generates the nth Fibonacci number using either an iterative or recursive approach. It optionally supports negative numbers by inversely applying the Fibonacci formula. The code also implements a time/space tradeoff to improve performance for larger values of N by storing interim N/Value pairs for quicker future use. It also includes a generator function that can generate all Fibonacci numbers in sequence without requiring any bound input variables.


The code selects specific elements from an array to create a new array in a generic manner. It specifically filters out all even numbers from an array. Optionally, it can also modify the original array instead of creating a new one. The code is compatible with SWI-Prolog and the lambda module by Ulrich Neumerkel.


Works with: SWI Prolog version 7
substring_task(Str, N, M, Char, SubStr) :-
    sub_string(Str, N, M, _, Span),
    sub_string(Str, N, _, 0, ToEnd),
    sub_string(Str, 0, _, 1, MinusLast),
    string_from_substring_to_m(Str, Char, M, FromCharToMth),
    string_from_substring_to_m(Str, SubStr, M, FromSubToM),
    maplist( writeln,
            [ 'from n to m ':Span,
              'from n to end ': ToEnd,
              'string minus last char ': MinusLast,
              'form known char to m ': FromCharToMth,
              'from known substring to m ': FromSubToM ]).

string_from_substring_to_m(String, Sub, M, FromSubToM) :-
    sub_string(String, Before, _, _, Sub),
    sub_string(String, Before, M, _, FromSubToM).

?- substring_task("abcdefghijk", 2, 4, "d", "ef").
from n to m :cdef
from n to end :cdefghijk
string minus last char :abcdefghij
form known char to m :defg
from known substring to m :efgh
true

The code extracts substrings from a given string in various ways: starting from a specified character index and of a certain length, starting from a specified character index to the end of the string, excluding the last character of the string, starting from a known character or substring within the string and of a specified length. The code supports any valid Unicode code point and works with logical characters, not 8-bit or 16-bit code units. It is not designed to handle all Unicode characters for other encodings like 8-bit ASCII or EUC-JP.


Works with: SWI Prolog
reverse("abcd", L), string_to_list(S,L).

The code takes an input string and reverses its characters. It also ensures the preservation of Unicode combining characters during the reversal process. For instance, "asdf" is reversed to "fdsa" and "as⃝df̅" is reversed to "f̅ds⃝a". The main functionality is encapsulated in the reverse/2 predicate.


    rpath([target|reversed_path], distance)

   - arbitrarily selects a node (Qi) neighboring origin (o), and for that node
   - if o->Qi is the shortest known path:
       - update path and distance
       - traverse Qi
   - if o->Qi is not the shortest, select the next node.

   - We use this list to ensure that we do not loop endlessly.
   - This path is recorded as the shortest if the distance is indeed shorter than a known path.
   - Leaf nodes in the traversal tree are processed completely before the origin node processing
     is completed.
     - This implies that the first stage in our algorithm involves allocating each node
       in the traversal tree a path and 'shortest known distance from origin' value.
     - ...Which is arguably better than assigning an initial 'infinite distance' value.

%___________________________________________________________________________

:-dynamic
	rpath/2.      % A reversed path

edge(a,b,7).
edge(a,c,9).
edge(b,c,10).
edge(b,d,15).
edge(c,d,11).
edge(d,e,6).
edge(a,f,14).
edge(c,f,2).
edge(e,f,9).

path(From,To,Dist) :- edge(To,From,Dist).
path(From,To,Dist) :- edge(From,To,Dist).

shorterPath([H|Path], Dist) :-		       % path < stored path? replace it
	rpath([H|T], D), !, Dist < D,          % match target node [H|_]
	retract(rpath([H|_],_)),
	writef('%w is closer than %w\n', [[H|Path], [H|T]]),
	assert(rpath([H|Path], Dist)).
shorterPath(Path, Dist) :-		       % Otherwise store a new path
	writef('New path:%w\n', [Path]),
	assert(rpath(Path,Dist)).

traverse(From, Path, Dist) :-		    % traverse all reachable nodes
	path(From, T, D),		    % For each neighbor
	not(memberchk(T, Path)),	    %	which is unvisited
	shorterPath([T,From|Path], Dist+D), %	Update shortest path and distance
	traverse(T,[From|Path],Dist+D).	    %	Then traverse the neighbor

traverse(From) :-
	retractall(rpath(_,_)),           % Remove solutions
	traverse(From,[],0).              % Traverse from origin
traverse(_).

go(From, To) :-
	traverse(From),                   % Find all distances
	rpath([To|RPath], Dist)->         % If the target was reached
	  reverse([To|RPath], Path),      % Report the path and distance
	  Distance is round(Dist),
	  writef('Shortest path is %w with distance %w = %w\n',
	       [Path, Dist, Distance]);
	writef('There is no route from %w to %w\n', [From, To]).

?- go(a,e).
New path:[b,a]
New path:[c,b,a]
New path:[d,c,b,a]
New path:[e,d,c,b,a]
New path:[f,e,d,c,b,a]
[f,c,b,a] is closer than [f,e,d,c,b,a]
[e,f,c,b,a] is closer than [e,d,c,b,a]
[d,b,a] is closer than [d,c,b,a]
[c,a] is closer than [c,b,a]
[d,c,a] is closer than [d,b,a]
[e,d,c,a] is closer than [e,f,c,b,a]
[f,c,a] is closer than [f,c,b,a]
[e,f,c,a] is closer than [e,d,c,a]
Shortest path is [a,c,f,e] with distance 0+9+2+9 = 20
true.

implement Dijkstra's algorithm for finding the shortest path in a graph with non-negative edge path costs. The algorithm takes a directed and weighted graph, represented by an adjacency matrix or list and a start node, as input. It outputs a set of edges depicting the shortest path to each reachable node from the start node. The code also includes functionality to interpret the output and display the shortest path from the start node to specified nodes.


mersenne_factor(P, F) :-
    prime(P),
    once((
        between(1, 100_000, K),  % Fail if we can't find a small factor
        Q is 2*K*P + 1,
        test_factor(Q, P, F))).

test_factor(Q, P, prime) :- Q*Q > (1 << P - 1), !.
test_factor(Q, P, Q) :-
    R is Q /\ 7, member(R, [1, 7]),
    prime(Q),
    powm(2, P, Q) =:= 1.

wheel235(L) :-
   W = [4, 2, 4, 2, 4, 6, 2, 6 | W],
   L = [1, 2, 2 | W].

prime(N) :-
   N >= 2,
   wheel235(W),
   prime(N, 2, W).

prime(N, D, _) :- D*D > N, !.
prime(N, D, [A|As]) :-
    N mod D =\= 0,
    D2 is D + A, prime(N, D2, As).

implement a method to find a factor of a Mersenne number (in this case, M929). The method uses efficient algorithms to determine if a number divides 2P-1, including a self-implemented modPow operation. It also incorporates properties of Mersenne numbers to refine the process, such as the form of any factor q of 2P-1 and the conditions that q must meet. The method stops when 2kP+1 > sqrt(N). It only works on Mersenne numbers where P is prime.


:- use_module(library(lists)).

set :-
	A = [2, 4, 1, 3],
	B = [5, 2, 3, 2],
	(   is_set(A) -> format('~w is a set~n', [A])
	;   format('~w is not a set~n', [A])),
	(   is_set(B) -> format('~w is a set~n', [B])
	;   format('~w is not a set~n', [B])),

	% create a set from a list

	list_to_set(B, BS),
	(   is_set(BS) -> format('~nCreate a set from a list~n~w is a set~n', [BS])
	;   format('~w is not a set~n', [BS])),

	intersection(A, BS, I),
	format('~n~w intersection ~w => ~w~n', [A, BS, I]),
	union(A, BS, U),
	format('~w union ~w => ~w~n', [A, BS, U]),
	difference(A, BS, D),
	format('~w difference ~w => ~w~n', [A, BS, D]),

	X = [1,2],
	(   subset(X, A) -> format('~n~w is a subset of ~w~n', [X, A])
	;   format('~w is not a subset of ~w~n', [X, A])),
	Y = [1,5],
	(   subset(Y, A) -> format('~w is a subset of ~w~n', [Y, A])
	;   format('~w is not a subset of ~w~n', [Y, A])),
	Z = [1, 2, 3, 4],
	(  equal(Z, A) -> format('~n~w is equal to ~w~n', [Z, A])
	;   format('~w is not equal to ~w~n', [Z, A])),
	T = [1, 2, 3],
	(  equal(T, A) -> format('~w is equal to ~w~n', [T, A])
	;   format('~w is not equal to ~w~n', [T, A])).

% compute difference of sets
difference(A, B, D) :-
	exclude(member_(B), A, D).

member_(L, X) :-
	member(X, L).

equal([], []).
equal([H1 | T1], B) :-
	select(H1, B, B1),
	equal(T1, B1).

The code demonstrates various set operations such as set creation, checking if an element belongs to a set, union, intersection, difference, subset, and equality of two sets. It also optionally shows other set operations and modifications on a mutable set. The set is implemented using an associative array, binary search tree, hash table, or binary bits. The code works with SWI-Prolog's standard library ordsets, which treats sets as ordered lists of unique elements.


main() :-
    christmas_days_falling_on_sunday(2011, 2121, SundayList),
    writeln(SundayList).

christmas_days_falling_on_sunday(StartYear, EndYear, SundayList) :-
    numlist(StartYear, EndYear, YearRangeList),
    include(is_christmas_day_a_sunday, YearRangeList, SundayList).

is_christmas_day_a_sunday(Year) :-
    Date = date(Year, 12, 25),
    day_of_the_week(Date, DayOfTheWeek),
    DayOfTheWeek == 7.

The code determines the years between 2008 and 2121 where Christmas (25th December) falls on a Sunday by using standard date handling libraries. It also compares the calculated dates with the outputs of other languages to identify any discrepancies due to issues like overflow in date/time representation similar to y2k problems. The code is compatible with SWI-Prolog.


uniq(Data,Uniques) :- sort(Data,Uniques).

?- uniq([1, 2, 3, 2, 3, 4],Xs).
Xs = [1, 2, 3, 4]

member1(X,[H|_]) :- X==H,!.
member1(X,[_|T]) :- member1(X,T).

distinct([],[]).
distinct([H|T],C) :- member1(H,T),!, distinct(T,C).
distinct([H|T],[H|C]) :- distinct(T,C).

?- distinct([A, A, 1, 2, 3, 2, 3, 4],Xs).
Xs = [A, 1, 2, 3, 4]

"Implement a function to remove duplicate elements from an array. This can be achieved through three approaches: 1) Using a hash table to eliminate duplicates with a complexity of O(n) on average and O(n2) in the worst case. 2) Sorting the elements and removing consecutive duplicates with a complexity of O(n log n). 3) Iterating through the list, checking for duplicate elements and discarding them with a complexity of O(n2)."


qsort( [], [] ).
qsort( [H|U], S ) :- splitBy(H, U, L, R), qsort(L, SL), qsort(R, SR), append(SL, [H|SR], S).

% splitBy( H, U, LS, RS )
% True if LS = { L in U | L <= H }; RS = { R in U | R > H }
splitBy( _, [], [], []).
splitBy( H, [U|T], [U|LS], RS ) :- U =< H, splitBy(H, T, LS, RS).
splitBy( H, [U|T], LS, [U|RS] ) :- U  > H, splitBy(H, T, LS, RS).

implement the Quicksort algorithm to sort an array or list of elements. The algorithm works by choosing a pivot element and dividing the rest of the elements into two partitions - one with elements less than the pivot and the other with elements greater than the pivot. It then recursively sorts these partitions and joins them with the pivot to get the sorted array. The codes also include an optimized version of Quicksort that works in place by swapping elements within the array to avoid memory allocation of more arrays. The pivot selection method is not specified.


Works with: SWI-Prolog version 6
display_date :-
    get_time(Time),
    format_time(atom(Short), '%Y-%M-%d',      Time),
    format_time(atom(Long),  '%A, %B %d, %Y', Time),
    format('~w~n~w~n', [Short, Long]).

display the current date in two formats: "2007-11-23" and "Friday, November 23, 2007".


powerset(X,Y) :- bagof( S, subseq(S,X), Y).

subseq( [], []).
subseq( [], [_|_]).
subseq( [X|Xs], [X|Ys] ) :- subseq(Xs, Ys).
subseq( [X|Xs], [_|Ys] ) :- append(_, [X|Zs], Ys), subseq(Xs, Zs).

The code implements a function that takes a set S as input and generates the power set of S. It uses either a built-in set type or a custom-defined set type with necessary operations. The power set includes all subsets of the original set, including the empty set and the set itself. The code also demonstrates the handling of edge cases, such as the power set of an empty set and the power set of a set containing only the empty set. It uses the predicate powerset(X,Y) to represent "Y is the power set of X" and subseq(X,Y) to check if X is a subsequence of Y. The implementation is efficient and logical.


The code defines a function that takes a positive integer as an input and returns its equivalent in Roman numerals. It handles each digit separately, starting from the leftmost digit and ignoring zeroes. It also ensures compatibility with both Roman to Arabic and Arabic to Roman conversions using the clpfd library.


Works with: SWI Prolog

singleassignment:-
    functor(Array,array,100), % create a term with 100 free Variables as arguments
                              % index of arguments start at 1
    arg(1 ,Array,a),          % put an a at position 1
    arg(12,Array,b),          % put an b at position 12
    arg(1 ,Array,Value1),     % get the value at position 1
    print(Value1),nl,         % will print Value1 and therefore a followed by a newline
    arg(4 ,Array,Value2),     % get the value at position 4 which is a free Variable
    print(Value2),nl.         % will print that it is a free Variable followed by a newline

destructive:-
    functor(Array,array,100), % create a term with 100 free Variables as arguments
                              % index of arguments start at 1
    setarg(1 ,Array,a),       % put an a at position 1
    setarg(12,Array,b),       % put an b at position 12
    setarg(1, Array,c),       % overwrite value at position 1 with c
    arg(1 ,Array,Value1),     % get the value at position 1
    print(Value1),nl.         % will print Value1 and therefore c followed by a newline

listvariant:-
    length(List,100),          % create a list of length 100
    nth1(1 ,List,a),           % put an a at position 1 , nth1/3 uses indexing from 1, nth0/3 from 0
    nth1(12,List,b),           % put an b at position 3
    append(List,[d],List2),    % append an d at the end , List2 has 101 elements
    length(Add,10),            % create a new list of length 10
    append(List2,Add,List3),   % append 10 free variables to List2 , List3 now has 111 elements
    nth1(1 ,List3,Value),      % get the value at position 1
    print(Value),nl.           % will print out a

demonstrate the basic syntax of arrays in the given programming language. The codes create an array, assign a value to it, and retrieve an element from it. The codes also showcase the use of both fixed-length and dynamic arrays, including the process of pushing a value into the array. The codes further illustrate the use of Prolog Terms as array structures, utilizing functor/3 for array creation and arg/3 for nondestructive retrieval and setting of elements. Additionally, setarg/3 is used for destructive setting of an array element, mimicking the common practice in most other programming languages. The codes also demonstrate the use of lists as arrays.


% main predicate, find and print closest point
do_find_closest_points(Points) :-
	points_closest(Points, points(point(X1,Y1),point(X2,Y2),Dist)),
	format('Point 1 : (~p, ~p)~n', [X1,Y1]),
	format('Point 1 : (~p, ~p)~n', [X2,Y2]),
	format('Distance: ~p~n', [Dist]).

% Find the distance between two points
distance(point(X1,Y1), point(X2,Y2), points(point(X1,Y1),point(X2,Y2),Dist)) :-
	Dx is X2 - X1,
	Dy is Y2 - Y1,
	Dist is sqrt(Dx * Dx + Dy * Dy).

% find the closest point that relatest to another point
point_closest(Points, Point, Closest) :-
	select(Point, Points, Remaining),
	maplist(distance(Point), Remaining, PointList),
	foldl(closest, PointList, 0, Closest).

% find the closest point/dist pair for all points
points_closest(Points, Closest) :-
	maplist(point_closest(Points), Points, ClosestPerPoint),
	foldl(closest, ClosestPerPoint, 0, Closest).

% used by foldl to get the lowest point/distance combination
closest(points(P1,P2,Dist), 0, points(P1,P2,Dist)).
closest(points(_,_,Dist), points(P1,P2,Dist2), points(P1,P2,Dist2)) :-
	Dist2 < Dist.
closest(points(P1,P2,Dist), points(_,_,Dist2), points(P1,P2,Dist)) :-
	Dist =< Dist2.

do_find_closest_points([
    point(0.654682, 0.925557),
    point(0.409382, 0.619391),
    point(0.891663, 0.888594),
    point(0.716629, 0.996200),
    point(0.477721, 0.946355),
    point(0.925092, 0.818220),
    point(0.624291, 0.142924),
    point(0.211332, 0.221507),
    point(0.293786, 0.691701),
    point(0.839186, 0.728260)
]).

The code provides two solutions to the closest pair of points problem in a two-dimensional plane. The first solution uses a brute-force algorithm with a time complexity of O(n^2) to find the two points with the minimum distance between them. The second solution uses a recursive divide and conquer approach with a time complexity of O(n log n) to find the closest pair of points. The points are sorted by their x and y coordinates in ascending order. The code is tested with a list of points in SWI-Prolog.


% create a list
L = [a,b,c,d],

% prepend to the list
L2 = [before_a|L],

% append to the list
append(L2, ['Hello'], L3),

% delete from list
exclude(=(b), L3, L4).

L = [a, b, c, d],
L2 = [before_a, a, b, c, d],
L3 = [before_a, a, b, c, d, 'Hello'],
L4 = [before_a, a, c, d, 'Hello'].

% create an empty dict call 'point'
D1 = point{},

% add a value
D2 = D1.put(x, 20).put(y, 30).put(z, 20),

% update a value
D3 = D2.put([x=25]),

% remove a value
del_dict(z, D3, _, D4),

% access a value randomly
format('x = ~w, y = ~w~n', [D4.x, D4.y]).

x = 25, y = 30
D1 = point{},
D2 = point{x:20, y:30, z:20},
D3 = point{x:25, y:30, z:20},
D4 = point{x:25, y:30}.

create a collection and add a few values to it. The code also demonstrates how to use different types of collections in statically-typed languages. It also includes examples of using Dicts in SWI-Prolog, which can be accessed, added, and removed in an immutable way.


:- use_module(library(simplex)).

% tuples (name, Explantion, Value, weights, volume).
knapsack :-
	L =[(	panacea, 'Incredible healing properties', 3000,	0.3,	0.025),
	    (	ichor,   'Vampires blood',                1800,	0.2,	0.015),
	    (	gold ,	 'Shiney shiney',	          2500,	2.0,	0.002)],

	 gen_state(S0),
	 length(L, N),
	 numlist(1, N, LN),

	 % to get statistics
	 time((create_constraint_N(LN, L, S0, S1, [], LVa, [], LW, [], LVo),
	       constraint(LW =< 25.0, S1, S2),
	       constraint(LVo =< 0.25, S2, S3),
	       maximize(LVa, S3, S4)
	      )),

	% we display the results
	compute_lenword(L, 0, Len),
	sformat(A0, '~~w~~t~~~w|', [3]),
	sformat(A1, '~~w~~t~~~w|', [Len]),
	sformat(A2, '~~t~~w~~~w|', [10]),
	sformat(A3, '~~t~~2f~~~w|', [10]),
	sformat(A4, '~~t~~3f~~~w|', [10]),
	sformat(A33, '~~t~~w~~~w|', [10]),
	sformat(A44, '~~t~~w~~~w|', [10]),

	sformat(W0, A0, ['Nb']),
	sformat(W1, A1, ['Items']),
	sformat(W2, A2, ['Value']),
	sformat(W3, A33, ['Weigth']),
	sformat(W4, A44, ['Volume']),
	format('~w~w~w~w~w~n', [W0, W1,W2,W3,W4]),

	print_results(S4, A0, A1, A2, A3, A4, L, LN, 0, 0, 0).

create_constraint_N([], [], S, S, LVa, LVa, LW, LW, LVo, LVo).

create_constraint_N([HN|TN], [(_, _,Va, W, Vo) | TL], S1, SF, LVa, LVaF, LW, LWF, LVo, LVoF) :-
	constraint(integral(x(HN)), S1, S2),
	constraint([x(HN)] >= 0, S2, S3),
	create_constraint_N(TN, TL, S3, SF,
			    [Va * x(HN) | LVa], LVaF,
			    [W * x(HN) | LW], LWF,
			    [Vo * x(HN) | LVo], LVoF).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
compute_lenword([], N, N).
compute_lenword([(Name, _, _, _, _)|T], N, NF):-
	atom_length(Name, L),
	(   L > N -> N1 = L; N1 = N),
	compute_lenword(T, N1, NF).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
print_results(_S, A0, A1, A2, A3, A4, [], [], VaM, WM, VoM) :-
	sformat(W0, A0, [' ']),
	sformat(W1, A1, [' ']),
	sformat(W2, A2, [VaM]),
	sformat(W3, A3, [WM]),
	sformat(W4, A4, [VoM]),
	format('~w~w~w~w~w~n', [W0, W1,W2,W3,W4]).

print_results(S, A0, A1, A2, A3, A4, [(Name, _, Va, W, Vo)|T], [N|TN], Va1, W1, Vo1) :-
	variable_value(S, x(N), X),
	(   X = 0 -> Va1 = Va2, W1 = W2, Vo1 = Vo2
	;
	    sformat(S0, A0, [X]),
	    sformat(S1, A1, [Name]),
	    Vatemp is X * Va,
	    Wtemp is X * W,
	    Votemp is X * Vo,
	    sformat(S2, A2, [Vatemp]),
	    sformat(S3, A3, [Wtemp]),
	    sformat(S4, A4, [Votemp]),
	    format('~w~w~w~w~w~n', [S0,S1,S2,S3,S4]),
	    Va2 is Va1 + Vatemp,
	    W2 is W1 + Wtemp,
	    Vo2 is Vo1 + Votemp ),
	print_results(S, A0, A1, A2, A3, A4, T, TN, Va2, W2, Vo2).

 ?- knapsack.
% 145,319 inferences, 0.078 CPU in 0.079 seconds (99% CPU, 1860083 Lips)
Nb Items       Value    Weigth    Volume
15 ichor       27000      3.00     0.225
11 gold        27500     22.00     0.022
               54500     25.00     0.247
true

determine the maximum value of items a traveler can carry in his knapsack, given the weight and volume constraints, and the value, weight, and volume of each item. The solution provides one of the four possible combinations that yield the maximum value.


example :-
  between(1,10,Val), write(Val), Val<10, write(', '), fail.
example.
?- example.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
true.

The code writes a comma-separated list from 1 to 10, using separate output statements for the number and the comma within a loop. The loop executes a partial body in its last iteration.


:- system:set_prolog_flag(double_quotes,codes) .

:- [library(lists)] .

%!  starts_with(FIRSTz,SECONDz)
%
% True if `SECONDz` is the beginning of `FIRSTz` .

starts_with(FIRSTz,SECONDz)
:-
lists:append(SECONDz,_,FIRSTz)
.

%!  contains(FIRSTz,SECONDz)
%
% True once if `SECONDz` is contained within `FIRSTz` at one or more positions .

contains(FIRSTz,SECONDz)
:-
contains(FIRSTz,SECONDz,_) ,
!
.

%!  contains(FIRSTz,SECONDz,NTH1)
%
% True if `SECONDz` is contained within `FIRSTz` at position `NTH1` .

contains(FIRSTz,SECONDz,NTH1)
:-
lists:append([PREFIXz,SECONDz,_SUFFIXz_],FIRSTz) ,
prolog:length(PREFIXz,NTH0) ,
NTH1 is NTH0 + 1
.

%!  ends_with(FIRSTz,SECONDz)
%
% True if `SECONDz` is the ending of `FIRSTz` .

ends_with(FIRSTz,SECONDz)
:-
lists:append(_,SECONDz,FIRSTz)
.

The code checks if a given string starts with, contains, or ends with a second string. It also prints the location of the match and handles multiple occurrences of the second string within the first string.


The code solves a puzzle where seven variables (a, b, c, d, e, f, g) are replaced with decimal digits ranging from a lower limit (LOW) to an upper limit (HIGH). The goal is to find the values of these variables such that the sum of the variables in each of the four squares is equal. The code provides all unique solutions for ranges 1-7 and 3-9, and the total number of solutions (including non-unique) for the range 0-9.


show :-
    Data = [100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000],
    forall(
        member(Max, Data),
        (count_triples(Max, Total, Prim),
         format("upto ~D, there are ~D Pythagorean triples (~D primitive.)~n", [Max, Total, Prim]))).

div(A, B, C) :- C is A div B.

count_triples(Max, Total, Prims) :-
    findall(S, (triple(Max, A, B, C), S is A + B + C), Ps),
    length(Ps, Prims),
    maplist(div(Max), Ps, Counts), sumlist(Counts, Total).

% - between_by/4

between_by(A, B, N, K) :-
    C is (B - A) div N,
    between(0, C, J),
    K is N*J + A.

% - Pythagorean triple generator

triple(P, A, B, C) :-
    Max is floor(sqrt(P/2)) - 1,
    between(0, Max, M),
    Start is (M /\ 1) + 1, succ(Pm, M),
    between_by(Start, Pm, 2, N),
    gcd(M, N) =:= 1,
    X is M*M - N*N,
    Y is 2*M*N,
    C is M*M + N*N,
    order2(X, Y, A, B),
    (A + B + C) =< P.

order2(A, B, A, B) :- A < B, !.
order2(A, B, B, A).

The code calculates the number of Pythagorean triples (a, b, c) where a, b, and c are positive integers, a < b < c, and a^2 + b^2 = c^2, with a perimeter (a + b + c) no larger than 100. It also determines the number of these triples that are primitive, meaning a, b, and c are co-prime. The code is also optimized to handle large values up to a maximum perimeter of 100,000,000.


?- new(D, window('Prolog Window')), send(D, open).

Creates an empty GUI window using SWI-Prolog's graphic interface XPCE, which can respond to close requests.


frequency(File) :-
	read_file_to_codes(File, Code, []),

	% we only keep alphabetic codes
	include(my_code_type, Code, LstCharCode),

	% we translate char_codes into uppercase atoms.
	maplist(my_upcase, LstCharCode, LstChar),

	% sort and pack the list
	msort(LstChar, SortLstChar),
	packList(SortLstChar, Freq),
	maplist(my_write, Freq).

my_write([Num, Atom]) :-
	swritef(A, '%3r', [Num]),
	writef('Number of %w :%w\n', [Atom, A]).

my_code_type(Code) :-
	code_type(Code, alpha).

my_upcase(CharCode, UpChar) :-
	char_code(Atom, CharCode),
	upcase_atom(Atom, UpChar).

:- use_module(library(clpfd)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ?- packList([a,a,a,b,c,c,c,d,d,e], L).
%  L = [[3,a],[1,b],[3,c],[2,d],[1,e]] .
%
% ?- packList(R,  [[3,a],[1,b],[3,c],[2,d],[1,e]]).
% R = [a,a,a,b,c,c,c,d,d,e] .
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
packList([],[]).

packList([X],[[1,X]]) :-
	!.

packList([X|Rest],[XRun|Packed]):-
	run(X,Rest, XRun,RRest),
	packList(RRest,Packed).

run(Var,[],[1,Var],[]).

run(Var,[Var|LRest],[N1, Var],RRest):-
	N #> 0,
	N1 #= N + 1,
	run(Var,LRest,[N, Var],RRest).

run(Var,[Other|RRest], [1,Var],[Other|RRest]):-
	dif(Var,Other).

The code opens a text file and counts the frequency of each letter, only considering alphabetic codes in uppercase. It uses the packlist/2 function for run-length encoding. It may also count all characters, including punctuation. The code is compatible with SWI-Prolog.


fractal :-
	new(D, window('Fractal')),
	send(D, size, size(800, 600)),
	drawTree(D, 400, 500, -90, 9),
	send(D, open).

drawTree(_D, _X, _Y, _Angle, 0).

drawTree(D, X1, Y1, Angle, Depth) :-
        X2 is X1 + cos(Angle * pi / 180.0) * Depth * 10.0,
        Y2 is Y1 + sin(Angle * pi / 180.0) * Depth * 10.0,
	new(Line, line(X1, Y1, X2, Y2, none)),
	send(D, display, Line),
	A1 is Angle - 30,
	A2 is Angle + 30,
	De is Depth - 1,
        drawTree(D, X2, Y2, A1, De),
        drawTree(D, X2, Y2, A2, De).

The code generates and draws a fractal tree using SWI-Prolog's graphic interface, XPCE. It begins by drawing the trunk, then splits the end of the trunk at a certain angle to create two branches. This process is repeated at the end of each branch until a desired level of branching is achieved.


brute_force_factors( N , Fs ) :-
  integer(N) ,
  N > 0 ,
  setof( F , ( between(1,N,F) , N mod F =:= 0 ) , Fs )
  .

smart_factors(N,Fs) :-
  integer(N) ,
  N > 0 ,
  setof( F , factor(N,F) , Fs )
  .

factor(N,F) :-
  L is floor(sqrt(N)) ,
  between(1,L,X) ,
  0 =:= N mod X ,
  ( F = X ; F is N // X )
  .

between(X,Y,Z) :-
  integer(X) ,
  integer(Y) ,
  X =< Z ,
  between1(X,Y,Z)
  .

between1(X,Y,X) :-
  X =< Y
  .
between1(X,Y,Z) :-
  X < Y ,
  X1 is X+1 ,
  between1(X1,Y,Z)
  .

calculate the factors of a positive integer, excluding zero and negative integers. The factors are the positive integers that can divide the given number to yield a positive integer result. For prime numbers, the factors are 1 and the number itself. The code implementation uses a simple brute force method and a slightly smarter method. Some Prolog versions may require between/3.


aligner :-
	L ="Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.",

	% read the lines and the words
	% compute the length of the longuest word.
	% LP is the list of lines,
	% each line is a list of words
	parse(L, 0, N, LP, []),

	% we need to add 1 to aligned
	N1 is N+1,
	% words will be left aligned
	sformat(AL, '~~w~~t~~~w|', [N1]),
	% words will be centered
	sformat(AC, '~~t~~w~~t~~~w|', [N1]),
	% words will be right aligned
	sformat(AR, '~~t~~w~~~w|', [N1]),

	write('Left justified :'), nl,
	maplist(affiche(AL), LP), nl,
	write('Centered justified :'), nl,
	maplist(affiche(AC), LP), nl,
	write('Right justified :'), nl,
	maplist(affiche(AR), LP), nl.

affiche(F, L) :-
	maplist(my_format(F), L),
	nl.

my_format(_F, [13]) :-
	nl.

my_format(F, W) :-
	string_to_atom(W,AW),
	sformat(AF, F, [AW]),
	write(AF).

parse([], Max, Max) --> [].

parse(T, N, Max) -->
	{ parse_line(T, 0, N1, T1, L, []),
	  (   N1 > N -> N2 = N1; N2 = N)},
	[L],
	parse(T1, N2, Max).

parse_line([], NF, NF, []) --> [].

parse_line([H|TF], NF, NF, TF) -->
	{code_type(H, end_of_line), !},
	[].

parse_line(T, N, NF, TF) -->
	{ parse_word(T, 0, N1, T1, W, []),
	  (   N1 > N -> N2 = N1; N2 = N)},
	[W],
	parse_line(T1, N2, NF, TF).

% 36 is the code of '$'
parse_word([36|T], N, N, T) -->
	{!},
	[].

parse_word([H|T], N, N, [H|T]) -->
	{code_type(H, end_of_line), !},
	[].

parse_word([], N, N, []) --> [].

parse_word([H|T], N1, NF, TF) -->
	[H],
	{N2 is  N1 + 1},
	parse_word(T, N2, NF, TF).

The code reads a text file where each line's fields are separated by a dollar sign. It aligns each column by ensuring at least one space between words in each column. The words in a column can be left, right, or center justified. The minimum space between columns is calculated from the text, not hard-coded. The code also handles trailing dollar characters and insignificant consecutive spaces at the end of lines. The output is displayed in a mono-spaced font on a plain text editor or terminal.