Skip to content

Commit 3702c7d

Browse files
✨ feat: Add rotateLeft and rotateRight.
1 parent 38e9a89 commit 3702c7d

File tree

10 files changed

+9620
-27
lines changed

10 files changed

+9620
-27
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
ArrayLike rotation for JavaScript.
55
See [docs](https://array-like.github.io/rotate/index.html).
66

7-
> :building_construction: Caveat emptor! This is work in progress. Code may be
8-
> working. Documentation may be present. Coherence may be. Maybe.
7+
```js
8+
import {range} from '@iterable-iterator/range';
9+
import {rotateLeft} from '@array-like/rotate';
910

10-
> :warning: Depending on your environment, the code may require
11-
> `regeneratorRuntime` to be defined, for instance by importing
12-
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
11+
const a = Array.from(range(5));
12+
rotateLeft(a, 0, 5, 2);
13+
a; // 2 3 4 0 1
14+
```
1315

1416
[![License](https://img.shields.io/github/license/array-like/rotate.svg)](https://raw.githubusercontent.com/array-like/rotate/main/LICENSE)
1517
[![Version](https://img.shields.io/npm/v/@array-like/rotate.svg)](https://www.npmjs.org/package/@array-like/rotate)

doc/manual/usage.md

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
11
# Usage
22

3-
> :warning: Depending on your environment, the code may require
4-
> `regeneratorRuntime` to be defined, for instance by importing
5-
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
6-
7-
First, require the polyfill at the entry point of your application
8-
```js
9-
await import('regenerator-runtime/runtime.js');
10-
// or
11-
import 'regenerator-runtime/runtime.js';
12-
```
13-
14-
Then, import the library where needed
3+
Import the library where needed
154
```js
16-
const rotate = await import('@array-like/rotate');
5+
const {rotateLeft, rotateRight} = await import('@array-like/rotate');
176
// or
18-
import * as rotate from '@array-like/rotate';
7+
import {rotateLeft, rotateRight} from '@array-like/rotate';
198
```

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,13 @@
5959
"release": "np --message ':hatching_chick: release: Bumping to v%s.'",
6060
"test": "ava"
6161
},
62-
"dependencies": {},
62+
"dependencies": {
63+
"@array-like/reverse": "^0.0.1"
64+
},
6365
"devDependencies": {
66+
"@array-like/alloc": "^0.0.1",
67+
"@array-like/copy": "^0.0.1",
68+
"@array-like/fill": "^0.0.1",
6469
"@babel/core": "7.14.8",
6570
"@babel/preset-env": "7.14.8",
6671
"@babel/register": "7.14.5",

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const answer = 42;
2-
export default answer;
1+
export {default as rotateLeft} from './rotateLeft.js';
2+
export {default as rotateRight} from './rotateRight.js';

src/rotateLeft.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import rotateRight from './rotateRight.js';
2+
3+
/**
4+
* Rotate array values k places to the left in-place in time O(j-i).
5+
*
6+
* See http://prakhar.me/articles/the-string-rotation-problem/.
7+
*
8+
* @param {{[x: number]: any}} a
9+
* @param {number} i
10+
* @param {number} j
11+
* @param {number} k
12+
*/
13+
const rotateLeft = (a, i, j, k) => rotateRight(a, i, j, j - i - k);
14+
15+
export default rotateLeft;

src/rotateRight.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import assert from 'assert';
2+
import {reverse} from '@array-like/reverse';
3+
4+
/**
5+
* Rotate array values k places to the right in-place in time O(j-i).
6+
*
7+
* See http://prakhar.me/articles/the-string-rotation-problem/.
8+
*
9+
* @param {{[x: number]: any}} a
10+
* @param {number} i
11+
* @param {number} j
12+
* @param {number} k
13+
*/
14+
const rotateRight = (a, i, j, k) => {
15+
assert(k >= 0);
16+
assert(k <= j - i);
17+
reverse(a, i, j);
18+
reverse(a, i, i + k);
19+
reverse(a, i + k, j);
20+
};
21+
22+
export default rotateRight;

test/src/api.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/src/rotateLeft.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import test from 'ava';
2+
3+
import {alloc} from '@array-like/alloc';
4+
import {iota} from '@array-like/fill';
5+
import {copy} from '@array-like/copy';
6+
7+
import {rotateLeft} from '../../src/index.js';
8+
9+
const macro = (t, n, k) => {
10+
const a = alloc(n);
11+
iota(a, 0, n, 0);
12+
13+
const reference = alloc(n);
14+
copy(a, 0, n, reference, 0);
15+
16+
rotateLeft(a, 0, n, k);
17+
t.is(a.length, n, 'length did not change');
18+
19+
const expected = reference.slice(k).concat(reference.slice(0, k));
20+
t.deepEqual(a, expected, 'works as expected');
21+
};
22+
23+
macro.title = (title, n, k) => title ?? `${n} - ${k}`;
24+
25+
test(macro, 1000, 0);
26+
test(macro, 1000, 1);
27+
test(macro, 1000, 2);
28+
test(macro, 1000, 3);
29+
test(macro, 1000, 500);
30+
test(macro, 1000, 1000);

test/src/rotateRight.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import test from 'ava';
2+
3+
import {alloc} from '@array-like/alloc';
4+
import {iota} from '@array-like/fill';
5+
import {copy} from '@array-like/copy';
6+
7+
import {rotateRight} from '../../src/index.js';
8+
9+
const macro = (t, n, k) => {
10+
const a = alloc(n);
11+
iota(a, 0, n, 0);
12+
13+
const reference = alloc(n);
14+
copy(a, 0, n, reference, 0);
15+
16+
rotateRight(a, 0, n, n - k);
17+
t.is(a.length, n, 'length did not change');
18+
19+
const expected = reference.slice(k).concat(reference.slice(0, k));
20+
t.deepEqual(a, expected, 'works as expected');
21+
};
22+
23+
macro.title = (title, n, k) => title ?? `${n} - ${k}`;
24+
25+
test(macro, 1000, 0);
26+
test(macro, 1000, 1);
27+
test(macro, 1000, 2);
28+
test(macro, 1000, 3);
29+
test(macro, 1000, 500);
30+
test(macro, 1000, 1000);

0 commit comments

Comments
 (0)