Created
March 1, 2013 01:43
-
-
Save kragen/5061821 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- --> <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