Created
May 12, 2016 02:54
-
-
Save peisenmann/a578d79957afec0ee110c2dd36e87b9f to your computer and use it in GitHub Desktop.
Revisions
-
peisenmann created this gist
May 12, 2016 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,8 @@ # Pascal's Triangle A blind implementation of Pascal's Triangle without any algorithms or optimization research. Uses ES2015 (ES6) level Javascript. ## Execution Executable in browser or via Node 6+ repl. To run in browser, paste all the code from both `.js` files into the console and remove the `export` keyword Also executable via GistRun at https://gist.run/?id=bed8e0a105f795f99820ba139f034aaa&sha=2ffda6f14e917df89b8dc0b5c4614e7fc4f8c165 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,54 @@ <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Pascal's Triangle</title> <style type="text/css"> .triangle {float: left} .triangleRow {text-align: center;} .triangleItem {display: inline-block; width: 2em; text-align: center;} .clearfix {clear: both;} </style> </head> <body> <h1>Generated on the left, Hard Coded on the right</h1> <script src="pascal.js"></script> <script src="pascal.test.js"></script> <script> /* Super hacky testing for visibility and entertainment */ for (var i = 0; i < knownTriangle.length; i++) { var newPT = pascalsTriangle(i), knownPT = knownTriangle.slice(0,i+1); visualizeTriangles(newPT, knownPT); let hr = document.createElement('hr'); hr.className = 'clearfix'; document.body.appendChild(hr); } function visualizeTriangles(...triangles) { const dce = document.createElement.bind(document); const dctn = document.createTextNode.bind(document); let html = triangles.map(triangle => { let div = dce('div'); div.className = 'triangle'; triangle.forEach(row => { let rowDiv = dce('div'); rowDiv.className = 'triangleRow'; row.forEach(item => { var span = dce('span'); span.className = 'triangleItem'; span.appendChild(dctn(item)); rowDiv.appendChild(span); }); div.appendChild(rowDiv); }); return div; }); html.forEach(document.body.appendChild.bind(document.body)); } </script> </body> </html> 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,28 @@ "use strict"; /** * Produces Pascal's triangle up to the given row number * Example: pascalsTriangle(5) [[1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1], [1,5,10,10,5,1]] * @param {Number} row The highest row returned in the resulting triangle * @returns {Array<Array<Number>>}} The resulting Pascal's triangle */ function pascalsTriangle(row) { // Guard against bad input if (!Number.isInteger(row) || row < 0) { throw new TypeError('row must be a positive integer, but was ' + row); } // Base case let triangle = [[1]]; for (let r = 1; r < row + 1; r++) { triangle.push(triangle[r-1].concat(0).map((term, i, arr) => term + (arr[i-1] || 0))); } return triangle; } 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,77 @@ "use strict"; const knownTriangle = [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1], [1,5,10,10,5,1], [1,6,15,20,15,6,1], [1,7,21,35,35,21,7,1], [1,8,28,56,70,56,28,8,1], [1,9,36,84,126,126,84,36,9,1] ]; /** * * @param {function} pt The given pascalTriangle function to test * @returns {boolean | Array<String>} true if the pt function produces valid outputs, an Array<String> errors if not */ function testPascalsTriangle(pt) { let errors = []; // Iterate over the sizes of the known triangle and ensure that pt(i) equals the known triangle for (let i = 0; i < knownTriangle.length; i++) { let newPT = pt(i), knownPT = knownTriangle.slice(0,i+1); if (!equalTriangles(newPT, knownPT)) { errors.push('Error at pt(' + i + '). Expected\n' + knownPT + '\nbut got\n' + newPT); } } return errors.length ? errors : true; } /** * Compare if all of the given triangles have the same value in the same position * @param {...Array} triangles The triangles to compare * @returns {boolean} true if all triangles are equal, false otherwise */ function equalTriangles(...triangles) { return strictEquals(...[true].concat(...compareTriangles(...triangles))); } /** * Produces a position for position mapping of all triangles where true indicates a same value across all triangles * and false indicates a mismatch or missing value in one or more triangles * @param {...Array<Array<Number>>} triangles Arbitrary number of 2D arrays that represents a pascal's triangle * @return {Array<Array<Number>>} a superpositional 2D array representing the matching parts of the given triangles */ function compareTriangles(...triangles) { // Since we know the exact structure of a triangle is an array of arrays, we can hard code to that level of depth return coiterate(coiterate.bind(null, strictEquals), ...triangles); } /** * Iterate across the given arrays and invoke pred(arr1[0], arr2[0], etc) for each index of the arrays up to the length * of the longest given array * @param pred The predicate to apply * @param {...Array} arrays The arrays to coiterate over * @returns {Array} The result of the predicate applied positionally to each array */ function coiterate(pred, ...arrays) { let maxLength = arrays.reduce((max, arr) => arr && arr.length > max ? arr.length : max, 0); return Array.from(Array(maxLength).keys()).map(i => pred(...arrays.map(arr => arr && arr[i]))); } /** * Given many items as input, return true if all items are strictly equal * @param {...*} items The items to compare * @returns {boolean} true if all items are the same, false otherwise */ function strictEquals(...items) { for (let i = 1; i < items.length; i++) { if (items[i] !== items[i-1]) { return false; } } return true; }