chore: manual translations (#42811)

This commit is contained in:
Nicholas Carrigan (he/him)
2021-07-09 21:23:54 -07:00
committed by GitHub
parent a3395269a0
commit c4fd49e5b7
806 changed files with 8935 additions and 4378 deletions

View File

@ -8,7 +8,7 @@ dashedName: abundant-deficient-and-perfect-number-classifications
# --description--
These define three classifications of positive integers based on their [proper divisors](https://rosettacode.org/wiki/Proper divisors "Proper divisors").
These define three classifications of positive integers based on their proper divisors.
Let $P(n)$ be the sum of the proper divisors of `n` where proper divisors are all positive integers `n` other than `n` itself.
@ -22,7 +22,7 @@ If `P(n) > n` then `n` is classed as `abundant`
# --instructions--
Implement a function that calculates how many of the integers from `1` to `20,000` (inclusive) are in each of the three classes. Output the result as an array in the following format `[deficient, perfect, abundant]`.
Implement a function that calculates how many of the integers from `1` to `num` (inclusive) are in each of the three classes. Output the result as an array in the following format `[deficient, perfect, abundant]`.
# --hints--
@ -32,32 +32,38 @@ Implement a function that calculates how many of the integers from `1` to `20,00
assert(typeof getDPA === 'function');
```
`getDPA` should return an array.
`getDPA(5000)` should return an array.
```js
assert(Array.isArray(getDPA(100)));
assert(Array.isArray(getDPA(5000)));
```
`getDPA` return value should have a length of 3.
`getDPA(5000)` return array should have a length of `3`.
```js
assert(getDPA(100).length === 3);
assert(getDPA(5000).length === 3);
```
`getDPA(20000)` should equal [15043, 4, 4953]
`getDPA(5000)` should return `[3758, 3, 1239]`.
```js
assert.deepEqual(getDPA(20000), solution);
assert.deepEqual(getDPA(5000), [3758, 3, 1239]);
```
`getDPA(10000)` should return `[7508, 4, 2488]`.
```js
assert.deepEqual(getDPA(10000), [7508, 4, 2488]);
```
`getDPA(20000)` should return `[15043, 4, 4953]`.
```js
assert.deepEqual(getDPA(20000), [15043, 4, 4953]);
```
# --seed--
## --after-user-code--
```js
const solution = [15043, 4, 4953];
```
## --seed-contents--
```js

View File

@ -8,35 +8,43 @@ dashedName: align-columns
# --description--
Given a text file of many lines, where fields within a line are delineated by a single `$` character, write a program that aligns each column of fields by ensuring that words in each column are separated by at least one space. Further, allow for each word in a column to be either left justified, right justified, or center justified within its column.
Given an array of many lines, where fields within a line are delineated by a single `$` character, write a program that aligns each column of fields by ensuring that words in each column are separated by at least one space. Further, allow for each word in a column to be either left justified, right justified, or center justified within its column.
# --instructions--
Use the following text to test your programs:
<pre>
Given$a$text$file$of$many$lines
where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character
write$a$program
that$aligns$each$column$of$fields
by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified
or$center$justified$within$its$column.
</pre>
```js
const testText = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$"dollar"$character',
'write$a$program',
'that$aligns$each$column$of$fields',
'by$ensuring$that$words$in$each$',
'column$are$separated$by$at$least$one$space.',
'Further,$allow$for$each$word$in$a$column$to$be$either$left$',
'justified,$right$justified',
'or$center$justified$within$its$column.'
];
```
**Note that:**
<ul>
<li>The example input texts lines may, or may not, have trailing dollar characters.</li>
<li>All columns should share the same alignment.</li>
<li>Consecutive space characters produced adjacent to the end of lines are insignificant for the purposes of the task.</li>
<li>Output text will be viewed in a mono-spaced font on a plain text editor or basic terminal.</li>
<li>The minimum space between columns should be computed from the text and not hard-coded.</li>
<li>It is not a requirement to add separating characters between or around columns.</li>
</ul>
- The example input texts lines may, or may not, have trailing dollar characters.
- All columns should share the same alignment.
- Consecutive space characters produced adjacent to the end of lines are insignificant for the purposes of the task.
- Output text will be viewed in a mono-spaced font on a plain text editor or basic terminal. Lines in it should be joined using new line character (`\n`).
- The minimum space between columns should be computed from the text and not hard-coded.
- It is not a requirement to add separating characters between or around columns.
For example, one of the lines from the `testText`, after jusitifing to the right, left and center respectivelly:
```js
' column are separated by at least one space.\n'
'column are separated by at least one space.\n'
' column are separated by at least one space.\n'
```
# --hints--
@ -46,22 +54,22 @@ or$center$justified$within$its$column.
assert(typeof formatText === 'function');
```
`formatText` with the above input and "right" justification should produce the following:
`formatText(testText, 'right')` should produce text with columns justified to the right.
```js
assert.strictEqual(formatText(testInput, 'right'), rightAligned);
assert.strictEqual(formatText(_testText, 'right'), rightAligned);
```
`formatText` with the above input and "left" justification should produce the following:
`formatText(testText, 'left')` should produce text with columns justified to the left.
```js
assert.strictEqual(formatText(testInput, 'left'), leftAligned);
assert.strictEqual(formatText(_testText, 'left'), leftAligned);
```
`formatText` with the above input and "center" justification should produce the following:
`formatText(testText, 'center')` should produce text with columns justified to the center.
```js
assert.strictEqual(formatText(testInput, 'center'), centerAligned);
assert.strictEqual(formatText(_testText, 'center'), centerAligned);
```
# --seed--
@ -69,10 +77,10 @@ assert.strictEqual(formatText(testInput, 'center'), centerAligned);
## --after-user-code--
```js
const testInput = [
const _testText = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$\"dollar\"$character',
'are$delineated$by$a$single$"dollar"$character',
'write$a$program',
'that$aligns$each$column$of$fields$',
'by$ensuring$that$words$in$each$',
@ -119,7 +127,11 @@ const centerAligned = ' Given a text file of many
## --seed-contents--
```js
const testArr = [
function formatText(input, justification) {
}
const testText = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$"dollar"$character',
@ -131,28 +143,11 @@ const testArr = [
'justified,$right$justified',
'or$center$justified$within$its$column.'
];
function formatText(input, justification) {
}
```
# --solutions--
```js
const testArr = [
'Given$a$text$file$of$many$lines',
'where$fields$within$a$line$',
'are$delineated$by$a$single$"dollar"$character',
'write$a$program',
'that$aligns$each$column$of$fields$',
'by$ensuring$that$words$in$each$',
'column$are$separated$by$at$least$one$space.',
'Further,$allow$for$each$word$in$a$column$to$be$either$left$',
'justified,$right$justified',
'or$center$justified$within$its$column.'
];
String.prototype.repeat = function (n) { return new Array(1 + parseInt(n)).join(this); };
function formatText(input, justification) {

View File

@ -8,9 +8,9 @@ dashedName: closest-pair-problem
# --description--
Provide a function to find the closest two points among a set of given points in two dimensions, i.e. to solve the [Closest pair of points problem](https://en.wikipedia.org/wiki/Closest pair of points problem "wp: Closest pair of points problem") in the *planar* case.
Provide a function to find the closest two points among a set of given points in two dimensions.
The straightforward solution is a O(n<sup>2</sup>) algorithm (which we can call *brute-force algorithm*); the pseudo-code (using indexes) could be simply:
The straightforward solution is a $O(n^2)$ algorithm (which we can call *brute-force algorithm*); the pseudo-code (using indexes) could be simply:
<pre><strong>bruteForceClosestPair</strong> of P(1), P(2), ... P(N)
<strong>if</strong> N &#x3C; 2 <strong>then</strong>
@ -30,7 +30,7 @@ The straightforward solution is a O(n<sup>2</sup>) algorithm (which we can call
<strong>endif</strong>
</pre>
A better algorithm is based on the recursive divide and conquer approach, as explained also at [Wikipedia's Closest pair of points problem](https://en.wikipedia.org/wiki/Closest pair of points problem#Planar_case "wp: Closest pair of points problem#Planar_case"), which is `O(nlog(n))` a pseudo-code could be:
A better algorithm is based on the recursive divide and conquer approach, which is $O(n\log n)$ a pseudo-code could be:
<pre><strong>closestPair</strong> of (xP, yP)
where xP is P(1) .. P(N) sorted by x coordinate, and
@ -65,16 +65,38 @@ A better algorithm is based on the recursive divide and conquer approach, as exp
<strong>endif</strong>
</pre>
For the input, expect the argument to be an array of objects (points) with `x` and `y` members set to numbers. For the output, return an object containing the key:value pairs for `distance` and `pair` (the pair of two closest points).
For the input, expect the argument to be an array of `Point` objects with `x` and `y` members set to numbers. Return an object containing the key:value pairs for `distance` and `pair` (the pair of two closest points).
**References and further readings:**
For example `getClosestPair` with input array `points`:
```js
const points = [
new Point(1, 2),
new Point(3, 3),
new Point(2, 2)
];
```
Would return:
```js
{
distance: 1,
pair: [
{
x: 1,
y: 2
},
{
x: 2,
y: 2
}
]
}
```
**Note:** Sort the `pair` array by their `x` values in incrementing order.
<ul>
<li><a href='https://en.wikipedia.org/wiki/Closest pair of points problem' title='wp: Closest pair of points problem' target='_blank'>Closest pair of points problem</a></li>
<li><a href='https://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPairDQ.html' target='_blank'>Closest Pair (McGill)</a></li>
<li><a href='https://www.cs.ucsb.edu/~suri/cs235/ClosestPair.pdf' target='_blank'>Closest Pair (UCSB)</a></li>
<li><a href='https://classes.cec.wustl.edu/~cse241/handouts/closestpair.pdf' target='_blank'>Closest pair (WUStL)</a></li>
</ul>
# --hints--
@ -84,13 +106,13 @@ For the input, expect the argument to be an array of objects (points) with `x` a
assert(typeof getClosestPair === 'function');
```
Distance should be the following.
`getClosestPair(points1).distance` should be `0.0894096443343775`.
```js
assert.equal(getClosestPair(points1).distance, answer1.distance);
```
Points should be the following.
`getClosestPair(points1).pair` should be `[ { x: 7.46489, y: 4.6268 }, { x: 7.46911, y: 4.71611 } ]`.
```js
assert.deepEqual(
@ -99,13 +121,13 @@ assert.deepEqual(
);
```
Distance should be the following.
`getClosestPair(points2).distance` should be `65.06919393998976`.
```js
assert.equal(getClosestPair(points2).distance, answer2.distance);
```
Points should be the following.
`getClosestPair(points2).pair` should be `[ { x: 37134, y: 1963 }, { x: 37181, y: 2008 } ]`.
```js
assert.deepEqual(
@ -114,6 +136,21 @@ assert.deepEqual(
);
```
`getClosestPair(points3).distance` should be `6754.625082119658`.
```js
assert.equal(getClosestPair(points3).distance, answer3.distance);
```
`getClosestPair(points3).pair` should be `[ { x: 46817, y: 64975 }, { x: 48953, y: 58567 } ]`.
```js
assert.deepEqual(
JSON.parse(JSON.stringify(getClosestPair(points3))).pair,
answer3.pair
);
```
# --seed--
## --after-user-code--
@ -132,14 +169,6 @@ const points1 = [
new Point(1.45428, 0.087596)
];
const points2 = [
new Point(37100, 13118),
new Point(37134, 1963),
new Point(37181, 2008),
new Point(37276, 21611),
new Point(37307, 9320)
];
const answer1 = {
distance: 0.0894096443343775,
pair: [
@ -154,6 +183,14 @@ const answer1 = {
]
};
const points2 = [
new Point(37100, 13118),
new Point(37134, 1963),
new Point(37181, 2008),
new Point(37276, 21611),
new Point(37307, 9320)
];
const answer2 = {
distance: 65.06919393998976,
pair: [
@ -168,8 +205,8 @@ const answer2 = {
]
};
const benchmarkPoints = [
new Point(16909, 54699),
const points3 = [
new Point(16910, 54699),
new Point(14773, 61107),
new Point(95547, 45344),
new Point(95951, 17573),
@ -196,7 +233,7 @@ const benchmarkPoints = [
new Point(70721, 66707),
new Point(31863, 9837),
new Point(49358, 30795),
new Point(13041, 39745),
new Point(13041, 39744),
new Point(59635, 26523),
new Point(25859, 1292),
new Point(1551, 53890),
@ -220,6 +257,20 @@ const benchmarkPoints = [
new Point(51090, 52158),
new Point(48953, 58567)
];
const answer3 = {
distance: 6754.625082119658,
pair: [
{
x: 46817,
y: 64975
},
{
x: 48953,
y: 58567
}
]
}
```
## --seed-contents--
@ -347,7 +398,7 @@ const closestPair = function _closestPair(Px, Py) {
return {
distance: minDelta,
pair: closestPair
pair: closestPair.sort((pointA, pointB) => pointA.x - pointB.x)
};
};

View File

@ -22,7 +22,7 @@ Demonstrate that it passes the following three test-cases:
| Input number | Output number |
| ------------ | ------------------------- |
| 7259 | <code>2 hr, 59 sec</code> |
| 728640059 | <code>1 d</code> |
| 86400 | <code>1 d</code> |
| 6000000 | <code>9 wk, 6 d, 10 hr, 40 min</code> |
<div style="font-size:115%; font-weight: bold;">Details</div>

View File

@ -30,7 +30,7 @@ There are four types of common coins in [US](https://en.wikipedia.org/wiki/Unite
# --instructions--
Implement a function to determine how many ways there are to make change for a dollar using these common coins (1 dollar = 100 cents)
Implement a function to determine how many ways there are to make change for a given input, `cents`, that represents an amount of US pennies using these common coins.
# --hints--
@ -40,10 +40,22 @@ Implement a function to determine how many ways there are to make change for a d
assert(typeof countCoins === 'function');
```
`countCoins()` should return 242.
`countCoins(15)` should return `6`.
```js
assert.equal(countCoins(), 242);
assert.equal(countCoins(15), 6);
```
`countCoins(85)` shouls return `163`.
```js
assert.equal(countCoins(85), 163);
```
`countCoins(100)` should return `242`.
```js
assert.equal(countCoins(100), 242);
```
# --seed--
@ -51,7 +63,7 @@ assert.equal(countCoins(), 242);
## --seed-contents--
```js
function countCoins() {
function countCoins(cents) {
return true;
}
@ -60,12 +72,11 @@ function countCoins() {
# --solutions--
```js
function countCoins() {
let t = 100;
function countCoins(cents) {
const operands = [1, 5, 10, 25];
const targetsLength = t + 1;
const targetsLength = cents + 1;
const operandsLength = operands.length;
t = [1];
const t = [1];
for (let a = 0; a < operandsLength; a++) {
for (let b = 1; b < targetsLength; b++) {

View File

@ -13,51 +13,82 @@ A given rectangle is made from *m* × *n* squares. If *m* and *n* are not both o
<div style="width: 100%; text-align: center;">
<svg xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink" width="520" height="170" aria-hidden="true" alt="Diagram showing the possible paths for 2 by 2 and 4 by 3 rectangles">
<style>
.g { fill: none; stroke: #ccc }
.s, .s2 { fill: #bff; stroke: black; fill-opacity: .4 }
.s2 { fill: #fbf }
.d { stroke:black; fill:none}
.diagram-g { fill: none; stroke: #ccc }
.diagram-s, .diagram-s2 { fill: #bff; stroke: black; fill-opacity: .4 }
.diagram-s2 { fill: #fbf }
.diagram-d { stroke:black; fill:none}
</style>
<defs> <g id="m">
<g id="h4"><g id="h2">
<path id="h" d="m0 10h 640" class="g"/>
<use xlink:href="#h" transform="translate(0,20)"/></g>
<use xlink:href="#h2" transform="translate(0, 40)"/></g>
<use xlink:href="#h4" transform="translate(0,80)"/>
<g id="v8"><g id="v4"><g id="v2">
<path id="v" d="m10 0v160 m 20 0 v-160" class="g"/>
<use xlink:href="#v" transform="translate(40,0)"/></g>
<use xlink:href="#v2" transform="translate(80,0)"/></g>
<use xlink:href="#v4" transform="translate(160,0)"/></g>
<use xlink:href="#v8" transform="translate(320,0)"/></g>
<path id="b" d="m0 0h80v60h-80z" class="s"/>
<defs>
<g id="diagram-m">
<g id="diagram-h4">
<g id="diagram-h2">
<path id="diagram-h" d="m0 10h 640" class="diagram-g"/>
<use xlink:href="#diagram-h" transform="translate(0, 20)"/>
</g>
<use xlink:href="#diagram-h2" transform="translate(0, 40)"/>
</g>
<use xlink:href="#diagram-h4" transform="translate(0, 80)"/>
<g id="diagram-v8">
<g id="diagram-v4">
<g id="diagram-v2">
<path id="diagram-v" d="m10 0v160 m 20 0 v-160" class="diagram-g"/>
<use xlink:href="#diagram-v" transform="translate(40, 0)"/>
</g>
<use xlink:href="#diagram-v2" transform="translate(80, 0)"/>
</g>
<use xlink:href="#diagram-v4" transform="translate(160, 0)"/>
</g>
<use xlink:href="#diagram-v8" transform="translate(320, 0)"/>
</g>
<path id="diagram-b" d="m0 0h80v60h-80z" class="diagram-s"/>
</defs>
<g transform="translate(.5,.5)">
<use xlink:href="#m"/>
<g transform="translate(10,10)">
<path d="m0 0v40h40v-40z" class="s2"/><path d="m20 0v40" class="d"/>
<path d="m60 0v40h40v-40z" class="s2"/><path d="m60 20h40" class="d"/>
<g transform="translate(120, 0)">
<use xlink:href="#b"/><path d="m0 20h40v20h40" class="d"/></g>
<g transform="translate(220, 0)">
<use xlink:href="#b"/><path d="m0 40h40v-20h40" class="d"/></g>
<g transform="translate(320, 0)">
<use xlink:href="#b"/><path d="m20 0v40h20v-20h20v40" class="d"/></g>
<g transform="translate(420, 0)">
<use xlink:href="#b"/><path d="m60 0v40h-20v-20h-20v40" class="d"/></g>
<g transform="translate(20, 80)">
<use xlink:href="#b"/><path d="m40 0v60" class="d"/></g>
<g transform="translate(120, 80)">
<use xlink:href="#b"/><path d="m60 0v20h-20v20h-20v20" class="d"/></g>
<g transform="translate(220, 80)">
<use xlink:href="#b"/><path d="m20 0v20h20v20h20v20" class="d"/></g>
<g transform="translate(320, 80)">
<use xlink:href="#b"/><path d="m0 20h20v20h20v-20h20v20h20" class="d"/></g>
<g transform="translate(420, 80)">
<use xlink:href="#b"/><path d="m0 40h20v-20h20v20h20v-20h20" class="d"/></g>
</g></g>
</svg>
</div>
<g transform="translate(.5, .5)">
<use xlink:href="#diagram-m"/>
<g transform="translate(10, 10)">
<path d="m0 0v40h40v-40z" class="diagram-s2"/>
<path d="m20 0v40" class="diagram-d"/>
<path d="m60 0v40h40v-40z" class="diagram-s2"/>
<path d="m60 20h40" class="diagram-d"/>
<g transform="translate(120, 0)">
<use xlink:href="#diagram-b"/>
<path d="m0 20h40v20h40" class="diagram-d"/>
</g>
<g transform="translate(220, 0)">
<use xlink:href="#diagram-b"/>
<path d="m0 40h40v-20h40" class="diagram-d"/>
</g>
<g transform="translate(320, 0)">
<use xlink:href="#diagram-b"/>
<path d="m20 0v40h20v-20h20v40" class="diagram-d"/>
</g>
<g transform="translate(420, 0)">
<use xlink:href="#diagram-b"/>
<path d="m60 0v40h-20v-20h-20v40" class="diagram-d"/>
</g>
<g transform="translate(20, 80)">
<use xlink:href="#diagram-b"/>
<path d="m40 0v60" class="diagram-d"/>
</g>
<g transform="translate(120, 80)">
<use xlink:href="#diagram-b"/>
<path d="m60 0v20h-20v20h-20v20" class="diagram-d"/>
</g>
<g transform="translate(220, 80)">
<use xlink:href="#diagram-b"/>
<path d="m20 0v20h20v20h20v20" class="diagram-d"/>
</g>
<g transform="translate(320, 80)">
<use xlink:href="#diagram-b"/>
<path d="m0 20h20v20h20v-20h20v20h20" class="diagram-d"/>
</g>
<g transform="translate(420, 80)">
<use xlink:href="#diagram-b"/>
<path d="m0 40h20v-20h20v20h20v-20h20" class="diagram-d"/>
</g>
</g>
</g>
</svg>
</div>
# --instructions--

View File

@ -8,14 +8,20 @@ dashedName: date-format
# --description--
Return an array with the current date in the formats:
Return an array with two date strings of the current date with the following specifications:
<ul>
<li>2007-11-23</li>
<li>Friday, November 23, 2007</li>
</ul>
- The first string's date order should be the year number, month number, and day number separated by dashes (`-`).
- The first string's year should be four digits in length.
- The first string's month and day should not contain any leading zeros.
- The second string's weekday and month names should not be abbreviated.
- The second string's day should not contain any leading zeros.
Example output: `['2007-11-23', 'Friday, November 23, 2007']`
Example outputs:
```js
['2007-11-23', 'Friday, November 23, 2007']
['2021-3-2', 'Tuesday, March 2, 2021']
```
# --hints--

View File

@ -82,7 +82,7 @@ assert.deepEqual(emirps([7700, 8000], true), [
]);
```
`emirps([7700,8000],true)` should return `11`
`emirps([7700,8000],false)` should return `11`
```js
assert.deepEqual(emirps([7700, 8000], false), 11);

View File

@ -40,13 +40,7 @@ the shop -> my brother
a never used -> .terminating rule
</pre>
Sample text of:
`I bought a B of As from T S.`
Should generate the output:
`I bought a bag of apples from my brother.`
Sample text of `I bought a B of As from T S.` should generate the output `I bought a bag of apples from my brother.`
**Ruleset 2:**
@ -61,13 +55,7 @@ the shop -> my brother
a never used -> .terminating rule
</pre>
Sample text of:
`I bought a B of As from T S.`
Should generate:
`I bought a bag of apples from T shop.`
Sample text of `I bought a B of As from T S.` should generate `I bought a bag of apples from T shop.`
**Ruleset 3:**
@ -86,13 +74,7 @@ the shop -> my brother
a never used -> .terminating rule
</pre>
Sample text of:
`I bought a B of As W my Bgage from T S.`
Should generate:
`I bought a bag of apples with my money from T shop.`
Sample text of `I bought a B of As W my Bgage from T S.` should generate `I bought a bag of apples with my money from T shop.`
**Ruleset 4:**
@ -128,13 +110,7 @@ _1 -> 1
_+_ ->
</pre>
Sample text of:
`_1111*11111_`
should generate the output:
`11111111111111111111`
Sample text of `_1111*11111_` should generate the output `11111111111111111111`
**Ruleset 5:**
@ -164,13 +140,7 @@ B1 -> 1B
1C1 -> H11
</pre>
This ruleset should turn
`000000A000000`
into
`00011H1111000`
This ruleset should turn `000000A000000` into `00011H1111000`
# --hints--

View File

@ -54,7 +54,7 @@ As in other trial division algorithms, the algorithm stops when `2kP+1 > sqrt(N)
# --instructions--
Using the above method find a factor of <code>2<sup>929</sup>-1</code> (aka M929)
Using the above method find a factor of <code>2<sup>p</sup>-1</code>.
# --hints--
@ -70,19 +70,19 @@ assert(typeof check_mersenne === 'function');
assert(typeof check_mersenne(3) == 'string');
```
`check_mersenne(3)` should return "M3 = 2^3-1 is prime".
`check_mersenne(3)` should return the string `M3 = 2^3-1 is prime`.
```js
assert.equal(check_mersenne(3), 'M3 = 2^3-1 is prime');
```
`check_mersenne(23)` should return "M23 = 2^23-1 is composite with factor 47".
`check_mersenne(23)` should return the string `M23 = 2^23-1 is composite with factor 47`.
```js
assert.equal(check_mersenne(23), 'M23 = 2^23-1 is composite with factor 47');
```
`check_mersenne(929)` should return "M929 = 2^929-1 is composite with factor 13007
`check_mersenne(929)` should return the string `M929 = 2^929-1 is composite with factor 13007`.
```js
assert.equal(

View File

@ -10,29 +10,18 @@ dashedName: hailstone-sequence
The Hailstone sequence of numbers can be generated from a starting positive integer, `n` by:
<ul>
<li>If <code>n</code> is <code>1</code> then the sequence ends</li>
<li>If <code>n</code> is <code>even</code> then the next <code>n</code> of the sequence <code>= n/2</code></li>
<li>If <code>n</code> is <code>odd</code> then the next <code>n</code> of the sequence <code>= (3 * n) + 1</code></li>
</ul>
- If `n` is `1` then the sequence ends
- If `n` is `even` then the next `n` of the sequence `= n/2`
- If `n` is `odd` then the next `n` of the sequence `= (3 * n) + 1`
The (unproven) [Collatz conjecture](https://en.wikipedia.org/wiki/Collatz conjecture "wp: Collatz conjecture") is that the hailstone sequence for any starting number always terminates.
The (unproven) Collatz conjecture is that the hailstone sequence for any starting number always terminates.
The hailstone sequence is also known as hailstone numbers (because the values are usually subject to multiple descents and ascents like hailstones in a cloud), or as the Collatz sequence.
# --instructions--
<ol>
<li>Create a routine to generate the hailstone sequence for a number</li>
<li>Use the routine to show that the hailstone sequence for the number 27 has 112 elements starting with <code>27, 82, 41, 124</code> and ending with <code>8, 4, 2, 1</code></li>
<li>Show the number less than 100,000 which has the longest hailstone sequence together with that sequence's length. (But don't show the actual sequence!)</li>
</ol>
**See also:**
<ul>
<li><a href='https://xkcd.com/710' target='_blank'>xkcd</a> (humourous).</li>
</ul>
1. Create a routine to generate the hailstone sequence for a number
2. Your function should return an array with the number less than `limit` which has the longest hailstone sequence and that sequence's length. (But don't show the actual sequence!)
# --hints--
@ -42,24 +31,36 @@ The hailstone sequence is also known as hailstone numbers (because the values ar
assert(typeof hailstoneSequence === 'function');
```
`hailstoneSequence()` should return `[[27,82,41,124,8,4,2,1], [351, 77031]]`
`hailstoneSequence(30)` should return an array.
```js
assert.deepEqual(hailstoneSequence(), res);
assert(Array.isArray(hailstoneSequence(30)));
```
`hailstoneSequence(30)` should return `[27, 112]`.
```js
assert.deepEqual(hailstoneSequence(30), [27, 112]);
```
`hailstoneSequence(50000)` should return `[35655, 324]`.
```js
assert.deepEqual(hailstoneSequence(50000), [35655, 324]);
```
`hailstoneSequence(100000)` should return `[77031, 351]`.
```js
assert.deepEqual(hailstoneSequence(100000), [77031, 351]);
```
# --seed--
## --after-user-code--
```js
const res = [[27, 82, 41, 124, 8, 4, 2, 1], [351, 77031]];
```
## --seed-contents--
```js
function hailstoneSequence() {
function hailstoneSequence(limit) {
const res = [];
@ -70,9 +71,7 @@ function hailstoneSequence() {
# --solutions--
```js
function hailstoneSequence () {
const res = [];
function hailstoneSequence (limit) {
function hailstone(n) {
const seq = [n];
while (n > 1) {
@ -82,13 +81,9 @@ function hailstoneSequence () {
return seq;
}
const h = hailstone(27);
const hLen = h.length;
res.push([...h.slice(0, 4), ...h.slice(hLen - 4, hLen)]);
let n = 0;
let max = 0;
for (let i = 100000; --i;) {
for (let i = limit; --i;) {
const seq = hailstone(i);
const sLen = seq.length;
@ -97,8 +92,7 @@ function hailstoneSequence () {
max = sLen;
}
}
res.push([max, n]);
return res;
return [n, max];
}
```

View File

@ -30,67 +30,67 @@ assert(typeof happy === 'function');
assert(typeof happy(1) === 'boolean');
```
`happy(1)` should return true.
`happy(1)` should return `true`.
```js
assert(happy(1));
```
`happy(2)` should return false.
`happy(2)` should return `false`.
```js
assert(!happy(2));
```
`happy(7)` should return true.
`happy(7)` should return `true`.
```js
assert(happy(7));
```
`happy(10)` should return true.
`happy(10)` should return `true`.
```js
assert(happy(10));
```
`happy(13)` should return true.
`happy(13)` should return `true`.
```js
assert(happy(13));
```
`happy(19)` should return true.
`happy(19)` should return `true`.
```js
assert(happy(19));
```
`happy(23)` should return true.
`happy(23)` should return `true`.
```js
assert(happy(23));
```
`happy(28)` should return true.
`happy(28)` should return `true`.
```js
assert(happy(28));
```
`happy(31)` should return true.
`happy(31)` should return `true`.
```js
assert(happy(31));
```
`happy(32)` should return true:.
`happy(32)` should return `true`.
```js
assert(happy(32));
```
`happy(33)` should return false.
`happy(33)` should return `false`.
```js
assert(!happy(33));

View File

@ -10,7 +10,7 @@ dashedName: harshad-or-niven-series
The Harshad or Niven numbers are positive integers ≥ 1 that are divisible by the sum of their digits.
For example, `42` is a [Harshad number](https://rosettacode.org/wiki/Harshad_or_Niven_series "Harshad or Niven series") as `42` is divisible by `(4 + 2)` without remainder.
For example, `42` is a Harshad number as `42` is divisible by `(4 + 2)` without remainder.
Assume that the series is defined as the numbers in increasing order.
@ -18,7 +18,7 @@ Assume that the series is defined as the numbers in increasing order.
Implement a function to generate successive members of the Harshad sequence.
Use it to list the first twenty members of the sequence and list the first Harshad number greater than 1000.
Use it to return an array with ten members of the sequence, starting with first Harshad number greater than `n`.
# --hints--
@ -28,32 +28,31 @@ Use it to list the first twenty members of the sequence and list the first Harsh
assert(typeof isHarshadOrNiven === 'function');
```
`isHarshadOrNiven()` should return `{"firstTwenty": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 18, 20, 21, 24, 27, 30, 36, 40, 42],"firstOver1000": 1002}`
`isHarshadOrNiven(10)` should return `[12, 18, 20, 21, 24, 27, 30, 36, 40, 42]`
```js
assert.deepEqual(isHarshadOrNiven(), res);
assert.deepEqual(isHarshadOrNiven(10), [12, 18, 20, 21, 24, 27, 30, 36, 40, 42]);
```
`isHarshadOrNiven(400)` should return `[402, 405, 407, 408, 410, 414, 420, 423, 432, 440]`
```js
assert.deepEqual(isHarshadOrNiven(400), [402, 405, 407, 408, 410, 414, 420, 423, 432, 440]);
```
`isHarshadOrNiven(1000)` should return `[1002, 1008, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1020]`
```js
assert.deepEqual(isHarshadOrNiven(1000), [1002, 1008, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1020]);
```
# --seed--
## --after-user-code--
```js
const res = {
firstTwenty: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 18, 20, 21, 24, 27, 30, 36, 40, 42],
firstOver1000: 1002
};
```
## --seed-contents--
```js
function isHarshadOrNiven() {
const res = {
firstTwenty: [],
firstOver1000: undefined
};
// Only change code below this line
function isHarshadOrNiven(n) {
const res = [];
return res;
}
@ -62,37 +61,27 @@ function isHarshadOrNiven() {
# --solutions--
```js
function isHarshadOrNiven() {
const res = {
firstTwenty: [],
firstOver1000: undefined
};
function isHarshad(n) {
function isHarshadOrNiven(n) {
function isHarshad(num) {
let s = 0;
const nStr = n.toString();
const nStr = num.toString();
for (let i = 0; i < nStr.length; ++i) {
s += parseInt(nStr.charAt(i), 10);
}
return n % s === 0;
}
const res = [];
let count = 0;
const harshads = [];
for (let n = 1; count < 20; ++n) {
while (count < 10) {
n++;
if (isHarshad(n)) {
count++;
harshads.push(n);
res.push(n);
}
}
res.firstTwenty = harshads;
let h = 1000;
while (!isHarshad(++h));
res.firstOver1000 = h;
return res;
}
```

View File

@ -42,34 +42,34 @@ assert(typeof josephus == 'function');
assert(typeof josephus(30, 3) == 'number');
```
`josephus(30,3)` should return `29`.
`josephus(30,3)` should return `28`.
```js
assert.equal(josephus(30, 3), 29);
assert.equal(josephus(30, 3), 28);
```
`josephus(30,5)` should return `3`.
`josephus(30,5)` should return `2`.
```js
assert.equal(josephus(30, 5), 3);
assert.equal(josephus(30, 5), 2);
```
`josephus(20,2)` should return `9`.
`josephus(20,2)` should return `8`.
```js
assert.equal(josephus(20, 2), 9);
assert.equal(josephus(20, 2), 8);
```
`josephus(17,6)` should return `2`.
`josephus(17,6)` should return `1`.
```js
assert.equal(josephus(17, 6), 2);
assert.equal(josephus(17, 6), 1);
```
`josephus(29,4)` should return `2`.
`josephus(29,4)` should return `1`.
```js
assert.equal(josephus(29, 4), 2);
assert.equal(josephus(29, 4), 1);
```
# --seed--
@ -86,36 +86,13 @@ function josephus(init, kill) {
```js
function josephus(init, kill) {
var Josephus = {
init: function(n) {
this.head = {};
var current = this.head;
for (var i = 0; i < n - 1; i++) {
current.label = i + 1;
current.next = {
prev: current
};
current = current.next;
}
current.label = n;
current.next = this.head;
this.head.prev = current;
return this;
},
kill: function(spacing) {
var current = this.head;
while (current.next !== current) {
for (var i = 0; i < spacing - 1; i++) {
current = current.next;
}
current.prev.next = current.next;
current.next.prev = current.prev;
current = current.next;
}
return current.label;
}
const arr = Array.from(Array(init).keys());
let curr = -1
while (arr.length > 1) {
curr = (curr + kill) % arr.length;
arr.splice(curr, 1);
curr--;
}
return Josephus.init(init).kill(kill)
return arr[0];
}
```

View File

@ -73,7 +73,7 @@ assert.equal(
);
```
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 35, 0.35)` should return `75300`.
`knapsackUnbounded([{ name:"panacea", value:3000, weight:0.3, volume:0.025 }, { name:"ichor", value:1800, weight:0.2, volume:0.015 }, { name:"gold", value:2500, weight:2, volume:0.002 }], 35, 0.35)` should return `75900`.
```js
assert.equal(
@ -86,7 +86,7 @@ assert.equal(
35,
0.35
),
75300
75900
);
```
@ -120,36 +120,66 @@ function knapsackUnbounded(items, maxweight, maxvolume) {
# --solutions--
```js
function knapsackUnbounded(items, maxweight, maxvolume) {
var n = items.length;
var best_value = 0;
var count = new Array(n);
var best = new Array(n);
function recurseKnapsack(i, value, weight, volume) {
var j, m1, m2, m;
if (i == n) {
if (value > best_value) {
best_value = value;
for (j = 0; j < n; j++) {
best[j] = count[j];
}
}
return;
function knapsackUnbounded(items, maxWeight, maxVolume) {
function getPickTotals(items, pick) {
let totalValue = 0;
let totalWeight = 0;
let totalVolume = 0;
for (let i = 0; i < items.length; i++) {
totalValue += pick[i] * items[i].value;
totalWeight += pick[i] * items[i].weight;
totalVolume += pick[i] * items[i].volume;
}
m1 = Math.floor(weight / items[i].weight);
m2 = Math.floor(volume / items[i].volume);
m = m1 < m2 ? m1 : m2;
for (count[i] = m; count[i] >= 0; count[i]--) {
recurseKnapsack(
i + 1,
value + count[i] * items[i].value,
weight - count[i] * items[i].weight,
volume - count[i] * items[i].volume
);
return [totalValue, totalWeight, totalVolume];
}
function getMaxes(items, maxWeight, maxVolume) {
const maxes = [];
for (let i = 0; i < items.length; i++) {
const maxUnitsInWeight = Math.floor(maxWeight / items[i].weight);
const maxUnitsInVolume = Math.floor(maxVolume / items[i].volume);
const maxUnitsInLimit = Math.min(maxUnitsInWeight, maxUnitsInVolume);
maxes.push(maxUnitsInLimit);
}
return maxes;
}
function isInLimit(value, limit) {
return value <= limit;
}
function getCombinations(maxValues, curPicks, combinations) {
if (maxValues.length === 0) {
combinations.push(curPicks);
}
const curMax = maxValues[0];
const leftMaxValues = maxValues.slice(1);
for (let i = 0; i <= curMax; i++) {
getCombinations(leftMaxValues, curPicks.concat(i), combinations);
}
return combinations;
}
let bestValue = 0;
let bestPick = [];
const maxes = getMaxes(items, maxWeight, maxVolume);
const combinations = getCombinations(maxes, [], []);
for (let i = 0; i < combinations.length; i++) {
const curPick = combinations[i];
const [curValue, curWeight, curVolume] = getPickTotals(items, curPick);
if (!isInLimit(curWeight, maxWeight) || !isInLimit(curVolume, maxVolume)) {
continue;
}
if (curValue > bestValue) {
bestValue = curValue;
bestPick = [curPick];
} else if (curValue === bestValue) {
bestPick.push(curPick);
}
}
recurseKnapsack(0, 0, maxweight, maxvolume);
return best_value;
return bestValue;
}
```

View File

@ -8,7 +8,7 @@ dashedName: knights-tour
# --description--
[Knight's Tour](https://en.wikipedia.org/wiki/Knight%27s_tour)Problem: 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.
[Knight's Tour](https://en.wikipedia.org/wiki/Knight%27s_tour) Problem: 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--
@ -28,34 +28,34 @@ assert(typeof knightTour == 'function');
assert(typeof knightTour(6, 6) == 'number');
```
`knightTour(6, 6)` should return `35`.
`knightTour(6, 6)` should return `36`.
```js
assert.equal(knightTour(6, 6), 35);
assert.equal(knightTour(6, 6), 36);
```
`knightTour(5, 6)` should return `20`.
`knightTour(5, 6)` should return `30`.
```js
assert.equal(knightTour(5, 6), 20);
assert.equal(knightTour(5, 6), 30);
```
`knightTour(4, 6)` should return `10`.
`knightTour(4, 6)` should return `12`.
```js
assert.equal(knightTour(4, 6), 10);
assert.equal(knightTour(4, 6), 12);
```
`knightTour(7, 3)` should return `4`.
`knightTour(7, 3)` should return `10`.
```js
assert.equal(knightTour(7, 3), 4);
assert.equal(knightTour(7, 3), 10);
```
`knightTour(8, 6)` should return `47`.
`knightTour(8, 6)` should return `48`.
```js
assert.equal(knightTour(8, 6), 47);
assert.equal(knightTour(8, 6), 48);
```
# --seed--
@ -72,83 +72,154 @@ function knightTour(w, h) {
```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 < h; i++) {
for (j = 0; j < w; j++) {
b[i][j] = 255;
}
function createBoards(rows, columns) {
const board = [];
const visited = [];
for (let i = 0; i < rows; i++) {
board.push(new Array(columns).fill(-1));
visited.push(new Array(columns).fill(false));
}
return [board, visited];
}
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
for (k = 0; k < 8; k++) {
(x = j + dx[k]), (y = i + dy[k]);
if (b[i][j] == 255) b[i][j] = 0;
if (x >= 0 && x < w && y >= 0 && y < h) b[i][j]++;
}
function copyBoard(board) {
const copied = [];
for (let i = 0; i < board.length; i++) {
copied.push([...board[i]]);
}
return copied;
}
function isOnBoard(value, limit) {
return value >= 0 && value < limit;
}
function markVisited(board, visited, row, column) {
visited[row][column] = true;
board[row][column] = -1;
}
function areAllVisited(visited) {
return (
visited.filter(row => row.filter(column => column === false).length !== 0)
.length === 0
);
}
function getMovesFrom(board, row, column) {
const possibleMoves = [];
for (let i = 0; i < moves.length; i++) {
const [rowChange, colChange] = moves[i];
const [rowN, colN] = [row + rowChange, column + colChange];
if (!isOnBoard(rowN, board.length) || !isOnBoard(colN, board[0].length)) {
continue;
}
possibleMoves.push([rowN, colN]);
}
return possibleMoves;
}
function fillAllowedMovesCounts(board) {
for (let row = 0; row < board.length; row++) {
for (let column = 0; column < board[0].length; column++) {
board[row][column] = getMovesFrom(board, row, column).length;
}
}
}
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];
}
function updateAllowedMovesCounts(board, possibleMoves) {
for (let i = 0; i < possibleMoves.length; i++) {
const [row, column] = possibleMoves[i];
if (board[row][column] > 0) {
board[row][column]--;
}
}
}
if (least > 7) {
return steps == w * h - 1;
function getBestNextMoves(board, allowedMoves) {
let bestMoves = [];
let fewestNextMoves = Infinity;
let zeroMove = [];
for (let i = 0; i < allowedMoves.length; i++) {
const [moveRow, moveCol] = allowedMoves[i];
const numMoves = board[moveRow][moveCol];
if (numMoves === -1) {
continue;
}
if (numMoves === 0) {
zeroMove.push(allowedMoves[i]);
}
if (numMoves < fewestNextMoves) {
bestMoves = [allowedMoves[i]];
fewestNextMoves = numMoves;
} else if (numMoves === fewestNextMoves) {
bestMoves.push(allowedMoves[i]);
}
steps++;
(x = nx), (y = ny);
}
if (bestMoves.length > 0) {
return bestMoves;
}
return zeroMove;
}
function solve(x, y) {
b = new Array(h);
for (var i = 0; i < h; i++) b[i] = new Array(w);
init_board();
if (walk_board(x, y)) {
cnt++;
function solve(board, visited, lastRow, lastColumn) {
if (areAllVisited(visited)) {
return true;
}
const nextMoves = getMovesFrom(board, lastRow, lastColumn);
updateAllowedMovesCounts(board, nextMoves);
const allowedMoves = nextMoves.filter(
([row, column]) => !visited[row][column]
);
const bestMoves = getBestNextMoves(board, allowedMoves);
const restMoves = allowedMoves.filter(
move => bestMoves.indexOf(move) === -1
);
const possibleMoves = [...bestMoves];
possibleMoves.push(...getBestNextMoves(board, restMoves));
for (let i = 0; i < possibleMoves.length; i++) {
const [moveRow, moveCol] = possibleMoves[i];
const newBoard = copyBoard(board);
const newVisited = copyBoard(visited);
markVisited(newBoard, newVisited, moveRow, moveCol);
if (solve(newBoard, newVisited, moveRow, moveCol)) {
return true;
}
}
return false;
}
for (var i = 0; i < h; i++) {
for (var j = 0; j < w; j++) {
solve(j, i);
}
function solveStart(board, visited, startRow, startColumn) {
const newBoard = copyBoard(board);
const newVisited = copyBoard(visited);
markVisited(newBoard, newVisited, startRow, startColumn);
return solve(newBoard, newVisited, startRow, startColumn);
}
return cnt;
const moves = [
[-1, -2],
[-2, -1],
[-2, 1],
[-1, 2],
[1, 2],
[2, 1],
[2, -1],
[1, -2]
];
const [baseBoard, baseVisited] = createBoards(h, w);
fillAllowedMovesCounts(baseBoard);
let solvedCount = 0;
for (let row = 0; row < h; row++) {
for (let column = 0; column < w; column++) {
if (solveStart(baseBoard, baseVisited, row, column)) {
solvedCount++;
}
}
}
return solvedCount;
}
```

View File

@ -34,7 +34,7 @@ assert(typeof letterFrequency == 'function');
assert(Array.isArray(letterFrequency('Not all that Mrs. Bennet, however')));
```
`letterFrequency("Not all that Mrs. Bennet, however")` should return `[[" ", 5], [", ", 1], [".", 1], ["B", 1], ["M", 1], ["N", 1], ["a", 2], ["e", 4], ["h", 2], ["l", 2], ["n", 2], ["o", 2], ["r", 2], ["s", 1], ["t", 4], ["v", 1], ["w", 1]]`.
`letterFrequency("Not all that Mrs. Bennet, however")` should return `[[" ", 5], [",", 1], [".", 1], ["B", 1], ["M", 1], ["N", 1], ["a", 2], ["e", 4], ["h", 2], ["l", 2], ["n", 2], ["o", 2], ["r", 2], ["s", 1], ["t", 4], ["v", 1], ["w", 1]]`.
```js
assert.deepEqual(letterFrequency('Not all that Mrs. Bennet, however'), [
@ -58,7 +58,7 @@ assert.deepEqual(letterFrequency('Not all that Mrs. Bennet, however'), [
]);
```
`letterFrequency("daughters, could ask on the ")` should return `[[' ',5],[',',1],['a',2],['c',1],['d',2],['e',2],['g',1],['h',2],['k',1],['l',1],['n',1],['o',2],['r',1],['s',2],['t',2],['u',2]]`.
`letterFrequency("daughters, could ask on the ")` should return `[[" ", 5],[",", 1],["a", 2],["c", 1],["d", 2],["e", 2],["g", 1],["h", 2],["k", 1],["l", 1],["n", 1],["o", 2],["r", 1],["s", 2],["t", 2],["u", 2]]`.
```js
assert.deepEqual(letterFrequency('daughters, could ask on the '), [
@ -131,7 +131,7 @@ assert.deepEqual(letterFrequency('in various ways--with barefaced'), [
]);
```
`letterFrequency("distant surmises; but he eluded")` should return `[[" ", 4], ["; ", 1], ["a", 1], ["b", 1], ["d", 3], ["e", 4], ["h", 1], ["i", 2], ["l", 1], ["m", 1], ["n", 1], ["r", 1], ["s", 4], ["t", 3], ["u", 3]]`.
`letterFrequency("distant surmises; but he eluded")` should return `[[" ", 4], [";", 1], ["a", 1], ["b", 1], ["d", 3], ["e", 4], ["h", 1], ["i", 2], ["l", 1], ["m", 1], ["n", 1], ["r", 1], ["s", 4], ["t", 3], ["u", 3]]`.
```js
assert.deepEqual(letterFrequency('distant surmises; but he eluded'), [
@ -153,7 +153,7 @@ assert.deepEqual(letterFrequency('distant surmises; but he eluded'), [
]);
```
`letterFrequency("last obliged to accept the second-hand,")` should return `[[" ", 5], [", ", 1], ["-", 1], ["a", 3], ["b", 1], ["c", 3], ["d", 3], ["e", 4], ["g", 1], ["h", 2], ["i", 1], ["l", 2], ["n", 2], ["o", 3], ["p", 1], ["s", 2], ["t", 4]]`.
`letterFrequency("last obliged to accept the second-hand,")` should return `[[" ", 5], [",", 1], ["-", 1], ["a", 3], ["b", 1], ["c", 3], ["d", 3], ["e", 4], ["g", 1], ["h", 2], ["i", 1], ["l", 2], ["n", 2], ["o", 3], ["p", 1], ["s", 2], ["t", 4]]`.
```js
assert.deepEqual(letterFrequency('last obliged to accept the second-hand,'), [

View File

@ -12,11 +12,15 @@ Loop over multiple arrays and create a new array whose $i^{th}$ element is the c
For this example, if you are given this array of arrays:
`[ ["a", "b", "c"], ["A", "B", "C"], [1, 2, 3] ]`
```js
[ ["a", "b", "c"], ["A", "B", "C"], [1, 2, 3] ]
```
the output should be:
`["aA1","bB2","cC3"]`
```js
["aA1","bB2","cC3"]
```
# --instructions--

View File

@ -22,9 +22,9 @@ Newlines and other whitespace may be ignored unless contained within a quoted st
Handling escaped quotes inside a string is optional; thus "`(foo"bar)`" may be treated as a string "`foo"bar`", or as an error.
For this, the reader need not recognize "<code>\\</code>" for escaping, but should, in addition, recognize numbers if the language has appropriate data types.
For this, the reader need not recognize `\` for escaping, but should, in addition, recognize numbers if the language has appropriate data types.
Note that with the exception of "`()"`" ("<code>\\</code>" if escaping is supported) and whitespace there are no special characters. Anything else is allowed without quotes.
Note that with the exception of `()"` (`\` if escaping is supported) and whitespace, there are no special characters. Anything else is allowed without quotes.
The reader should be able to read the following input
@ -48,7 +48,7 @@ assert(typeof parseSexpr === 'function');
assert.deepEqual(parseSexpr(simpleSExpr), simpleSolution);
```
`parseSexpr('(data1 data2 data3)')` should return an array with 3 elements.
`parseSexpr('((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))')` should return `[['data', '"quoted data"', 123, 4.5], ['data', ['!@#', [4.5], '"(more"', '"data)"']]]`.
```js
assert.deepEqual(parseSexpr(basicSExpr), basicSolution);

View File

@ -8,11 +8,11 @@ dashedName: sha-256
# --description--
**[SHA-256](https://en.wikipedia.org/wiki/SHA-256)** is the recommended stronger alternative to [SHA-1](https://rosettacode.org/wiki/SHA-1).
The `SHA-2` family is a stronger alternative to `SHA-1`. The main difference between them is the length of the hash. Meaning `SHA-1` provides a shorter code with fewer possibilities for unique combinations. `SHA-2` or `SHA-256` creates a longer and thus more complex hash with more possibilities.
# --instructions--
Write a function that takes a string as a parameter and returns its SHA-256 digest.
Research implemenation details and write a function that takes a string as the parameter and returns a hash using `SHA-256`
# --hints--

View File

@ -14,7 +14,9 @@ Make your function work with the following list of values and set of indices:
<code>values: [7, <b>6</b>, 5, 4, 3, 2, <b>1</b>, <b>0</b>]</code>
`indices(0-based): {6, 1, 7}`
```js
indices(0-based): {6, 1, 7}
```
Where the correct result would be:

View File

@ -11,13 +11,13 @@ dashedName: split-a-character-string-based-on-change-of-character
Split a (character) string into comma (plus a blank) delimited strings based on a change of character (left to right). Blanks should be treated as any other character (except they are problematic to display clearly). The same applies to commas. For instance, the string:
<pre>
"gHHH5YY++///\"
"gHHH5YY++///\\"
</pre>
should be split as:
<pre>
["g", "HHH", "5", "YY", "++", "///", "\" ];
["g", "HHH", "5", "YY", "++", "///", "\\" ];
</pre>
# --hints--
@ -80,7 +80,7 @@ assert.deepEqual(split('sssmmmaaammmaaat'), [
]);
```
`split("gHHH5YY++///\")` should return `["g", "HHH", "5", "YY", "++", "///", "\\"]`.
`split("gHHH5YY++///\\")` should return `["g", "HHH", "5", "YY", "++", "///", "\\"]`.
```js
assert.deepEqual(split('gHHH5YY++///\\'), [

View File

@ -8,7 +8,7 @@ dashedName: sudoku
# --description--
Write a function to solve a partially filled-in normal 9x9 [Sudoku](https://en.wikipedia.org/wiki/Sudoku) grid and return the result. The blank fields are represented by 0s. [Algorithmics of Sudoku](https://en.wikipedia.org/wiki/Algorithmics_of_sudoku) may help implement this.
Write a function to solve a partially filled-in normal 9x9 [Sudoku](https://en.wikipedia.org/wiki/Sudoku) grid and return the result. The blank fields are represented by `-1`. [Algorithmics of Sudoku](https://en.wikipedia.org/wiki/Algorithmics_of_sudoku) may help implement this.
# --hints--

View File

@ -8,7 +8,7 @@ dashedName: sum-of-a-series
# --description--
Compute the **n**<sup>th</sup> term of a [series](https://en.wikipedia.org/wiki/Series (mathematics)), i.e. the sum of the **n** first terms of the corresponding [sequence](https://en.wikipedia.org/wiki/sequence). Informally this value, or its limit when **n** tends to infinity, is also called the *sum of the series*, thus the title of this task. For this task, use: $S*n = \\sum*{k=1}^n \\frac{1}{k^2}$ and compute $S\_{1000}$ This approximates the [zeta function](https://en.wikipedia.org/wiki/Riemann zeta function) for S=2, whose exact value $\\zeta(2) = {\\pi^2\\over 6}$ is the solution of the [Basel problem](https://en.wikipedia.org/wiki/Basel problem).
Compute the **n**<sup>th</sup> term of a [series](https://en.wikipedia.org/wiki/Series (mathematics)), i.e. the sum of the **n** first terms of the corresponding [sequence](https://en.wikipedia.org/wiki/sequence). Informally this value, or its limit when **n** tends to infinity, is also called the *sum of the series*, thus the title of this task. For this task, use: $S_n = \displaystyle\sum_{k=1}^n \frac{1}{k^2}$.
# --instructions--

View File

@ -60,16 +60,6 @@ assert.deepEqual(sumTo100(243), [
]);
```
`sumTo100(199)` should return `["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"]`.
```js
assert.deepEqual(sumTo100(199), [
'-1+2-3+45+67+89',
'123-4+5+6+78-9',
'123-4+56+7+8+9'
]);
```
`sumTo100(197)` should return `["1-2-3+45+67+89", "12+34-5+67+89", "123+4-5+6+78-9"]`.
```js

View File

@ -12,7 +12,8 @@ Find the top `n` ranked data in each group, where `n` is provided as a parameter
Given the following data:
<pre>[
```js
testData1 = [
{ name: 'Tyler Bennett', id: 'E10297', salary: 32000, dept: 'D101' },
{ name: 'John Rappl', id: 'E21437', salary: 47000, dept: 'D050' },
{ name: 'George Woltman', id: 'E00127', salary: 53500, dept: 'D101' },
@ -27,29 +28,56 @@ Given the following data:
{ name: 'Kim Arlich', id: 'E10001', salary: 57000, dept: 'D190' },
{ name: 'Timothy Grove', id: 'E16398', salary: 29900, dept: 'D190' }
];
</pre>
```
one could rank top 10 employees in each department by calling
One could rank top 10 employees in each department by calling:
`topRankPerGroup(10, data, 'dept', 'salary')`
```js
topRankPerGroup(10, testData1, 'dept', 'salary')
```
Given the following data:
<pre>[
```js
testData2 = [
{ name: 'Friday 13th', genre: 'horror', rating: 9.9 },
{ name: "Nightmare on Elm's Street", genre: 'horror', rating: 5.7 },
{ name: 'Titanic', genre: 'drama', rating: 7.3 },
{ name: 'Maze Runner', genre: 'scifi', rating: 7.1 },
{ name: 'Blade runner', genre: 'scifi', rating: 8.9 }
];
</pre>
```
one could rank the top-rated movie in each genre by calling
One could rank the top-rated movie in each genre by calling:
`topRankPerGroup(1, data, 'genre', 'rating')`
```js
topRankPerGroup(1, testData2, 'genre', 'rating')
```
The function should return an array with an array for each group containing the top `n` objects.
For example, given data:
```js
[
{ name: 'Claire Buckman', id: 'E39876', salary: 27800, dept: 'D101' },
{ name: 'Rich Holcomb', id: 'E01234', salary: 49500, dept: 'D050' },
{ name: 'David Motsinger', id: 'E27002', salary: 19250, dept: 'D050' },
{ name: 'Tim Sampair', id: 'E03033', salary: 27000, dept: 'D101' },
{ name: 'Kim Arlich', id: 'E10001', salary: 57000, dept: 'D050' },
{ name: 'Timothy Grove', id: 'E16398', salary: 29900, dept: 'D101' }
];
```
Top two ranking employees in each department by salary would be:
```js
[ [ { name: 'Kim Arlich', id: 'E10001', salary: 57000, dept: 'D050' },
{ name: 'Rich Holcomb', id: 'E01234', salary: 49500, dept: 'D050' } ],
[ { name: 'Timothy Grove', id: 'E16398', salary: 29900, dept: 'D101' },
{ name: 'Claire Buckman', id: 'E39876', salary: 27800, dept: 'D101' } ] ]
```
# --hints--
`topRankPerGroup` should be a function.
@ -64,22 +92,16 @@ assert(typeof topRankPerGroup === 'function');
assert(typeof topRankPerGroup(-1, []) === 'undefined');
```
First department should be D050
For `topRankPerGroup(10, testData1, 'dept', 'salary')`, the first result in the first group should be `{ name: 'John Rappl', id: 'E21437', salary: 47000, dept: 'D050'}`.
```js
assert.equal(res1[0][0].dept, 'D050');
assert.deepEqual(res1[0][0], { name: 'John Rappl', id: 'E21437', salary: 47000, dept: 'D050'});
```
First department should be D050
For `topRankPerGroup(10, testData1, 'dept', 'salary')`, the last result in the last group should be `{ name: 'Adam Smith', id: 'E63535', salary: 18000, dept: 'D202' }`.
```js
assert.equal(res1[0][1].salary, 21900);
```
The last department should be D202
```js
assert.equal(res1[3][3].dept, 'D202');
assert.deepEqual(res1[3][3], { name: 'Adam Smith', id: 'E63535', salary: 18000, dept: 'D202' });
```
`topRankPerGroup(1, ...)` should return only top ranking result per group.
@ -88,7 +110,7 @@ assert.equal(res1[3][3].dept, 'D202');
assert.equal(res2[2].length, 1);
```
`topRankPerGroup(1, ...)` should return only top ranking result per group.
`topRankPerGroup(2, ...)` should return two ranking results per group.
```js
assert.equal(res3[2][1].name, 'Maze Runner');

View File

@ -8,19 +8,19 @@ dashedName: topological-sort
# --description--
Given a mapping between items, and items they depend on, a [topological sort](https://en.wikipedia.org/wiki/Topological sorting "wp: Topological sorting") orders items so that no item precedes an item it depends upon. The compiling of a library in the [VHDL](https://en.wikipedia.org/wiki/VHDL "wp: VHDL") language has the constraint that a library must be compiled after any library it depends on.
Given a mapping between items, and items they depend on, a topological sort orders items so that no item precedes an item it depends upon. There are two popular algorithms for topological sorting: Kahn's (1962) topological sort and depth-first search.
# --instructions--
Write a function that will return a valid compile order of VHDL libraries from their dependencies.
Write a function that will return a list with valid compile order of libraries from their dependencies.
- Assume library names are single words.
- Items mentioned as only dependents have no dependents of their own, but their order of compiling must be given.
- Any self dependencies should be ignored.
- Any un-orderable dependencies should be ignored.
<ul>
<li>Assume library names are single words.</li>
<li>Items mentioned as only dependents have no dependents of their own, but their order of compiling must be given.</li>
<li>Any self dependencies should be ignored.</li>
<li>Any un-orderable dependencies should be ignored.</li>
</ul>
Use the following data as an example:
<pre>
LIBRARY LIBRARY DEPENDENCIES
======= ====================
@ -38,16 +38,18 @@ ramlib std ieee
std_cell_lib ieee std_cell_lib
synopsys
</pre>
<small>Note: the above data would be un-orderable if, for example, <code>dw04</code> is added to the list of dependencies of <code>dw01</code>.</small>
<strong>C.f.:</strong>
<ul>
<li><a href="https://rosettacode.org/wiki/Topological sort/Extracted top item" title="Topological sort/Extracted top item" target="_blank">Topological sort/Extracted top item</a>.</li>
</ul>
There are two popular algorithms for topological sorting:
<ul>
<li><a href="https://en.wikipedia.org/wiki/Topological sorting" title="wp: Topological sorting" target="_blank">Kahn's 1962 topological sort</a></li>
<li><a href="https://www.embeddedrelated.com/showarticle/799.php" target="_blank">depth-first search</a></li>
</ul>
The compiling of a library in the VHDL language has the constraint that a library must be compiled after any library it depends on. The above data would be un-orderable if, for example, `dw04` is added to the list of dependencies of `dw01`.
The input of the function will be a multiline string, each line will consist of the name of the library, followed by its dependencies (if exist).
For example:
```js
const libsSimple =
`aaa bbb
bbb`;
```
# --hints--
@ -57,28 +59,34 @@ There are two popular algorithms for topological sorting:
assert(typeof topologicalSort === 'function');
```
`topologicalSort` should return correct library order.
`topologicalSort(libsSimple)` should return an array.
```js
assert(Array.isArray(topologicalSort(libsSimple)));
```
`topologicalSort(libsSimple)` should return `['bbb', 'aaa']`.
```js
assert.deepEqual(topologicalSort(libsSimple), ['bbb', 'aaa']);
```
`topologicalSort` should return correct library order.
`topologicalSort(libsVHDL)` should return `['ieee', 'std_cell_lib', 'gtech', 'dware', 'dw07', 'dw06', 'dw05', 'dw02', 'dw01', 'dw04', 'std', 'ramlib', 'synopsys', 'dw03', 'des_system_lib']`.
```js
assert.deepEqual(topologicalSort(libsVHDL), solutionVHDL);
assert.deepEqual(topologicalSort(libsVHDL), ['ieee', 'std_cell_lib', 'gtech', 'dware', 'dw07', 'dw06', 'dw05', 'dw02', 'dw01', 'dw04', 'std', 'ramlib', 'synopsys', 'dw03', 'des_system_lib']);
```
`topologicalSort` should return correct library order.
`topologicalSort(libsCustom)` should return `['base', 'c', 'd', 'b', 'a']`.
```js
assert.deepEqual(topologicalSort(libsCustom), solutionCustom);
assert.deepEqual(topologicalSort(libsCustom), ['base', 'c', 'd', 'b', 'a']);
```
`topologicalSort` should ignore unorderable dependencies.
```js
assert.deepEqual(topologicalSort(libsUnorderable), solutionUnorderable);
assert.deepEqual(topologicalSort(libsUnorderable), ['Base']);
```
# --seed--
@ -105,26 +113,17 @@ const libsVHDL =
std_cell_lib ieee std_cell_lib
synopsys`;
const solutionVHDL = [
'ieee', 'std_cell_lib', 'gtech', 'dware', 'dw07', 'dw06',
'dw05', 'dw02', 'dw01', 'dw04', 'std', 'ramlib', 'synopsys',
'dw03', 'des_system_lib'
];
const libsCustom =
`a b c d
b c d
d c
c base
base`;
const solutionCustom = ['base', 'c', 'd', 'b', 'a'];
const libsUnorderable =
`TestLib Base MainLib
MainLib TestLib
Base`;
const solutionUnorderable = ['Base'];
```
## --seed-contents--

View File

@ -16,19 +16,19 @@ Write a function that takes two vectors (arrays) as input and computes their cro
# --hints--
dotProduct should be a function.
`crossProduct` should be a function.
```js
assert.equal(typeof crossProduct, 'function');
```
dotProduct() should return null.
`crossProduct()` should return null.
```js
assert.equal(crossProduct(), null);
```
crossProduct([1, 2, 3], [4, 5, 6]) should return [-3, 6, -3].
`crossProduct([1, 2, 3], [4, 5, 6])` should return `[-3, 6, -3]`.
```js
assert.deepEqual(res12, exp12);

View File

@ -14,42 +14,145 @@ The decimal number eleven can be written as `0*13 + 1*8 + 0*5 + 1*3 + 0*2 + 0*1`
# --instructions--
Write a function that generates and returns an array of the first `n` Zeckendorf numbers in order.
Write a function that generates and returns the Zeckendorf number representation of `n`.
# --hints--
zeckendorf should be function.
`zeckendorf` should be a function.
```js
assert.equal(typeof zeckendorf, 'function');
```
Your `zeckendorf` function should return the correct answer.
`zeckendorf(0)` should return `0`.
```js
assert.deepEqual(answer, solution20);
assert.equal(zeckendorf(0), 0);
```
`zeckendorf(1)` should return `1`.
```js
assert.equal(zeckendorf(1), 1);
```
`zeckendorf(2)` should return `10`.
```js
assert.equal(zeckendorf(2), 10);
```
`zeckendorf(3)` should return `100`.
```js
assert.equal(zeckendorf(3), 100);
```
`zeckendorf(4)` should return `101`.
```js
assert.equal(zeckendorf(4), 101);
```
`zeckendorf(5)` should return `1000`.
```js
assert.equal(zeckendorf(5), 1000);
```
`zeckendorf(6)` should return `1001`.
```js
assert.equal(zeckendorf(6), 1001);
```
`zeckendorf(7)` should return `1010`.
```js
assert.equal(zeckendorf(7), 1010);
```
`zeckendorf(8)` should return `10000`.
```js
assert.equal(zeckendorf(8), 10000);
```
`zeckendorf(9)` should return `10001`.
```js
assert.equal(zeckendorf(9), 10001);
```
`zeckendorf(10)` should return `10010`.
```js
assert.equal(zeckendorf(10), 10010);
```
`zeckendorf(11)` should return `10100`.
```js
assert.equal(zeckendorf(11), 10100);
```
`zeckendorf(12)` should return `10101`.
```js
assert.equal(zeckendorf(12), 10101);
```
`zeckendorf(13)` should return `100000`.
```js
assert.equal(zeckendorf(13), 100000);
```
`zeckendorf(14)` should return `100001`.
```js
assert.equal(zeckendorf(14), 100001);
```
`zeckendorf(15)` should return `100010`.
```js
assert.equal(zeckendorf(15), 100010);
```
`zeckendorf(16)` should return `100100`.
```js
assert.equal(zeckendorf(16), 100100);
```
`zeckendorf(17)` should return `100101`.
```js
assert.equal(zeckendorf(17), 100101);
```
`zeckendorf(18)` should return `101000`.
```js
assert.equal(zeckendorf(18), 101000);
```
`zeckendorf(19)` should return `101001`.
```js
assert.equal(zeckendorf(19), 101001);
```
`zeckendorf(20)` should return `101010`.
```js
assert.equal(zeckendorf(20), 101010);
```
# --seed--
## --after-user-code--
```js
const range = (m, n) => (
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i)
);
const solution20 = [
'1', '10', '100', '101', '1000', '1001', '1010', '10000', '10001',
'10010', '10100', '10101', '100000', '100001', '100010', '100100', '100101',
'101000', '101001', '101010'
];
const answer = range(1, 20).map(zeckendorf);
```
## --seed-contents--
```js
@ -61,13 +164,13 @@ function zeckendorf(n) {
# --solutions--
```js
// zeckendorf :: Int -> String
// zeckendorf :: Int -> Int
function zeckendorf(n) {
const f = (m, x) => (m < x ? [m, 0] : [m - x, 1]);
return (n === 0 ? ([0]) :
return parseInt((n === 0 ? ([0]) :
mapAccumL(f, n, reverse(
tail(fibUntil(n))
))[1]).join('');
))[1]).join(''));
}
// fibUntil :: Int -> [Int]

View File

@ -10,87 +10,68 @@ dashedName: zhang-suen-thinning-algorithm
This is an algorithm used to thin a black and white i.e. one bit per pixel images. For example, with an input image of:
<!-- TODO write fully in markdown>
<!-- markdownlint-disable -->
<pre>
################# #############
################## ################
################### ##################
######## ####### ###################
###### ####### ####### ######
###### ####### #######
################# #######
################ #######
################# #######
###### ####### #######
###### ####### #######
###### ####### ####### ######
######## ####### ###################
######## ####### ###### ################## ######
######## ####### ###### ################ ######
######## ####### ###### ############# ######
</pre>
```js
const testImage1 = [
' ',
'######### ######## ',
'### #### #### #### ',
'### ### ### ### ',
'### #### ### ',
'######### ### ',
'### #### ### ### ',
'### #### ### #### #### ### ',
'### #### ### ######## ### ',
' '
];
```
It produces the thinned output:
<pre>
```js
[ ' ',
'######## ###### ',
'# # ## ',
'# # # ',
'# # # ',
'###### # # ',
'# ## # ',
'# # # ## ## # ',
'# # #### ',
' ' ];
```
# ########## #######
## # #### #
# # ##
# # #
# # #
# # #
############ #
# # #
# # #
# # #
# # #
# ##
# ############
### ###
</pre>
<h2>Algorithm</h2>
## Algorithm
Assume black pixels are one and white pixels zero, and that the input image is a rectangular N by M array of ones and zeroes. The algorithm operates on all black pixels P1 that can have eight neighbours. The neighbours are, in order, arranged as:
<table border="3">
<tr><td style="text-align: center;">P9</td><td style="text-align: center;">P2</td><td style="text-align: center;">P3</td></tr>
<tr><td style="text-align: center;">P8</td><td style="text-align: center;"><strong>P1</strong></td><td style="text-align: center;">P4</td></tr>
<tr><td style="text-align: center;">P7</td><td style="text-align: center;">P6</td><td style="text-align: center;">P5</td></tr>
</table>
$$\begin{array}{|c|c|c|} \\hline P9 & P2 & P3\\\\ \\hline P8 & \boldsymbol{P1} & P4\\\\ \\hline P7 & P6 & P5\\\\ \\hline \end{array}$$
Obviously the boundary pixels of the image cannot have the full eight neighbours.
<ul>
<li>Define $A(P1)$ = the number of transitions from white to black, (0 -> 1) in the sequence P2, P3, P4, P5, P6, P7, P8, P9, P2. (Note the extra P2 at the end - it is circular).</li>
<li>Define $B(P1)$ = the number of black pixel neighbours of P1. ( = sum(P2 .. P9) )</li>
</ul>
- Define $A(P1)$ = the number of transitions from white to black, ($0 \to 1$) in the sequence P2, P3, P4, P5, P6, P7, P8, P9, P2. (Note the extra P2 at the end - it is circular).
- Define $B(P1)$ = the number of black pixel neighbours of P1. ($= \\sum(P2 \ldots P9)$)
**Step 1:**
All pixels are tested and pixels satisfying all the following conditions (simultaneously) are just noted at this stage. <ol>
<li>The pixel is black and has eight neighbours</li>
<li>$2 <= B(P1) <= 6$</li>
<li>$A(P1) = 1$</li>
<li>At least one of <strong>P2, P4 and P6</strong> is white</li>
<li>At least one of <strong>P4, P6 and P8</strong> is white</li>
</ol>
All pixels are tested and pixels satisfying all the following conditions (simultaneously) are just noted at this stage.
1. The pixel is black and has eight neighbours
2. $2 \le B(P1) \le 6$
3. $A(P1) = 1$
4. At least one of $P2$, $P4$ and $P6$ is white
5. At least one of $P4$, $P6$ and $P8$ is white
After iterating over the image and collecting all the pixels satisfying all step 1 conditions, all these condition satisfying pixels are set to white.
**Step 2:**
All pixels are again tested and pixels satisfying all the following conditions are just noted at this stage. <ol>
<li>The pixel is black and has eight neighbours</li>
<li>$2 <= B(P1) <= 6$</li>
<li>$A(P1) = 1$</li>
<li>At least one of <strong>P2, P4 and P8</strong> is white</li>
<li>At least one of <strong>P2, P6 and P8</strong> is white</li>
</ol>
All pixels are again tested and pixels satisfying all the following conditions are just noted at this stage.
1. The pixel is black and has eight neighbours
2. $2 \le B(P1) \le 6$
3. $A(P1) = 1$
4. At least one of $P2$, $P4$ and $P8$ is white
5. At least one of $P2$, $P6$ and $P8$ is white
After iterating over the image and collecting all the pixels satisfying all step 2 conditions, all these condition satisfying pixels are again set to white.
@ -100,7 +81,7 @@ If any pixels were set in this round of either step 1 or step 2 then all steps a
# --instructions--
Write a routine to perform Zhang-Suen thinning on the provided image matrix.
Write a routine to perform Zhang-Suen thinning on the provided `image`, an array of strings, where each string represents single line of the image. In the string, `#` represents black pixel, and whitespace represents white pixel. Function should return thinned image, using the same representation.
# --hints--
@ -113,19 +94,25 @@ assert.equal(typeof thinImage, 'function');
`thinImage` should return an array.
```js
assert(Array.isArray(result));
assert(Array.isArray(thinImage(_testImage1)));
```
`thinImage` should return an array of strings.
```js
assert.equal(typeof result[0], 'string');
assert.equal(typeof thinImage(_testImage1)[0], 'string');
```
`thinImage` should return an array of strings.
`thinImage(testImage1)` should return a thinned image as in the example.
```js
assert.deepEqual(result, expected);
assert.deepEqual(thinImage(_testImage1), expected1);
```
`thinImage(testImage2)` should return a thinned image.
```js
assert.deepEqual(thinImage(_testImage2), expected2);
```
# --seed--
@ -133,7 +120,31 @@ assert.deepEqual(result, expected);
## --after-user-code--
```js
const imageForTests = [
const _testImage1 = [
' ',
'######### ######## ',
'### #### #### #### ',
'### ### ### ### ',
'### #### ### ',
'######### ### ',
'### #### ### ### ',
'### #### ### #### #### ### ',
'### #### ### ######## ### ',
' '
];
const expected1 = [
' ',
'######## ###### ',
'# # ## ',
'# # # ',
'# # # ',
'###### # # ',
'# ## # ',
'# # # ## ## # ',
'# # #### ',
' '
];
const _testImage2 = [
' ',
' ################# ############# ',
' ################## ################ ',
@ -152,7 +163,7 @@ const imageForTests = [
' ######## ####### ###### ################ ###### ',
' ######## ####### ###### ############# ###### ',
' '];
const expected = [
const expected2 = [
' ',
' ',
' # ########## ####### ',
@ -172,35 +183,27 @@ const expected = [
' ',
' '
];
const result = thinImage(imageForTests);
```
## --seed-contents--
```js
const testImage = [
' ',
' ################# ############# ',
' ################## ################ ',
' ################### ################## ',
' ######## ####### ################### ',
' ###### ####### ####### ###### ',
' ###### ####### ####### ',
' ################# ####### ',
' ################ ####### ',
' ################# ####### ',
' ###### ####### ####### ',
' ###### ####### ####### ',
' ###### ####### ####### ###### ',
' ######## ####### ################### ',
' ######## ####### ###### ################## ###### ',
' ######## ####### ###### ################ ###### ',
' ######## ####### ###### ############# ###### ',
' '];
function thinImage(image) {
}
const testImage1 = [
' ',
'######### ######## ',
'### #### #### #### ',
'### ### ### ### ',
'### #### ### ',
'######### ### ',
'### #### ### ### ',
'### #### ### #### #### ### ',
'### #### ### ######## ### ',
' '
];
```
# --solutions--