diff --git a/curriculum/challenges/_meta/rosetta-code/meta.json b/curriculum/challenges/_meta/rosetta-code/meta.json
index b38620e922..eca1027d75 100644
--- a/curriculum/challenges/_meta/rosetta-code/meta.json
+++ b/curriculum/challenges/_meta/rosetta-code/meta.json
@@ -408,6 +408,22 @@
"5e6dee7749a0b85a3f1fc7d5",
"Lucas-Lehmer test"
],
+ [
+ "5ea281203167d2b0bdefca00",
+ "Ludic numbers"
+ ],
+ [
+ "5ea28156e79528a9ab248f27",
+ "Luhn test of credit card numbers"
+ ],
+ [
+ "5ea2815a8640bcc6cb7dab3c",
+ "Lychrel numbers"
+ ],
+ [
+ "5ea2815e364d9a2222ea55f8",
+ "LZW compression"
+ ],
[
"59da22823d04c95919d46269",
"Sailors, coconuts and a monkey problem"
diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/ludic-numbers.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/ludic-numbers.md
new file mode 100644
index 0000000000..72a642850f
--- /dev/null
+++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/ludic-numbers.md
@@ -0,0 +1,112 @@
+---
+id: 5ea281203167d2b0bdefca00
+title: Ludic numbers
+challengeType: 5
+---
+
+## Description
+
+
+Ludic numbers are related to prime numbers as they are generated by a sieve quite like the Sieve of Eratosthenes is used to generate prime numbers.
+The first ludic number is 1.
+To generate succeeding ludic numbers create an array of increasing integers starting from 2.
+2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...
+(Loop)
+
+ - Take the first member of the resultant array as the next ludic number 2.
+ - Remove every 2nd indexed item from the array (including the first).
+ 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...
+
+
+ - (Unrolling a few loops...)
+ - Take the first member of the resultant array as the next ludic number 3.
+ - Remove every 3rd indexed item from the array (including the first).
+ 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 ...
+
+
+ - Take the first member of the resultant array as the next ludic number 5.
+ - Remove every 5th indexed item from the array (including the first).
+ 5 7 11 13 17 19 23 25 29 31 35 37 41 43 47 49 53 55 59 61 65 67 71 73 77 ...
+
+
+ - Take the first member of the resultant array as the next ludic number 7.
+ - Remove every 7th indexed item from the array (including the first).
+ 7 11 13 17 23 25 29 31 37 41 43 47 53 55 59 61 67 71 73 77 83 85 89 91 97 ...
+
+
+ - ...
+ - Take the first member of the current array as the next ludic number L.
+ - Remove every Lth indexed item from the array (including the first).
+ - ...
+
+
+
+## Instructions
+
+
+Write a function that returns all the ludic numbers less than or equal to the given number.
+
+
+## Tests
+
+
+
+```yml
+tests:
+ - text: ludic
should be a function.
+ testString: assert(typeof ludic === 'function', 'ludic
should be a function.');
+ - text: ludic(2)
should return a array.
+ testString: assert(Array.isArray(ludic(2)));
+ - text: ludic(2)
should return [1, 2]
.
+ testString: assert.deepEqual(ludic(2), [1, 2]);
+ - text: ludic(3)
should return [1, 2, 3]
.
+ testString: assert.deepEqual(ludic(3), [1, 2, 3]);
+ - text: ludic(5)
should return [1, 2, 3, 5]
.
+ testString: assert.deepEqual(ludic(5), [1, 2, 3, 5]);
+ - text: ludic(20)
should return [1, 2, 3, 5, 7, 11, 13, 17]
.
+ testString: assert.deepEqual(ludic(20), [1, 2, 3, 5, 7, 11, 13, 17]);
+ - text: ludic(26)
should return [1, 2, 3, 5, 7, 11, 13, 17, 23, 25]
.
+ testString: assert.deepEqual(ludic(26), [1, 2, 3, 5, 7, 11, 13, 17, 23, 25]);
+```
+
+
+
+## Challenge Seed
+
+
+
+
+
+```js
+function ludic(n) {
+
+}
+```
+
+
+
+
+
+## Solution
+
+
+
+```js
+function ludic(n) {
+ const makeArr = (s, e) => new Array(e + 1 - s).fill(s).map((e, i) => e + i);
+
+ const filterAtInc = (arr, n) => arr.filter((e, i) => (i + 1) % n);
+
+ const makeLudic = (arr, result) => {
+ const iter = arr.shift();
+ result.push(iter);
+ return arr.length ? makeLudic(filterAtInc(arr, iter), result) : result;
+ };
+
+ const ludicResult = makeLudic(makeArr(2, n), [1]);
+
+ return ludicResult;
+}
+```
+
+
diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/luhn-test-of-credit-card-numbers.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/luhn-test-of-credit-card-numbers.md
new file mode 100644
index 0000000000..87d7434f97
--- /dev/null
+++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/luhn-test-of-credit-card-numbers.md
@@ -0,0 +1,112 @@
+---
+id: 5ea28156e79528a9ab248f27
+title: Luhn test of credit card numbers
+challengeType: 5
+---
+
+## Description
+
+
+The Luhn test is used by some credit card companies to distinguish valid credit card numbers from what could be a random selection of digits.
+Those companies using credit card numbers that can be validated by the Luhn test have numbers that pass the following test:
+
+ - Reverse the order of the digits in the number.
+ - Take the first, third, ... and every other odd digit in the reversed digits and sum them to form the partial sum s1
+ - Taking the second, fourth ... and every other even digit in the reversed digits:
+
+ - Multiply each digit by two and sum the digits if the answer is greater than nine to form partial sums for the even digits.
+ - Sum the partial sums of the even digits to form s2.
+
+ - If s1 + s2 ends in zero then the original number is in the form of a valid credit card number as verified by the Luhn test.
+
+
+For example, if the trial number is 49927398716:
+
+```bash
+Reverse the digits:
+ 61789372994
+Sum the odd digits:
+ 6 + 7 + 9 + 7 + 9 + 4 = 42 = s1
+The even digits:
+ 1, 8, 3, 2, 9
+ Two times each even digit:
+ 2, 16, 6, 4, 18
+ Sum the digits of each multiplication:
+ 2, 7, 6, 4, 9
+ Sum the last:
+ 2 + 7 + 6 + 4 + 9 = 28 = s2
+
+s1 + s2 = 70 which ends in zero which means that 49927398716 passes the Luhn test.
+```
+
+
+
+## Instructions
+
+
+Write a function that will validate a number with the Luhn test. Return true if it's a valid number. Otherwise, return false.
+
+
+## Tests
+
+
+
+```yml
+tests:
+ - text: luhnTest
should be a function.
+ testString: assert(typeof luhnTest === 'function');
+ - text: luhnTest("4111111111111111")
should return a boolean.
+ testString: assert(typeof luhnTest("4111111111111111") === 'boolean');
+ - text: luhnTest("4111111111111111")
should return true
.
+ testString: assert.equal(luhnTest("4111111111111111"), true);
+ - text: luhnTest("4111111111111112")
should return false
.
+ testString: assert.equal(luhnTest("4111111111111112"), false);
+ - text: luhnTest("49927398716")
should return true
.
+ testString: assert.equal(luhnTest("49927398716"), true);
+ - text: luhnTest("49927398717")
should return false
.
+ testString: assert.equal(luhnTest("49927398717"), false);
+ - text: luhnTest("1234567812345678")
should return false
.
+ testString: assert.equal(luhnTest("1234567812345678"), false);
+ - text: luhnTest("1234567812345670")
should return true
.
+ testString: assert.equal(luhnTest("1234567812345670"), true);
+```
+
+
+
+## Challenge Seed
+
+
+
+
+
+```js
+function luhnTest(str) {
+
+}
+```
+
+
+
+
+
+## Solution
+
+
+
+```js
+function luhnTest(str) {
+ var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
+ var counter = 0;
+ var incNum;
+ var odd = false;
+ var temp = String(str).replace(/[^\d]/g, '');
+ if (temp.length == 0) return false;
+ for (var i = temp.length - 1; i >= 0; --i) {
+ incNum = parseInt(temp.charAt(i), 10);
+ counter += (odd = !odd) ? incNum : luhnArr[incNum];
+ }
+ return counter % 10 == 0;
+}
+```
+
+
diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/lychrel-numbers.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/lychrel-numbers.md
new file mode 100644
index 0000000000..5f9297d07b
--- /dev/null
+++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/lychrel-numbers.md
@@ -0,0 +1,139 @@
+---
+id: 5ea2815a8640bcc6cb7dab3c
+title: Lychrel numbers
+challengeType: 5
+---
+
+## Description
+
+
+ - Take an integer
n₀
, greater than zero.
+ - Form the next number
n
of the series by reversing n₀
and adding it to n₀
+ - Stop when
n
becomes palindromic - i.e. the digits of n
in reverse order == n
.
+
+
+The above recurrence relation when applied to most starting numbers `n` = 1, 2, ... terminates in a palindrome quite quickly.
+
+For example if `n₀` = 12 we get:
+
+```bash
+12
+12 + 21 = 33, a palindrome!
+```
+
+And if `n₀` = 55 we get:
+
+```bash
+55
+55 + 55 = 110
+110 + 011 = 121, a palindrome!
+```
+
+Notice that the check for a palindrome happens after an addition.
+
+Some starting numbers seem to go on forever; the recurrence relation for 196 has been calculated for millions of repetitions forming numbers with millions of digits, without forming a palindrome. These numbers that do not end in a palindrome are called Lychrel numbers.
+
+For the purposes of this task a Lychrel number is any starting number that does not form a palindrome within 500 (or more) iterations.
+
+Seed and related Lychrel numbers:
+
+Any integer produced in the sequence of a Lychrel number is also a Lychrel number.
+
+In general, any sequence from one Lychrel number might converge to join the sequence from a prior Lychrel number candidate; for example the sequences for the numbers 196 and then 689 begin:
+
+```bash
+ 196
+ 196 + 691 = 887
+ 887 + 788 = 1675
+ 1675 + 5761 = 7436
+ 7436 + 6347 = 13783
+ 13783 + 38731 = 52514
+ 52514 + 41525 = 94039
+ ...
+ 689
+ 689 + 986 = 1675
+ 1675 + 5761 = 7436
+ ...
+```
+
+So we see that the sequence starting with 689 converges to, and continues with the same numbers as that for 196.
+
+Because of this we can further split the Lychrel numbers into true Seed Lychrel number candidates, and Related numbers that produce no palindromes but have integers in their sequence seen as part of the sequence generated from a lower Lychrel number.
+
+
+
+## Instructions
+
+
+Write a function that takes a number as a parameter. Return true if the number is a Lynchrel number. Otherwise, return false. Remember that the iteration limit is 500.
+
+
+## Tests
+
+
+
+```yml
+tests:
+ - text: isLychrel
should be a function.
+ testString: assert(typeof isLychrel === 'function');
+ - text: isLychrel(12)
should return a boolean.
+ testString: assert(typeof isLychrel(12) === 'boolean');
+ - text: isLychrel(12)
should return false
.
+ testString: assert.equal(isLychrel(12), false);
+ - text: isLychrel(55)
should return false
.
+ testString: assert.equal(isLychrel(55), false);
+ - text: isLychrel(196)
should return true
.
+ testString: assert.equal(isLychrel(196), true);
+ - text: isLychrel(879)
should return true
.
+ testString: assert.equal(isLychrel(879), true);
+ - text: isLychrel(44987)
should return false
.
+ testString: assert.equal(isLychrel(44987), false);
+ - text: isLychrel(7059)
should return true
.
+ testString: assert.equal(isLychrel(7059), true);
+```
+
+
+
+## Challenge Seed
+
+
+
+
+
+```js
+function isLychrel(n) {
+
+}
+```
+
+
+
+
+
+## Solution
+
+
+
+```js
+function isLychrel(n) {
+ function reverse(num) {
+ return parseInt(
+ num
+ .toString()
+ .split('')
+ .reverse()
+ .join('')
+ );
+ }
+
+ var i;
+ for (i = 0; i < 500; i++) {
+ n = n + reverse(n);
+ if (n == reverse(n)) break;
+ }
+
+ return i == 500;
+}
+```
+
+
diff --git a/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/lzw-compression.md b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/lzw-compression.md
new file mode 100644
index 0000000000..27006b5ca1
--- /dev/null
+++ b/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/lzw-compression.md
@@ -0,0 +1,147 @@
+---
+id: 5ea2815e364d9a2222ea55f8
+title: LZW compression
+challengeType: 5
+---
+
+## Description
+
+The Lempel-Ziv-Welch (LZW) algorithm provides loss-less data compression.
+You can read a complete description of it in the Wikipedia article on the subject.
+
+
+## Instructions
+
+Write a function that takes two parameters. The first parameter is a boolean where `true` indicates compress and `false` indicates decompress. The second parameter is either a string or an array to be processed. If it is a string to be compressed, return an array of numbers. If it's an array of numbers to be decompressed, return a string.
+
+
+## Tests
+
+
+```yml
+tests:
+ - text: LZW
should be a function.
+ testString: assert(typeof LZW === 'function');
+ - text: LZW(true, "TOBEORNOTTOBEORTOBEORNOT")
should return a array.
+ testString: assert(Array.isArray(LZW(true, "TOBEORNOTTOBEORTOBEORNOT")));
+ - text: LZW(false, [84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263])
should return a string.
+ testString: assert(typeof LZW(false, [84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]) === 'string');
+ - text: LZW(true, "TOBEORNOTTOBEORTOBEORNOT")
should return [84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]
.
+ testString: assert.deepEqual(LZW(true, "TOBEORNOTTOBEORTOBEORNOT"), [84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]);
+ - text: LZW(false, [84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263])
should return "TOBEORNOTTOBEORTOBEORNOT"
.
+ testString: assert.equal(LZW(false, [84, 79, 66, 69, 79, 82, 78, 79, 84, 256, 258, 260, 265, 259, 261, 263]), "TOBEORNOTTOBEORTOBEORNOT");
+ - text: LZW(true, "0123456789")
should return [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]
.
+ testString: assert.deepEqual(LZW(true, "0123456789"), [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]);
+ - text: LZW(false, [48, 49, 50, 51, 52, 53, 54, 55, 56, 57])
should return "0123456789"
.
+ testString: assert.equal(LZW(false, [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]), "0123456789");
+ - text: LZW(true, "BABAABAAA")
should return [66, 65, 256, 257, 65, 260]
.
+ testString: assert.deepEqual(LZW(true, "BABAABAAA"), [66, 65, 256, 257, 65, 260]);
+ - text: LZW(false, [66, 65, 256, 257, 65, 260])
should return "BABAABAAA"
.
+ testString: assert.equal(LZW(false, [66, 65, 256, 257, 65, 260]), "BABAABAAA");
+```
+
+
+
+## Challenge Seed
+
+
+
+
+```js
+function LZW (compressData, input) {
+
+}
+```
+
+
+
+
+
+## Solution
+
+
+```js
+function LZW (compressData, input) {
+ function compress(uncompressed) {
+ // Build the dictionary.
+ var i,
+ dictionary = {},
+ c,
+ wc,
+ w = "",
+ result = [],
+ dictSize = 256;
+ for (i = 0; i < 256; i += 1) {
+ dictionary[String.fromCharCode(i)] = i;
+ }
+
+ for (i = 0; i < uncompressed.length; i += 1) {
+ c = uncompressed.charAt(i);
+ wc = w + c;
+ //Do not use dictionary[wc] because javascript arrays
+ //will return values for array['pop'], array['push'] etc
+ // if (dictionary[wc]) {
+ if (dictionary.hasOwnProperty(wc)) {
+ w = wc;
+ } else {
+ result.push(dictionary[w]);
+ // Add wc to the dictionary.
+ dictionary[wc] = dictSize++;
+ w = String(c);
+ }
+ }
+
+ // Output the code for w.
+ if (w !== "") {
+ result.push(dictionary[w]);
+ }
+ return result;
+ }
+
+
+ function decompress(compressed) {
+ // Build the dictionary.
+ var i,
+ dictionary = [],
+ w,
+ result,
+ k,
+ entry = "",
+ dictSize = 256;
+ for (i = 0; i < 256; i += 1) {
+ dictionary[i] = String.fromCharCode(i);
+ }
+
+ w = String.fromCharCode(compressed[0]);
+ result = w;
+ for (i = 1; i < compressed.length; i += 1) {
+ k = compressed[i];
+ if (dictionary[k]) {
+ entry = dictionary[k];
+ } else {
+ if (k === dictSize) {
+ entry = w + w.charAt(0);
+ } else {
+ return null;
+ }
+ }
+
+ result += entry;
+
+ // Add w+entry[0] to the dictionary.
+ dictionary[dictSize++] = w + entry.charAt(0);
+
+ w = entry;
+ }
+ return result;
+ }
+
+ if(compressData){
+ return compress(input)
+ }else{
+ return decompress(input)
+ }
+}
+```
+
+