diff --git a/curriculum/challenges/_meta/rosetta-code/meta.json b/curriculum/challenges/_meta/rosetta-code/meta.json index 9e2996f9f2..13f0bb2305 100644 --- a/curriculum/challenges/_meta/rosetta-code/meta.json +++ b/curriculum/challenges/_meta/rosetta-code/meta.json @@ -312,6 +312,38 @@ "5a23c84252665b21eecc7ec5", "Josephus problem" ], + [ + "5a23c84252665b21eecc7ecb", + "K-d tree" + ], + [ + "5a23c84252665b21eecc7eca", + "Kaprekar numbers" + ], + [ + "5a23c84252665b21eecc7ed5", + "Knight's tour" + ], + [ + "5a23c84252665b21eecc7edb", + "Largest int from concatenated ints" + ], + [ + "5a23c84252665b21eecc7edc", + "Last Friday of each month" + ], + [ + "5a23c84252665b21eecc7ede", + "Leap year" + ], + [ + "5a23c84252665b21eecc7edf", + "Least common multiple" + ], + [ + "5a23c84252665b21eecc7ee0", + "Left factorials" + ], [ "59da22823d04c95919d46269", "Sailors, coconuts and a monkey problem" diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/k-d-tree.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/k-d-tree.md new file mode 100644 index 0000000000..64eb7798db --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/k-d-tree.md @@ -0,0 +1,353 @@ +--- +id: 5a23c84252665b21eecc7ecb +title: K-d tree +challengeType: 5 +--- + +## Description +
+A k-d tree (short for k-dimensional tree) is a space-partitioning data structure for organizing points in a k-dimensional space. +k-d trees are a useful data structure for several applications, such as searches involving a multidimensional search key (e.g. range searches and nearest neighbor searches). +k-d trees are a special case of binary space partitioning trees. k-d trees are not suitable, however, for efficiently finding the nearest neighbor in high dimensional spaces. As a general rule, if the dimensionality is k, the number of points in the data, N, should be N ≫ 2k. +Otherwise, when k-d trees are used with high-dimensional data, most of the points in the tree will be evaluated and the efficiency is no better than exhaustive search, and other methods such as approximate nearest-neighbor are used instead. +
+ +## Instructions +
+Write a function to perform a nearest neighbour search using k-d tree. The function takes two parameters: an array of k-dimensional points, and a single k-dimensional point whose nearest neighbour should be returned by the function. A k-dimensional point will be given as an array of k elements. +
+ +## Tests +
+ +``` yml +tests: + - text: kdNN should be a function. + testString: assert(typeof kdNN == 'function', 'kdNN should be a function.'); + - text: kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2]) should return an array. + testString: assert(Array.isArray(kdNN([[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2])), 'kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2]) should return an array.'); + - text: kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2]) should return [ 8, 1 ]. + testString: assert.deepEqual(kdNN([[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2]), [8, 1], 'kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [9, 2]) should return [ 8, 1 ].'); + - text: kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [7, 1]) should return [ 8, 1 ]. + testString: assert.deepEqual(kdNN([[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [7, 1]), [8, 1], 'kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [7, 1]) should return [ 8, 1 ].'); + - text: kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [3, 2]) should return [ 2, 3 ]. + testString: assert.deepEqual(kdNN([[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [3, 2]), [2, 3], 'kdNN([[[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]], [3, 2]) should return [ 2, 3 ].'); + - text: kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [1, 2, 3]) should return [ 1, 2, 5 ]. + testString: assert.deepEqual(kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [1, 2, 3]), [1, 2, 5], 'kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [1, 2, 3]) should return [ 1, 2, 5 ].'); + - text: kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [4, 5, 6]) should return [ 4, 6, 7 ]. + testString: assert.deepEqual(kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [4, 5, 6]), [4, 6, 7], 'kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [4, 5, 6]) should return [ 4, 6, 7 ].'); + - text: kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [8, 8, 8]) should return [ 7, 8, 9 ]. + testString: assert.deepEqual(kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [8, 8, 8]), [7, 8, 9], 'kdNN([[2, 3, 1], [9, 4, 5], [4, 6, 7], [1, 2, 5], [7, 8, 9], [3, 6, 1]], [8, 8, 8]) should return [ 7, 8, 9 ].'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function kdNN(fpoints, fpoint) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function kdNN(fpoints, fpoint) { + function Node(obj, dimension, parent) { + this.obj = obj; + this.left = null; + this.right = null; + this.parent = parent; + this.dimension = dimension; + } + + function kdTree(points, metric, dimensions) { + + var self = this; + + function buildTree(points, depth, parent) { + var dim = depth % dimensions.length, + median, + node; + + if (points.length === 0) { + return null; + } + if (points.length === 1) { + return new Node(points[0], dim, parent); + } + + points.sort(function (a, b) { + return a[dimensions[dim]] - b[dimensions[dim]]; + }); + + median = Math.floor(points.length / 2); + node = new Node(points[median], dim, parent); + node.left = buildTree(points.slice(0, median), depth + 1, node); + node.right = buildTree(points.slice(median + 1), depth + 1, node); + + return node; + } + + this.root = buildTree(points, 0, null); + + this.insert = function (point) { + function innerSearch(node, parent) { + + if (node === null) { + return parent; + } + + var dimension = dimensions[node.dimension]; + if (point[dimension] < node.obj[dimension]) { + return innerSearch(node.left, node); + } else { + return innerSearch(node.right, node); + } + } + + var insertPosition = innerSearch(this.root, null), + newNode, + dimension; + + if (insertPosition === null) { + this.root = new Node(point, 0, null); + return; + } + + newNode = new Node(point, (insertPosition.dimension + 1) % dimensions.length, insertPosition); + dimension = dimensions[insertPosition.dimension]; + + if (point[dimension] < insertPosition.obj[dimension]) { + insertPosition.left = newNode; + } else { + insertPosition.right = newNode; + } + }; + + this.nearest = function (point, maxNodes, maxDistance) { + var i, + result, + bestNodes; + + bestNodes = new BinaryHeap( + function (e) { return -e[1]; } + ); + + function nearestSearch(node) { + var bestChild, + dimension = dimensions[node.dimension], + ownDistance = metric(point, node.obj), + linearPoint = {}, + linearDistance, + otherChild, + i; + + function saveNode(node, distance) { + bestNodes.push([node, distance]); + if (bestNodes.size() > maxNodes) { + bestNodes.pop(); + } + } + + for (i = 0; i < dimensions.length; i += 1) { + if (i === node.dimension) { + linearPoint[dimensions[i]] = point[dimensions[i]]; + } else { + linearPoint[dimensions[i]] = node.obj[dimensions[i]]; + } + } + + linearDistance = metric(linearPoint, node.obj); + + if (node.right === null && node.left === null) { + if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) { + saveNode(node, ownDistance); + } + return; + } + + if (node.right === null) { + bestChild = node.left; + } else if (node.left === null) { + bestChild = node.right; + } else { + if (point[dimension] < node.obj[dimension]) { + bestChild = node.left; + } else { + bestChild = node.right; + } + } + + nearestSearch(bestChild); + + if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) { + saveNode(node, ownDistance); + } + + if (bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[1]) { + if (bestChild === node.left) { + otherChild = node.right; + } else { + otherChild = node.left; + } + if (otherChild !== null) { + nearestSearch(otherChild); + } + } + } + + if (maxDistance) { + for (i = 0; i < maxNodes; i += 1) { + bestNodes.push([null, maxDistance]); + } + } + + if (self.root) + nearestSearch(self.root); + + result = []; + + for (i = 0; i < Math.min(maxNodes, bestNodes.content.length); i += 1) { + if (bestNodes.content[i][0]) { + result.push([bestNodes.content[i][0].obj, bestNodes.content[i][1]]); + } + } + return result; + }; + } + + function BinaryHeap(scoreFunction) { + this.content = []; + this.scoreFunction = scoreFunction; + } + + BinaryHeap.prototype = { + push: function (element) { + // Add the new element to the end of the array. + this.content.push(element); + // Allow it to bubble up. + this.bubbleUp(this.content.length - 1); + }, + + pop: function () { + // Store the first element so we can return it later. + var result = this.content[0]; + // Get the element at the end of the array. + var end = this.content.pop(); + // If there are any elements left, put the end element at the + // start, and let it sink down. + if (this.content.length > 0) { + this.content[0] = end; + this.sinkDown(0); + } + return result; + }, + + peek: function () { + return this.content[0]; + }, + + size: function () { + return this.content.length; + }, + + bubbleUp: function (n) { + // Fetch the element that has to be moved. + var element = this.content[n]; + // When at 0, an element can not go up any further. + while (n > 0) { + // Compute the parent element's index, and fetch it. + var parentN = Math.floor((n + 1) / 2) - 1, + parent = this.content[parentN]; + // Swap the elements if the parent is greater. + if (this.scoreFunction(element) < this.scoreFunction(parent)) { + this.content[parentN] = element; + this.content[n] = parent; + // Update 'n' to continue at the new position. + n = parentN; + } + // Found a parent that is less, no need to move it further. + else { + break; + } + } + }, + + sinkDown: function (n) { + // Look up the target element and its score. + var length = this.content.length, + element = this.content[n], + elemScore = this.scoreFunction(element); + + while (true) { + // Compute the indices of the child elements. + var child2N = (n + 1) * 2, child1N = child2N - 1; + // This is used to store the new position of the element, + // if any. + var swap = null; + // If the first child exists (is inside the array)... + if (child1N < length) { + // Look it up and compute its score. + var child1 = this.content[child1N], + child1Score = this.scoreFunction(child1); + // If the score is less than our element's, we need to swap. + if (child1Score < elemScore) + swap = child1N; + } + // Do the same checks for the other child. + if (child2N < length) { + var child2 = this.content[child2N], + child2Score = this.scoreFunction(child2); + if (child2Score < (swap == null ? elemScore : child1Score)) { + swap = child2N; + } + } + + // If the element needs to be moved, swap it, and continue. + if (swap != null) { + this.content[n] = this.content[swap]; + this.content[swap] = element; + n = swap; + } + // Otherwise, we are done. + else { + break; + } + } + } + }; + + var dims = [] + + for (var i = 0; i < fpoint.length; i++) dims.push(i) + + var tree = new kdTree(fpoints, function (e1, e2) { + var d = 0; + var e3 = e1; + if (!Array.isArray(e1)) { + e3 = [] + for (var key in e1) + e3.push(e1[key]) + + e1 = e3 + } + e1.forEach(function (e, i) { + var sqd = (e1[i] - e2[i]); + d += sqd * sqd; + }) + return d; + }, dims) + + return tree.nearest(fpoint, 1, 1000)[0][0]; +} +``` + +
\ No newline at end of file diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/kaprekar-numbers.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/kaprekar-numbers.md new file mode 100644 index 0000000000..86b619add3 --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/kaprekar-numbers.md @@ -0,0 +1,82 @@ +--- +id: 5a23c84252665b21eecc7eca +title: Kaprekar numbers +challengeType: 5 +--- + +## Description +
+A positive integer is a Kaprekar number if: + +Note that a split resulting in a part consisting purely of 0s is not valid, as 0 is not considered positive.Example +Kaprekar numbers: + +
+ +## Instructions +
+Write a function that takes a number $n$, a base $bs$, and returns true if the number is a Kaprekar number for the given base. Otherwise, the function returns false. +
+ +## Tests +
+ +``` yml +tests: + - text: isKaprekar should be a function. + testString: assert(typeof isKaprekar == 'function', 'isKaprekar should be a function.'); + - text: isKaprekar(1, 10) should return a boolean. + testString: assert(typeof isKaprekar(1, 10) == 'boolean', 'isKaprekar(1, 10) should return a boolean.'); + - text: isKaprekar(1, 10) should return true. + testString: assert.equal(isKaprekar(1, 10), true, 'isKaprekar(1, 10) should return true.'); + - text: isKaprekar(9, 10) should return true. + testString: assert.equal(isKaprekar(9, 10), true, 'isKaprekar(9, 10) should return true.'); + - text: isKaprekar(2223, 10) should return true. + testString: assert.equal(isKaprekar(2223, 10), true, 'isKaprekar(2223, 10) should return true.'); + - text: isKaprekar(22823, 10) should return false. + testString: assert.equal(isKaprekar(22823, 10), false, 'isKaprekar(22823, 10) should return false.'); + - text: isKaprekar(9, 17) should return false. + testString: assert.equal(isKaprekar(9, 17), false, 'isKaprekar(9, 17) should return false.'); + - text: isKaprekar(225, 17) should return true. + testString: assert.equal(isKaprekar(225, 17), true, 'isKaprekar(225, 17) should return true.'); + - text: isKaprekar(999, 17) should return false. + testString: assert.equal(isKaprekar(999, 17), false, 'isKaprekar(999, 17) should return false.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function isKaprekar(n, bs) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function isKaprekar(n, bs) { + if (n < 1) return false; + if (n == 1) return true; + for (var a = n * n, b = 0, s = 1; a; s *= bs) { + b += a % bs * s; + a = Math.floor(a / bs); + if (b && a + b == n) return true; + } return false; +} +``` + +
diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/knight's-tour.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/knight's-tour.md new file mode 100644 index 0000000000..968fda3581 --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/knight's-tour.md @@ -0,0 +1,141 @@ +--- +id: 5a23c84252665b21eecc7ed5 +title: Knight's tour +challengeType: 5 +--- + +## Description +
+Knight's TourProblem: You have an empty w * h chessboard, but for a single knight on some square. The knight must perform a sequence of legal moves that result in the knight visiting every square on the chessboard exactly once. Note that it is not a requirement that the tour be "closed"; that is, the knight need not end within a single move of its start position. +
+ +## Instructions +
+Write a function that takes w and h as parameters and returns the number of initial positions from where it is possible to achieve the task stated above. +
+ +## Tests +
+ +``` yml +tests: + - text: knightTour should be a function. + testString: assert(typeof knightTour == 'function', 'knightTour should be a function.'); + - text: knightTour(6, 6) should return a number. + testString: assert(typeof knightTour(6, 6) == 'number', 'knightTour(6, 6) should return a number.'); + - text: knightTour(6, 6) should return 35. + testString: assert.equal(knightTour(6, 6), 35, 'knightTour(6, 6) should return 35.'); + - text: knightTour(5, 6) should return 20. + testString: assert.equal(knightTour(5, 6), 20, 'knightTour(5, 6) should return 20.'); + - text: knightTour(4, 6) should return 10. + testString: assert.equal(knightTour(4, 6), 10, 'knightTour(4, 6) should return 10.'); + - text: knightTour(7, 3) should return 4. + testString: assert.equal(knightTour(7, 3), 4, 'knightTour(7, 3) should return 4.'); + - text: knightTour(8, 6) should return 47. + testString: assert.equal(knightTour(8, 6), 47, 'knightTour(8, 6) should return 47.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function knightTour(w, h) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function knightTour (w, h) { + var b, cnt=0; + + var dx = [ -2, -2, -1, 1, 2, 2, 1, -1 ]; + var dy = [ -1, 1, 2, 2, 1, -1, -2, -2 ]; + + function init_board() + { + var i, j, k, x, y; + // * b is board; a is board with 2 rows padded at each side + + for(i=0;i= 0 && x < w && y >= 0 && y < h) b[i][j]++; + } + } + } + } + + function walk_board(x, y) + { + var i, nx, ny, least; + var steps = 0; + // printf(E"H"E"J"E"%d;%dH"E"32m[]"E"m", y + 1, 1 + 2 * x); + + while (1) { + // * occupy cell + b[y][x] = 255; + + // * reduce all neighbors' neighbor count + for (i = 0; i < 8; i++) + if(y+dy[i] >= 0 && x+dx[i] >= 0 && y+dy[i] < h && x+dx[i] < w) + b[ y + dy[i] ][ x + dx[i] ]--; + + // find neighbor with lowest neighbor count + least = 255; + for (i = 0; i < 8; i++) { + if(y+dy[i] >= 0 && x+dx[i] >= 0 && y+dy[i] < h && x+dx[i] < w) + if (b[ y + dy[i] ][ x + dx[i] ] < least) { + nx = x + dx[i]; + ny = y + dy[i]; + least = b[ny][nx]; + } + } + + if (least > 7) { + return steps == w * h - 1; + } + + steps++; + x = nx, y = ny; + } + } + + function solve (x, y) { + b=new Array(h); + for(var i=0;i diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/largest-int-from-concatenated-ints.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/largest-int-from-concatenated-ints.md new file mode 100644 index 0000000000..e5ff62546f --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/largest-int-from-concatenated-ints.md @@ -0,0 +1,74 @@ +--- +id: 5a23c84252665b21eecc7edb +title: Largest int from concatenated ints +challengeType: 5 +--- + +## Description +
+Given a set of positive integers, write a function to order the integers in such a way that the concatenation of the numbers forms the largest possible integer and return this integer. +
+ +## Instructions +
+ +
+ +## Tests +
+ +``` yml +tests: + - text: maxCombine should be a function. + testString: assert(typeof maxCombine == 'function', 'maxCombine should be a function.'); + - text: maxCombine([1, 3, 3, 4, 55]) should return a number. + testString: assert(typeof maxCombine([1, 3, 3, 4, 55]) == 'number', 'maxCombine([1, 3, 3, 4, 55]) should return a number.'); + - text: maxCombine([1, 3, 3, 4, 55]) should return 554331. + testString: assert.equal(maxCombine([1, 3, 3, 4, 55]), 554331, 'maxCombine([1, 3, 3, 4, 55]) should return 554331.'); + - text: maxCombine([71, 45, 23, 4, 5]) should return 71545423. + testString: assert.equal(maxCombine([71, 45, 23, 4, 5]), 71545423, 'maxCombine([71, 45, 23, 4, 5]) should return 71545423.'); + - text: maxCombine([14, 43, 53, 114, 55]) should return 55534314114. + testString: assert.equal(maxCombine([14, 43, 53, 114, 55]), 55534314114, 'maxCombine([14, 43, 53, 114, 55]) should return 55534314114.'); + - text: maxCombine([1, 34, 3, 98, 9, 76, 45, 4]) should return 998764543431. + testString: assert.equal(maxCombine([1, 34, 3, 98, 9, 76, 45, 4]), 998764543431, 'maxCombine([1, 34, 3, 98, 9, 76, 45, 4]) should return 998764543431.'); + - text: maxCombine([54, 546, 548, 60]) should return 6054854654. + testString: assert.equal(maxCombine([54, 546, 548, 60]), 6054854654, 'maxCombine([54, 546, 548, 60]) should return 6054854654.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function maxCombine(xs) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function maxCombine (xs) { + return parseInt( + xs.sort( + function (x, y) { + var a = x.toString(), + b = y.toString(), + ab = parseInt(a + b), + ba = parseInt(b + a); + + return ab > ba ? -1 : (ab < ba ? 1 : 0); + } + ) + .join(''), 10 + ); +} +``` + +
\ No newline at end of file diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/last-friday-of-each-month.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/last-friday-of-each-month.md new file mode 100644 index 0000000000..59541adbde --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/last-friday-of-each-month.md @@ -0,0 +1,76 @@ +--- +id: 5a23c84252665b21eecc7edc +title: Last Friday of each month +challengeType: 5 +--- + +## Description +
+Write a function that returns the date of the last Friday of a given month for a given year. +
+ +## Instructions +
+ +
+ +## Tests +
+ +``` yml +tests: + - text: lastFriday should be a function. + testString: assert(typeof lastFriday == 'function', 'lastFriday should be a function.'); + - text: lastFriday(2018, 1) should return a number. + testString: assert(typeof lastFriday(2018, 1) == 'number', 'lastFriday(2018, 1) should return a number.'); + - text: lastFriday(2018, 1) should return 26. + testString: assert.equal(lastFriday(2018, 1), 26, 'lastFriday(2018, 1) should return 26.'); + - text: lastFriday(2017, 2) should return 24. + testString: assert.equal(lastFriday(2017, 2), 24, 'lastFriday(2017, 2) should return 24.'); + - text: lastFriday(2012, 3) should return 30. + testString: assert.equal(lastFriday(2012, 3), 30, 'lastFriday(2012, 3) should return 30.'); + - text: lastFriday(1900, 4) should return 27. + testString: assert.equal(lastFriday(1900, 4), 27, 'lastFriday(1900, 4) should return 27.'); + - text: lastFriday(2000, 5) should return 26. + testString: assert.equal(lastFriday(2000, 5), 26, 'lastFriday(2000, 5) should return 26.'); + - text: lastFriday(2006, 6) should return 30. + testString: assert.equal(lastFriday(2006, 6), 30, 'lastFriday(2006, 6) should return 30.'); + - text: lastFriday(2010, 7) should return 30. + testString: assert.equal(lastFriday(2010, 7), 30, 'lastFriday(2010, 7) should return 30.'); + - text: lastFriday(2005, 8) should return 26. + testString: assert.equal(lastFriday(2005, 8), 26, 'lastFriday(2005, 8) should return 26.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function lastFriday(year, month) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function lastFriday (year, month) { + var i, last_day; + i = 0; + while (true) { + last_day = new Date(year, month, i); + if (last_day.getDay() === 5) { + return last_day.getDate(); + } + i -= 1; + } +}; +``` + +
\ No newline at end of file diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/leap-year.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/leap-year.md new file mode 100644 index 0000000000..2f65c66203 --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/leap-year.md @@ -0,0 +1,64 @@ +--- +id: 5a23c84252665b21eecc7ede +title: Leap year +challengeType: 5 +--- + +## Description +
+Determine whether a given year is a leap year in the Gregorian calendar. +
+ +## Instructions +
+ +
+ +## Tests +
+ +``` yml +tests: + - text: isLeapYear should be a function. + testString: assert(typeof isLeapYear == 'function', 'isLeapYear should be a function.'); + - text: isLeapYear() should return a boolean. + testString: assert(typeof isLeapYear(2018) == 'boolean', 'isLeapYear() should return a boolean.'); + - text: isLeapYear(2018) should return false. + testString: assert.equal(isLeapYear(2018), false, 'isLeapYear(2018) should return false.'); + - text: isLeapYear(2016) should return true. + testString: assert.equal(isLeapYear(2016), true, 'isLeapYear(2016) should return true.'); + - text: isLeapYear(2000) should return true. + testString: assert.equal(isLeapYear(2000), true, 'isLeapYear(2000) should return true.'); + - text: isLeapYear(1900) should return false. + testString: assert.equal(isLeapYear(1900), false, 'isLeapYear(1900) should return false.'); + - text: isLeapYear(1996) should return true. + testString: assert.equal(isLeapYear(1996), true, 'isLeapYear(1996) should return true.'); + - text: isLeapYear(1800) should return false. + testString: assert.equal(isLeapYear(1800), false, 'isLeapYear(1800) should return false.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function isLeapYear(year) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function isLeapYear (year) { + return (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0); +}; +``` + +
\ No newline at end of file diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/least-common-multiple.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/least-common-multiple.md new file mode 100644 index 0000000000..e4d5031f28 --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/least-common-multiple.md @@ -0,0 +1,72 @@ +--- +id: 5a23c84252665b21eecc7edf +title: Least common multiple +challengeType: 5 +--- + +## Description +
+The least common multiple of 12 and 18 is 36, because 12 is a factor (12 × 3 = 36), and 18 is a factor (18 × 2 = 36), and there is no positive integer less than 36 that has both factors. As a special case, if either m or n is zero, then the least common multiple is zero. +One way to calculate the least common multiple is to iterate all the multiples of m, until you find one that is also a multiple of n. +If you already have gcd for greatest common divisor, then this formula calculates lcm. +\( \operatorname{lcm}(m, n) = \frac{|m \times n|}{\operatorname{gcd}(m, n)} \) +
+ +## Instructions +
+Compute the least common multiple of an array of intergers. +Given m and n, the least common multiple is the smallest positive integer that has both m and n as factors. +
+ +## Tests +
+ +``` yml +tests: + - text: LCM should be a function. + testString: assert(typeof LCM == 'function', 'LCM should be a function.'); + - text: LCM([2, 4, 8]) should return a number. + testString: assert(typeof LCM([2, 4, 8]) == 'number', 'LCM([2, 4, 8]) should return a number.'); + - text: LCM([2, 4, 8]) should return 8. + testString: assert.equal(LCM([2, 4, 8]), 8, 'LCM([2, 4, 8]) should return 8.'); + - text: LCM([4, 8, 12]) should return 24. + testString: assert.equal(LCM([4, 8, 12]), 24, 'LCM([4, 8, 12]) should return 24.'); + - text: LCM([3, 4, 5, 12, 40]) should return 120. + testString: assert.equal(LCM([3, 4, 5, 12, 40]), 120, 'LCM([3, 4, 5, 12, 40]) should return 120.'); + - text: LCM([11, 33, 90]) should return 990. + testString: assert.equal(LCM([11, 33, 90]), 990, 'LCM([11, 33, 90]) should return 990.'); + - text: LCM([-50, 25, -45, -18, 90, 447]) should return 67050. + testString: assert.equal(LCM([-50, 25, -45, -18, 90, 447]), 67050, 'LCM([-50, 25, -45, -18, 90, 447]) should return 67050.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function LCM(A) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function LCM (A) { + var n = A.length, a = Math.abs(A[0]); + for (var i = 1; i < n; i++) + { var b = Math.abs(A[i]), c = a; + while (a && b){ a > b ? a %= b : b %= a; } + a = Math.abs(c*A[i])/(a+b); + } + return a; +} +``` + +
\ No newline at end of file diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/left-factorials.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/left-factorials.md new file mode 100644 index 0000000000..572bb426dd --- /dev/null +++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/left-factorials.md @@ -0,0 +1,89 @@ +--- +id: 5a23c84252665b21eecc7ee0 +title: Left factorials +challengeType: 5 +--- + +## Description +
+Left factorials, $ !n $, may refer to either subfactorials or to factorial sums. The same notation can be confusingly seen used for the two different definitions. Sometimes, subfactorials (also known as derangements) may use any of the notations: +
    +
  • $!n`$
  • +
  • $!n$
  • +
  • $n¡$
  • +
+(It may not be visually obvious, but the last example uses an upside-down exclamation mark.) This task will be using this formula for left factorial: +$ !n = \sum_{k=0}^{n-1} k! $ +where $!0 = 0$ +
+ +## Instructions +
+Write a function to calculate the left factorial of a given number. +
+ +## Tests +
+ +``` yml +tests: + - text: leftFactorial should be a function. + testString: assert(typeof leftFactorial == 'function', 'leftFactorial should be a function.'); + - text: leftFactorial(0) should return a number. + testString: assert(typeof leftFactorial(0) == 'number', 'leftFactorial(0) should return a number.'); + - text: leftFactorial(0) should return 0. + testString: assert.equal(leftFactorial(0), 0, 'leftFactorial(0) should return 0.'); + - text: leftFactorial(1) should return 1. + testString: assert.equal(leftFactorial(1), 1, 'leftFactorial(1) should return 1.'); + - text: leftFactorial(2) should return 2. + testString: assert.equal(leftFactorial(2), 2, 'leftFactorial(2) should return 2.'); + - text: leftFactorial(3) should return 4. + testString: assert.equal(leftFactorial(3), 4, 'leftFactorial(3) should return 4.'); + - text: leftFactorial(10) should return 409114. + testString: assert.equal(leftFactorial(10), 409114, 'leftFactorial(10) should return 409114.'); + - text: leftFactorial(17) should return 22324392524314. + testString: assert.equal(leftFactorial(17), 22324392524314, 'leftFactorial(17) should return 22324392524314.'); + - text: leftFactorial(19) should return 6780385526348314. + testString: assert.equal(leftFactorial(19), 6780385526348314, 'leftFactorial(19) should return 6780385526348314.'); +``` + +
+ +## Challenge Seed +
+
+ +```js +function leftFactorial(n) { + // Good luck! +} +``` + +
+
+ +## Solution +
+ +```js +function leftFactorial(n) { + if (n == 0) + return 0 + if (n == 1) + return 1; + + // Note: for n>=20, the result may not be correct. + // This is because Javascript uses 53 bit integers and + // for n>=20 result becomes too large. + + let res = 2, fact = 2; + for (var i = 2; i < n; i++) { + res += fact; + fact *= (i + 1); + } + + return res; +} +``` + +
\ No newline at end of file