<!-- --> <script>
// Euler problem 1, in APL semantics implemented in JS

// Count zero to n, not including n.
function iota(n) {
    var rv = [];
    for (var ii = 0; ii < n; ii++) rv.push(ii);
    return aplify(rv);
}

// Some basic binary operations.
function add(a, b) { return a + b }
function mod(a, b) { return a % b }
function eq(a, b) { return a === b }
function or(a, b) { return a || b }

// Add aggregate operations to an array.
function aplify(array) {
    array.reduce = apl_reduce;
    array.where = apl_where;
    array.mod = apl_mod;
    array.eq = apl_eq;
    array.or = apl_or;
    return array;
}

// Generalization of sum.  Mostly useful with associative functions.
function apl_reduce(op) {
    if (this.length === 0) return op.identity;
    var rv = this[0];
    for (var ii = 1; ii < this.length; ii++) rv = op(rv, this[ii]);
    return rv;
}

// aka "compress", with the arguments backwards; returns items corresponding to 
true indices.
function apl_where(indices) {
    var rv = aplify([]);
    for (var ii = 0; ii < indices.length; ii++) if (indices[ii]) 
rv.push(this[ii]);
    return rv;
}

// The aggregate functions we're using.
function apl_mod(rand) { return apl_simd(this, mod, rand) }
function apl_eq(rand) { return apl_simd(this, eq, rand) }
function apl_or(rand) { return apl_simd(this, or, rand) }

// Aggregate functions in general.
function apl_simd(left, op, right) {
    var left_scalar = (left.length === undefined);
    var right_scalar = (right.length === undefined);
    if (left_scalar && right_scalar) return op(left, right);

    var length = left_scalar ? right.length : left.length;
    if (!left_scalar && !right_scalar && left.length != right.length) {
        throw new Error("mismatched argument sizes " + left + " : " + right);
    }

    var rv = aplify([]);
    for (var ii = 0; ii < length; ii++) {
        rv.push(op(left_scalar ? left : left[ii],
                   right_scalar ? right : right[ii]));
    }
    return rv;
}

// === End of APL semantics implementation.  Solutions:

// APL way:
var x = iota(1000);
document.write(x.where(x.mod(3).eq(0).or(x.mod(5).eq(0))).reduce(add));

// Conventional imperative way:
var total = 0;
for (var ii = 0; ii < 1000; ii++) if (ii % 3 === 0 || ii % 5 === 0) total += ii;
document.write("\nimperative: " + total);
// </script>
-- 
To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-hacks

Reply via email to