Skip to content

Instantly share code, notes, and snippets.

@kragen
Created March 1, 2013 01:43
Show Gist options
  • Save kragen/5061821 to your computer and use it in GitHub Desktop.
Save kragen/5061821 to your computer and use it in GitHub Desktop.
<!-- --> <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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment