chore: manual translations (#42811)
This commit is contained in:
committed by
GitHub
parent
a3395269a0
commit
c4fd49e5b7
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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 < 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)
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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++) {
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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];
|
||||
}
|
||||
```
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
```
|
||||
|
@ -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];
|
||||
}
|
||||
```
|
||||
|
@ -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;
|
||||
}
|
||||
```
|
||||
|
@ -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;
|
||||
}
|
||||
```
|
||||
|
@ -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,'), [
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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++///\\'), [
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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--
|
||||
|
||||
|
@ -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
|
||||
|
@ -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');
|
||||
|
@ -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--
|
||||
|
@ -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);
|
||||
|
@ -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]
|
||||
|
@ -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--
|
||||
|
Reference in New Issue
Block a user