diff --git a/curriculum/challenges/_meta/rosetta-code/meta.json b/curriculum/challenges/_meta/rosetta-code/meta.json index 72ded7105eb..c7c610e68a5 100644 --- a/curriculum/challenges/_meta/rosetta-code/meta.json +++ b/curriculum/challenges/_meta/rosetta-code/meta.json @@ -428,10 +428,18 @@ "5ea2815e364d9a2222ea55f8", "LZW compression" ], + [ + "59667989bf71cf555dd5d2ff", + "S-Expressions" + ], [ "59da22823d04c95919d46269", "Sailors, coconuts and a monkey problem" ], + [ + "5eb3e497b8d6d7f63c5517ea", + "Search a list of records" + ], [ "59d9c6bc214c613ba73ff012", "SEDOLs" @@ -441,8 +449,28 @@ "Self Describing Numbers" ], [ - "59667989bf71cf555dd5d2ff", - "S-Expressions" + "5eb3e4a21f462f409d656c73", + "Self-referential sequence" + ], + [ + "5eb3e4aa847216613aa81983", + "Semiprime" + ], + [ + "5eb3e4af7d0e7b760b46cedc", + "Set consolidation" + ], + [ + "5eb3e4b20aa93c437f9e9717", + "Set of real numbers" + ], + [ + "5eb3e4b5f629b9a07429a5d2", + "SHA-1" + ], + [ + "5eb3e4c3a894c333d2811a3f", + "SHA-256" ], [ "5a23c84252665b21eecc7ffe", diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/search-a-list-of-records.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/search-a-list-of-records.english.md new file mode 100644 index 00000000000..5eb5adcc821 --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/search-a-list-of-records.english.md @@ -0,0 +1,99 @@ +--- +id: 5eb3e497b8d6d7f63c5517ea +title: Search a list of records +challengeType: 5 +isHidden: false +forumTopicId: 385315 +--- + +## Description + +
+ +A record consists of attributes that describe an entity. Each attribute has a name and a value. For example, a person can have an attribute `age` with a value of 25. An important operation on a list of records is to find a record with a particular attribute value. + +
+ +## Instructions + +
+ +Write a function that takes a string as a parameter. The function should return the index of the item in `list` for which the value of the `name` attribute matches the given string. + +
+ +## Tests + +
+ +```yml +tests: + - text: searchCity should be a function. + testString: assert(typeof searchCity === 'function'); + - text: searchCity("Dar Es Salaam") should return a number. + testString: assert(typeof searchCity("Dar Es Salaam") === 'number'); + - text: searchCity("Dar Es Salaam") should return 6. + testString: assert.equal(searchCity("Dar Es Salaam"), 6); + - text: searchCity("Casablanca") should return 9. + testString: assert.equal(searchCity("Casablanca"), 9); + - text: searchCity("Cairo") should return 1. + testString: assert.equal(searchCity("Cairo"), 1); + - text: searchCity("Mogadishu") should return 4. + testString: assert.equal(searchCity("Mogadishu"), 4); + - text: searchCity("Lagos") should return 0. + testString: assert.equal(searchCity("Lagos"), 0); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function searchCity(name) { + +} + +const list = [ + { name: 'Lagos', population: 21.0 }, + { name: 'Cairo', population: 15.2 }, + { name: 'Kinshasa-Brazzaville', population: 11.3 }, + { name: 'Greater Johannesburg', population: 7.55 }, + { name: 'Mogadishu', population: 5.85 }, + { name: 'Khartoum-Omdurman', population: 4.98 }, + { name: 'Dar Es Salaam', population: 4.7 }, + { name: 'Alexandria', population: 4.58 }, + { name: 'Abidjan', population: 4.4 }, + { name: 'Casablanca', population: 3.98 } +]; +``` + +
+
+ +## Solution + +
+ +```js +function searchCity(name) { + return list.findIndex(item => item.name === name); +} + +const list = [ + { name: 'Lagos', population: 21.0 }, + { name: 'Cairo', population: 15.2 }, + { name: 'Kinshasa-Brazzaville', population: 11.3 }, + { name: 'Greater Johannesburg', population: 7.55 }, + { name: 'Mogadishu', population: 5.85 }, + { name: 'Khartoum-Omdurman', population: 4.98 }, + { name: 'Dar Es Salaam', population: 4.7 }, + { name: 'Alexandria', population: 4.58 }, + { name: 'Abidjan', population: 4.4 }, + { name: 'Casablanca', population: 3.98 } +]; +``` + +
diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/self-referential-sequence.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/self-referential-sequence.english.md new file mode 100644 index 00000000000..a8f491336ec --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/self-referential-sequence.english.md @@ -0,0 +1,152 @@ +--- +id: 5eb3e4a21f462f409d656c73 +title: Self-referential sequence +challengeType: 5 +isHidden: false +forumTopicId: 385317 +--- + +## Description + +
+There are several ways to generate a self-referential sequence. One very common one (the Look-and-say sequence) is to start with a positive integer, then generate the next term by concatenating enumerated groups of adjacent alike digits: + +
0, 10, 1110, 3110, 132110, 1113122110, 311311222110 ...
+ +The terms generated grow in length geometrically and never converge. + +Another way to generate a self-referential sequence is to summarize the previous term. + +Count how many of each alike digit there is, then concatenate the sum and digit for each of the sorted enumerated digits. Note that the first five terms are the same as for the previous sequence. + +
0, 10, 1110, 3110, 132110, 13123110, 23124110 ...
+ +Sort the digits largest to smallest. Do not include counts of digits that do not appear in the previous term. + +Depending on the seed value, series generated this way always either converge to a stable value or to a short cyclical pattern. (For our purposes, converge means that an element matches a previously seen element.) The sequence shown, with a seed value of 0, converges to a stable value of 1433223110 after 11 iterations. The seed value that converges most quickly is 22. It goes stable after the first element. (The next element is 22, which has been seen before.) +
+ +## Instructions + +
+Write a function that takes the seed value as parameter, generates a self referential sequence until it converges, and returns it as an array. +
+ +## Tests + +
+ +```yml +tests: + - text: selfReferential should be a function. + testString: assert(typeof selfReferential === 'function'); + - text: selfReferential(40) should return a array. + testString: assert(Array.isArray(selfReferential(40))); + - text: selfReferential(40) should return ["40", "1410", "142110", "14123110", "1413124110", "2413125110", "151413224110", "152413225110", "251413324110", "152423224110", "152413423110"]. + testString: assert.deepEqual(selfReferential(40), ["40", "1410", "142110", "14123110", "1413124110", "2413125110", "151413224110", "152413225110", "251413324110", "152423224110", "152413423110"]); + - text: selfReferential(132110) should return ["132110", "13123110", "23124110", "1413223110", "1423224110", "2413323110", "1433223110"]. + testString: assert.deepEqual(selfReferential(132110), ["132110", "13123110", "23124110", "1413223110", "1423224110", "2413323110", "1433223110"]); + - text: selfReferential(132211) should return ["132211", "132231", "232221", "134211", "14131231", "14231241", "24132231", "14233221"]. + testString: assert.deepEqual(selfReferential(132211), ["132211", "132231", "232221", "134211", "14131231", "14231241", "24132231", "14233221"]); + - text: selfReferential(1413223110) should return ["1413223110", "1423224110", "2413323110", "1433223110"]. + testString: assert.deepEqual(selfReferential(1413223110), ["1413223110", "1423224110", "2413323110", "1433223110"]); + - text: selfReferential(251413126110) should return ["251413126110", "16151413225110", "16251413226110", "26151413325110", "16251423225110", "16251413424110", "16153413225110"]. + testString: assert.deepEqual(selfReferential(251413126110), ["251413126110", "16151413225110", "16251413226110", "26151413325110", "16251423225110", "16251413424110", "16153413225110"]); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function selfReferential(n) { + +} +``` + +
+
+ +## Solution + +
+ +```js +function selfReferential(n) { + var descending, + i, + incr, + j, + max_i, + max_len, + max_seq, + seq, + sequence, + indexOf = + [].indexOf || + function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) return i; + } + return -1; + }; + + sequence = function(n) { + var c, cnt, cnts, d, digit, i, j, l, len, new_cnts, ref, s, seq; + cnts = {}; + ref = n.toString(); + for (j = 0, len = ref.length; j < len; j++) { + c = ref[j]; + d = parseInt(c); + incr(cnts, d); + } + seq = [ref]; + while (true) { + s = ''; + for (i = l = 9; l >= 0; i = --l) { + if (cnts[i]) { + s += '' + cnts[i] + i; + } + } + if (indexOf.call(seq, s) >= 0) { + break; + } + seq.push(s); + new_cnts = {}; + for (digit in cnts) { + cnt = cnts[digit]; + incr(new_cnts, cnt); + incr(new_cnts, digit); + } + cnts = new_cnts; + } + return seq; + }; + + incr = function(h, k) { + if (h[k] == null) { + h[k] = 0; + } + return (h[k] += 1); + }; + + descending = function(n) { + var tens; + if (n < 10) { + return true; + } + tens = n / 10; + if (n % 10 > tens % 10) { + return false; + } + return descending(tens); + }; + + return sequence(n); +} +``` + +
diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/semiprime.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/semiprime.english.md new file mode 100644 index 00000000000..2a22133c832 --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/semiprime.english.md @@ -0,0 +1,117 @@ +--- +id: 5eb3e4aa847216613aa81983 +title: Semiprime +challengeType: 5 +isHidden: false +forumTopicId: 385318 +--- + +## Description + +
+Semiprime numbers are natural numbers that are products of exactly two (possibly equal) prime numbers. +
1679  =  23 x 73
+
+ +## Instructions + +
+Write a function that returns true if a number is semiprime, or false if it is not. +
+ +## Tests + +
+ +```yml +tests: + - text: isSemiPrime should be a function. + testString: assert(typeof isSemiPrime === 'function'); + - text: isSemiPrime(100) should return a boolean. + testString: assert(typeof isSemiPrime(100) === 'boolean'); + - text: isSemiPrime(100) should return false. + testString: assert.equal(isSemiPrime(100), false); + - text: isSemiPrime(504) should return false. + testString: assert.equal(isSemiPrime(504), false); + - text: isSemiPrime(4) should return true. + testString: assert.equal(isSemiPrime(4), true); + - text: isSemiPrime(46) should return true. + testString: assert.equal(isSemiPrime(46), true); + - text: isSemiPrime(13) should return false. + testString: assert.equal(isSemiPrime(13), false); + - text: isSemiPrime(74) should return true. + testString: assert.equal(isSemiPrime(74), true); + - text: isSemiPrime(1679) should return true. + testString: assert.equal(isSemiPrime(1679), true); + - text: isSemiPrime(2) should return false. + testString: assert.equal(isSemiPrime(2), false); + - text: isSemiPrime(95) should return true. + testString: assert.equal(isSemiPrime(95), true); + - text: isSemiPrime(124) should return false. + testString: assert.equal(isSemiPrime(124), false); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function isSemiPrime(n) { + +} +``` + +
+
+ +## Solution + +
+ +```js +function isSemiPrime(n) { + if (n <= 3) return false; + + var ans = []; + var done = false; + while (!done) { + if (n % 2 === 0) { + ans.push(2); + n /= 2; + continue; + } + if (n % 3 === 0) { + ans.push(3); + n /= 3; + continue; + } + if (n === 1) return ans.length == 2; + var sr = Math.sqrt(n); + done = true; + // try to divide the checked number by all numbers till its square root. + for (var i = 6; i <= sr; i += 6) { + if (n % (i - 1) === 0) { + // is n divisible by i-1? + ans.push(i - 1); + n /= i - 1; + done = false; + break; + } + if (n % (i + 1) === 0) { + // is n divisible by i+1? + ans.push(i + 1); + n /= i + 1; + done = false; + break; + } + } + } + ans.push(n); + return ans.length == 2; +} +``` + +
diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/set-consolidation.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/set-consolidation.english.md new file mode 100644 index 00000000000..bfc2dd39e72 --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/set-consolidation.english.md @@ -0,0 +1,186 @@ +--- +id: 5eb3e4af7d0e7b760b46cedc +title: Set consolidation +challengeType: 5 +isHidden: false +forumTopicId: 385319 +--- + +## Description + +
+Given two sets of items then if any item is common to any set then the result of applying consolidation to those sets is a set of sets whose contents is: + + + +Given N sets of items where N > 2 then the result is the same as repeatedly replacing all combinations of two sets by their consolidation until no further consolidation between set pairs is possible. If N < 2 then consolidation has no strict meaning and the input can be returned. + +Here are some examples: + +Example 1: + +Given the two sets `{A,B}` and `{C,D}` then there is no common element between the sets and the result is the same as the input. + +Example 2: + +Given the two sets `{A,B}` and `{B,D}` then there is a common element `B` between the sets and the result is the single set `{B,D,A}`. (Note that order of items in a set is immaterial: `{A,B,D}` is the same as `{B,D,A}` and `{D,A,B}`, etc). + +Example 3: + +Given the three sets `{A,B}` and `{C,D}` and `{D,B}` then there is no common element between the sets `{A,B}` and `{C,D}` but the sets `{A,B}` and `{D,B}` do share a common element that consolidates to produce the result `{B,D,A}`. On examining this result with the remaining set, `{C,D}`, they share a common element and so consolidate to the final output of the single set `{A,B,C,D}` + +Example 4: + +The consolidation of the five sets: + +`{H,I,K}`, `{A,B}`, `{C,D}`, `{D,B}`, and `{F,G,H}` + +Is the two sets: + +`{A, C, B, D}`, and `{G, F, I, H, K}` +
+ +## Instructions + +
+Write a function that takes an array of strings as a parameter. Each string is represents a set with the characters representing the set elements. The function should return a 2D array containing the consolidated sets. Note: Each set should be sorted. +
+ +## Tests + +
+ +```yml +tests: + - text: setConsolidation should be a function. + testString: assert(typeof setConsolidation === 'function'); + - text: setConsolidation(["AB", "CD"]) should return a array. + testString: assert(Array.isArray(setConsolidation(["AB", "CD"]))); + - text: setConsolidation(["AB", "CD"]) should return [["C", "D"], ["A", "B"]]. + testString: assert.deepEqual(setConsolidation(["AB", "CD"]), [["C", "D"], ["A", "B"]]); + - text: setConsolidation(["AB", "BD"]) should return [["A", "B", "D"]]. + testString: assert.deepEqual(setConsolidation(["AB", "BD"]), [["A", "B", "D"]]); + - text: setConsolidation(["AB", "CD", "DB"]) should return [["A", "B", "C", "D"]]. + testString: assert.deepEqual(setConsolidation(["AB", "CD", "DB"]), [["A", "B", "C", "D"]]); + - text: setConsolidation(["HIK", "AB", "CD", "DB", "FGH"]) should return [["F", "G", "H", "I", "K"], ["A", "B", "C", "D"]]. + testString: assert.deepEqual(setConsolidation(["HIK", "AB", "CD", "DB", "FGH"]), [["F", "G", "H", "I", "K"], ["A", "B", "C", "D"]]); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function setConsolidation(sets) { + +} +``` + +
+
+ +## Solution + +
+ +```js +function setConsolidation(sets) { + function addAll(l1, l2) { + l2.forEach(function(e) { + if (l1.indexOf(e) == -1) l1.push(e); + }); + } + + function consolidate(sets) { + var r = []; + for (var i = 0; i < sets.length; i++) { + var s = sets[i]; + { + var new_r = []; + new_r.push(s); + for (var j = 0; j < r.length; j++) { + var x = r[j]; + { + if ( + !(function(c1, c2) { + for (var i = 0; i < c1.length; i++) { + if (c2.indexOf(c1[i]) >= 0) return false; + } + return true; + })(s, x) + ) { + (function(l1, l2) { + addAll(l1, l2); + })(s, x); + } else { + new_r.push(x); + } + } + } + r = new_r; + } + } + return r; + } + + function consolidateR(sets) { + if (sets.length < 2) return sets; + var r = []; + r.push(sets[0]); + { + var arr1 = consolidateR(sets.slice(1, sets.length)); + for (var i = 0; i < arr1.length; i++) { + var x = arr1[i]; + { + if ( + !(function(c1, c2) { + for (var i = 0; i < c1.length; i++) { + if (c2.indexOf(c1[i]) >= 0) return false; + } + return true; + })(r[0], x) + ) { + (function(l1, l2) { + return l1.push.apply(l1, l2); + })(r[0], x); + } else { + r.push(x); + } + } + } + } + return r; + } + + function hashSetList(set) { + var r = []; + for (var i = 0; i < set.length; i++) { + r.push([]); + for (var j = 0; j < set[i].length; j++) + (function(s, e) { + if (s.indexOf(e) == -1) { + s.push(e); + return true; + } else { + return false; + } + })(r[i], set[i].charAt(j)); + } + return r; + } + + var h1 = consolidate(hashSetList(sets)).map(function(e) { + e.sort(); + return e; + }); + return h1; +} +``` + +
diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/set-of-real-numbers.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/set-of-real-numbers.english.md new file mode 100644 index 00000000000..90d7141f02f --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/set-of-real-numbers.english.md @@ -0,0 +1,184 @@ +--- +id: 5eb3e4b20aa93c437f9e9717 +title: Set of real numbers +challengeType: 5 +isHidden: false +forumTopicId: 385322 +--- + +## Description + +
+All real numbers form the uncountable set ℝ. Among its subsets, relatively simple are the convex sets, each expressed as a range between two real numbers a and b where ab. There are actually four cases for the meaning of "between", depending on open or closed boundary: + + + +Note that if a = b, of the four only [a, a] would be non-empty. + +Task + + +
+ +## Instructions + +
+ +Write a function that takes 2 objects, a string and an array as parameters. The objects represents the set and have attributes: `low`, `high` and `rangeType`. + +The `rangeType` can have values 0, 1, 2 and 3 for `CLOSED`, `BOTH_OPEN`, `LEFT_OPEN` and `RIGHT_OPEN`, respectively. The function should implement a set using this information. + +The string represents the operation to be performed on the sets. It can be: `"union"`, `"intersect"` and `"subtract"` (difference). + +After performing the operation, the function should check if the values in the array are present in the resultant set and store a corresponding boolean value to an array. The function should return this array. + +
+ +## Tests + +
+ +```yml +tests: + - text: realSet should be a function. + testString: assert(typeof realSet=='function'); + - text: realSet({"low":0, "high":1, "rangeType":2}, {"low":0, "high":2, "rangeType":3}, "union", [1, 2, 3]) should return a array. + testString: assert(Array.isArray(realSet({"low":0, "high":1, "rangeType":2}, {"low":0, "high":2, "rangeType":3}, "union", [1, 2, 3]))); + - text: realSet({"low":0, "high":1, "rangeType":2}, {"low":0, "high":2, "rangeType":3}, "union", [1, 2, 3]) should return [true, false, false]. + testString: assert.deepEqual(realSet({"low":0, "high":1, "rangeType":2}, {"low":0, "high":2, "rangeType":3}, "union", [1, 2, 3]), [true, false, false]); + - text: realSet({"low":0, "high":2, "rangeType":3}, {"low":1, "high":2, "rangeType":2}, "intersect", [0, 1, 2]) should return [false, false, false]. + testString: assert.deepEqual(realSet({"low":0, "high":2, "rangeType":3}, {"low":1, "high":2, "rangeType":2}, "intersect", [0, 1, 2]), [false, false, false]); + - text: realSet({"low":0, "high":3, "rangeType":3}, {"low":0, "high":1, "rangeType":1}, "subtract", [0, 1, 2]) should return [true, true, true]. + testString: assert.deepEqual(realSet({"low":0, "high":3, "rangeType":3}, {"low":0, "high":1, "rangeType":1}, "subtract", [0, 1, 2]), [true, true, true]); + - text: realSet({"low":0, "high":3, "rangeType":3}, {"low":0, "high":1, "rangeType":0}, "subtract", [0, 1, 2]) should return [false, false, true]. + testString: assert.deepEqual(realSet({"low":0, "high":3, "rangeType":3}, {"low":0, "high":1, "rangeType":0}, "subtract", [0, 1, 2]), [false, false, true]); + - text: realSet({"low":0, "high":33, "rangeType":1}, {"low":30, "high":31, "rangeType":0}, "intersect", [30, 31, 32]) should return [true, true, false]. + testString: assert.deepEqual(realSet({"low":0, "high":33, "rangeType":1}, {"low":30, "high":31, "rangeType":0}, "intersect", [30, 31, 32]), [true, true, false]); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function realSet(set1, set2, operation, values) { + +} +``` + +
+
+ +## Solution + +
+ +```js +function realSet(set1, set2, operation, values) { + const RangeType = { + CLOSED: 0, + BOTH_OPEN: 1, + LEFT_OPEN: 2, + RIGHT_OPEN: 3 + }; + + function Predicate(test) { + this.test = test; + this.or = function(other) { + return new Predicate(t => this.test(t) || other.test(t)); + }; + this.and = function(other) { + return new Predicate(t => this.test(t) && other.test(t)); + }; + this.negate = function() { + return new Predicate(t => !this.test(t)); + }; + } + + function RealSet(start, end, rangeType, predF) { + this.low = start; + this.high = end; + + if (predF) { + this.predicate = new Predicate(predF); + } else { + this.predicate = new Predicate(d => { + switch (rangeType) { + case RangeType.CLOSED: + return start <= d && d <= end; + case RangeType.BOTH_OPEN: + return start < d && d < end; + case RangeType.LEFT_OPEN: + return start < d && d <= end; + case RangeType.RIGHT_OPEN: + return start <= d && d < end; + } + }); + } + + this.contains = function(d) { + return this.predicate.test(d); + }; + + this.union = function(other) { + var low2 = Math.min(this.low, other.low); + var high2 = Math.max(this.high, other.high); + return new RealSet(low2, high2, null, d => + this.predicate.or(other.predicate).test(d) + ); + }; + + this.intersect = function(other) { + var low2 = Math.min(this.low, other.low); + var high2 = Math.max(this.high, other.high); + return new RealSet(low2, high2, null, d => + this.predicate.and(other.predicate).test(d) + ); + }; + + this.subtract = function(other) { + return new RealSet(this.low, this.high, null, d => + this.predicate.and(other.predicate.negate()).test(d) + ); + }; + } + set1 = new RealSet(set1.low, set1.high, set1.rangeType); + set2 = new RealSet(set2.low, set2.high, set2.rangeType); + var result = []; + values.forEach(function(value) { + result.push(set1[operation](set2).contains(value)); + }); + return result; +} +``` + +
diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/sha-1.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/sha-1.english.md new file mode 100644 index 00000000000..891a50fda31 --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/sha-1.english.md @@ -0,0 +1,168 @@ +--- +id: 5eb3e4b5f629b9a07429a5d2 +title: SHA-1 +challengeType: 5 +isHidden: false +forumTopicId: 385326 +--- + +## Description + +
+SHA-1 or SHA1 is a one-way hash function; it computes a 160-bit message digest. +SHA-1 often appears in security protocols; for example, many HTTPS websites use RSA with SHA-1 to secure their connections. +BitTorrent uses SHA-1 to verify downloads. +Git and Mercurial use SHA-1 digests to identify commits. +A US government standard, FIPS 180-1, defines SHA-1. +
+ +## Instructions + +
+Write a function that returns the SHA-1 message digest for a given string. +
+ +## Tests + +
+ +```yml +tests: + - text: SHA1 should be a function. + testString: assert(typeof SHA1 === 'function'); + - text: SHA1("abc") should return a string. + testString: assert(typeof SHA1("abc") === 'string'); + - text: SHA1("abc") should return "a9993e364706816aba3e25717850c26c9cd0d89d". + testString: assert.equal(SHA1("abc"), "a9993e364706816aba3e25717850c26c9cd0d89d"); + - text: SHA1("Rosetta Code") should return "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5". + testString: assert.equal(SHA1("Rosetta Code"), "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"); + - text: SHA1("Hello world") should return "7b502c3a1f48c8609ae212cdfb639dee39673f5e". + testString: assert.equal(SHA1("Hello world"), "7b502c3a1f48c8609ae212cdfb639dee39673f5e"); + - text: SHA1("Programming") should return "d1a946bf8b2f2a7292c250063ee28989d742cd4b". + testString: assert.equal(SHA1("Programming"), "d1a946bf8b2f2a7292c250063ee28989d742cd4b"); + - text: SHA1("is Awesome") should return "6537205da59c72b57ed3881843c2d24103d683a3". + testString: assert.equal(SHA1("is Awesome"), "6537205da59c72b57ed3881843c2d24103d683a3"); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function SHA1(input) { + +} +``` + +
+
+ +## Solution + +
+ +```js +function SHA1(input) { + var hexcase = 0; + var b64pad = ''; + var chrsz = 8; + + function hex_sha1(s) { + return binb2hex(core_sha1(str2binb(s), s.length * chrsz)); + } + + function core_sha1(x, len) { + x[len >> 5] |= 0x80 << (24 - (len % 32)); + x[(((len + 64) >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for (var i = 0; i < x.length; i += 16) { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for (var j = 0; j < 80; j++) { + if (j < 16) w[j] = x[i + j]; + else w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + var t = safe_add( + safe_add(rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j)) + ); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + } + + function sha1_ft(t, b, c, d) { + if (t < 20) return (b & c) | (~b & d); + if (t < 40) return b ^ c ^ d; + if (t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; + } + + function sha1_kt(t) { + return t < 20 + ? 1518500249 + : t < 40 + ? 1859775393 + : t < 60 + ? -1894007588 + : -899497514; + } + + function safe_add(x, y) { + var lsw = (x & 0xffff) + (y & 0xffff); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xffff); + } + + function rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + function str2binb(str) { + var bin = Array(); + var mask = (1 << chrsz) - 1; + for (var i = 0; i < str.length * chrsz; i += chrsz) + bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - (i % 32)); + return bin; + } + + function binb2hex(binarray) { + var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef'; + var str = ''; + for (var i = 0; i < binarray.length * 4; i++) { + str += + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8 + 4)) & 0xf) + + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8)) & 0xf); + } + return str; + } + + return hex_sha1(input); +} +``` + +
diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/sha-256.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/sha-256.english.md new file mode 100644 index 00000000000..1f8c333f1f3 --- /dev/null +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/sha-256.english.md @@ -0,0 +1,412 @@ +--- +id: 5eb3e4c3a894c333d2811a3f +title: SHA-256 +challengeType: 5 +isHidden: false +forumTopicId: 385328 +--- + +## Description + +
+SHA-256 is the recommended stronger alternative to SHA-1. +
+ +## Instructions + +
+Write a function that takes a string as a parameter and returns its SHA-256 digest. +
+ +## Tests + +
+ +```yml +tests: + - text: SHA256 should be a function. + testString: assert(typeof SHA256 === 'function'); + - text: SHA256("Rosetta code") should return a string. + testString: assert(typeof SHA256("Rosetta code") === 'string'); + - text: SHA256("Rosetta code") should return "764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf". + testString: assert.equal(SHA256("Rosetta code"), "764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf"); + - text: SHA256("SHA-256 Hash") should return "bee8c0cabdcf8c7835f40217dd35a8b0dba9134520e633f1c57285f35ca7ee3e". + testString: assert.equal(SHA256("SHA-256 Hash"), "bee8c0cabdcf8c7835f40217dd35a8b0dba9134520e633f1c57285f35ca7ee3e"); + - text: SHA256("implementation") should return "da31012c40330e7e21538e7dd57503b16e8a0839159e96137090cccc9910b171". + testString: assert.equal(SHA256("implementation"), "da31012c40330e7e21538e7dd57503b16e8a0839159e96137090cccc9910b171"); + - text: SHA256("algorithm") should return "b1eb2ec8ac9f31ff7918231e67f96e6deda83a9ff33ed2c67443f1df81e5ed14". + testString: assert.equal(SHA256("algorithm"), "b1eb2ec8ac9f31ff7918231e67f96e6deda83a9ff33ed2c67443f1df81e5ed14"); + - text: SHA256("language") should return "a4ef304ba42a200bafd78b046e0869af9183f6eee5524aead5dcb3a5ab5f8f3f". + testString: assert.equal(SHA256("language"), "a4ef304ba42a200bafd78b046e0869af9183f6eee5524aead5dcb3a5ab5f8f3f"); +``` + +
+ +## Challenge Seed + +
+
+ +```js +function SHA256(input) { + +} +``` + +
+
+ +## Solution + +
+ +```js +function SHA256(input) { + var chrsz = 8; + var hexcase = 0; + + function safe_add(x, y) { + var lsw = (x & 0xffff) + (y & 0xffff); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xffff); + } + + function S(X, n) { + return (X >>> n) | (X << (32 - n)); + } + + function R(X, n) { + return X >>> n; + } + + function Ch(x, y, z) { + return (x & y) ^ (~x & z); + } + + function Maj(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); + } + + function Sigma0256(x) { + return S(x, 2) ^ S(x, 13) ^ S(x, 22); + } + + function Sigma1256(x) { + return S(x, 6) ^ S(x, 11) ^ S(x, 25); + } + + function Gamma0256(x) { + return S(x, 7) ^ S(x, 18) ^ R(x, 3); + } + + function Gamma1256(x) { + return S(x, 17) ^ S(x, 19) ^ R(x, 10); + } + + function Sigma0512(x) { + return S(x, 28) ^ S(x, 34) ^ S(x, 39); + } + + function Sigma1512(x) { + return S(x, 14) ^ S(x, 18) ^ S(x, 41); + } + + function Gamma0512(x) { + return S(x, 1) ^ S(x, 8) ^ R(x, 7); + } + + function Gamma1512(x) { + return S(x, 19) ^ S(x, 61) ^ R(x, 6); + } + + function core_sha256(m, l) { + var K = new Array( + 0x428a2f98, + 0x71374491, + 0xb5c0fbcf, + 0xe9b5dba5, + 0x3956c25b, + 0x59f111f1, + 0x923f82a4, + 0xab1c5ed5, + 0xd807aa98, + 0x12835b01, + 0x243185be, + 0x550c7dc3, + 0x72be5d74, + 0x80deb1fe, + 0x9bdc06a7, + 0xc19bf174, + 0xe49b69c1, + 0xefbe4786, + 0xfc19dc6, + 0x240ca1cc, + 0x2de92c6f, + 0x4a7484aa, + 0x5cb0a9dc, + 0x76f988da, + 0x983e5152, + 0xa831c66d, + 0xb00327c8, + 0xbf597fc7, + 0xc6e00bf3, + 0xd5a79147, + 0x6ca6351, + 0x14292967, + 0x27b70a85, + 0x2e1b2138, + 0x4d2c6dfc, + 0x53380d13, + 0x650a7354, + 0x766a0abb, + 0x81c2c92e, + 0x92722c85, + 0xa2bfe8a1, + 0xa81a664b, + 0xc24b8b70, + 0xc76c51a3, + 0xd192e819, + 0xd6990624, + 0xf40e3585, + 0x106aa070, + 0x19a4c116, + 0x1e376c08, + 0x2748774c, + 0x34b0bcb5, + 0x391c0cb3, + 0x4ed8aa4a, + 0x5b9cca4f, + 0x682e6ff3, + 0x748f82ee, + 0x78a5636f, + 0x84c87814, + 0x8cc70208, + 0x90befffa, + 0xa4506ceb, + 0xbef9a3f7, + 0xc67178f2 + ); + var HASH = new Array( + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 + ); + var W = new Array(64); + var a, b, c, d, e, f, g, h, i, j; + var T1, T2; + + m[l >> 5] |= 0x80 << (24 - (l % 32)); + m[(((l + 64) >> 9) << 4) + 15] = l; + + for (var i = 0; i < m.length; i += 16) { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for (var j = 0; j < 64; j++) { + if (j < 16) W[j] = m[j + i]; + else + W[j] = safe_add( + safe_add( + safe_add(Gamma1256(W[j - 2]), W[j - 7]), + Gamma0256(W[j - 15]) + ), + W[j - 16] + ); + + T1 = safe_add( + safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), + W[j] + ); + T2 = safe_add(Sigma0256(a), Maj(a, b, c)); + + h = g; + g = f; + f = e; + e = safe_add(d, T1); + d = c; + c = b; + b = a; + a = safe_add(T1, T2); + } + + HASH[0] = safe_add(a, HASH[0]); + HASH[1] = safe_add(b, HASH[1]); + HASH[2] = safe_add(c, HASH[2]); + HASH[3] = safe_add(d, HASH[3]); + HASH[4] = safe_add(e, HASH[4]); + HASH[5] = safe_add(f, HASH[5]); + HASH[6] = safe_add(g, HASH[6]); + HASH[7] = safe_add(h, HASH[7]); + } + return HASH; + } + + function core_sha512(m, l) { + var K = new Array( + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817 + ); + var HASH = new Array( + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179 + ); + var W = new Array(80); + var a, b, c, d, e, f, g, h, i, j; + var T1, T2; + } + + function str2binb(str) { + var bin = Array(); + var mask = (1 << chrsz) - 1; + for (var i = 0; i < str.length * chrsz; i += chrsz) + bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - (i % 32)); + return bin; + } + + function binb2str(bin) { + var str = ''; + var mask = (1 << chrsz) - 1; + for (var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i >> 5] >>> (24 - (i % 32))) & mask); + return str; + } + + function binb2hex(binarray) { + var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef'; + var str = ''; + for (var i = 0; i < binarray.length * 4; i++) { + str += + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8 + 4)) & 0xf) + + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8)) & 0xf); + } + return str; + } + + function binb2b64(binarray) { + var tab = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var str = ''; + for (var i = 0; i < binarray.length * 4; i += 3) { + var triplet = + (((binarray[i >> 2] >> (8 * (3 - (i % 4)))) & 0xff) << 16) | + (((binarray[(i + 1) >> 2] >> (8 * (3 - ((i + 1) % 4)))) & 0xff) << 8) | + ((binarray[(i + 2) >> 2] >> (8 * (3 - ((i + 2) % 4)))) & 0xff); + for (var j = 0; j < 4; j++) { + if (i * 8 + j * 6 > binarray.length * 32) str += ''; + else str += tab.charAt((triplet >> (6 * (3 - j))) & 0x3f); + } + } + return str; + } + + function hex_sha2(s) { + return binb2hex(core_sha256(str2binb(s), s.length * chrsz)); + } + + function b64_sha2(s) { + return binb2b64(core_sha256(str2binb(s), s.length * chrsz)); + } + + function str_sha2(s) { + return binb2str(core_sha256(str2binb(s), s.length * chrsz)); + } + return hex_sha2(input); +} +``` + +