Skip to content

Commit d933219

Browse files
🚧 progress: Import existing sources, tests, and code samples.
1 parent bdef171 commit d933219

File tree

8 files changed

+10184
-9
lines changed

8 files changed

+10184
-9
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ See [docs](https://computational-combinatorics.github.io/n-combinations/index.ht
1111
> `regeneratorRuntime` to be defined, for instance by importing
1212
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
1313
14+
```js
15+
import {combinations} from '@combinatorics/n-combinations';
16+
17+
combinations("ABCD", 2); // AB AC AD BC BD CD
18+
combinations(range(4), 3); // 012 013 023 123
19+
```
20+
1421
[![License](https://img.shields.io/github/license/computational-combinatorics/n-combinations.svg)](https://raw.githubusercontent.com/computational-combinatorics/n-combinations/main/LICENSE)
1522
[![Version](https://img.shields.io/npm/v/@combinatorics/n-combinations.svg)](https://www.npmjs.org/package/@combinatorics/n-combinations)
1623
[![Tests](https://img.shields.io/github/workflow/status/computational-combinatorics/n-combinations/ci:test?event=push&label=tests)](https://github.com/computational-combinatorics/n-combinations/actions/workflows/ci:test.yml?query=branch:main)

doc/scripts/header.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ domReady(() => {
1717
header.insertBefore(projectname, header.firstChild);
1818

1919
const testlink = document.querySelector('header > a[data-ice="testLink"]');
20-
testlink.href = 'https://app.codecov.io/gh/computational-combinatorics/n-combinations';
20+
testlink.href =
21+
'https://app.codecov.io/gh/computational-combinatorics/n-combinations';
2122
testlink.target = '_BLANK';
2223

2324
const searchBox = document.querySelector('.search-box');

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@
6060
"release": "np --message ':hatching_chick: release: Bumping to v%s.'",
6161
"test": "ava"
6262
},
63-
"dependencies": {},
63+
"dependencies": {
64+
"@iterable-iterator/list": "^0.0.2",
65+
"@iterable-iterator/map": "^0.1.0",
66+
"@iterable-iterator/range": "^1.0.0"
67+
},
6468
"devDependencies": {
6569
"@babel/core": "7.14.0",
6670
"@babel/preset-env": "7.14.0",

src/combinations.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {list} from '@iterable-iterator/list';
2+
import {pick} from '@iterable-iterator/map';
3+
import {range} from '@iterable-iterator/range';
4+
5+
/**
6+
* Yields all combinations of each possible choice of <code>r</code> elements
7+
* of the input iterable.
8+
*
9+
* @example
10+
* // AB AC AD BC BD CD
11+
* combinations('ABCD', 2)
12+
*
13+
* @example
14+
* // 012 013 023 123
15+
* combinations(range(4), 3)
16+
*
17+
* @param {Iterable} iterable - The input iterable.
18+
* @param {number} r - The size of the combinations to generate.
19+
* @returns {IterableIterator}
20+
*/
21+
export default function* combinations(iterable, r) {
22+
const pool = list(iterable);
23+
const length = pool.length;
24+
25+
if (r > length) {
26+
return;
27+
}
28+
29+
const indices = list(range(0, r, 1));
30+
31+
yield list(pick(pool, indices));
32+
33+
while (true) {
34+
let i = r - 1;
35+
36+
// eslint-disable-next-line no-constant-condition
37+
while (true) {
38+
if (i < 0) {
39+
return;
40+
}
41+
42+
if (indices[i] !== i + length - r) {
43+
let pivot = ++indices[i];
44+
45+
for (++i; i < r; ++i) {
46+
indices[i] = ++pivot;
47+
}
48+
49+
break;
50+
}
51+
52+
--i;
53+
}
54+
55+
yield list(pick(pool, indices));
56+
}
57+
}

src/index.js

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

test/src/api.js

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

test/src/combinations.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import test from 'ava';
2+
3+
import {list} from '@iterable-iterator/list';
4+
import {range} from '@iterable-iterator/range';
5+
import {combinations} from '../../src/index.js';
6+
7+
const repr = (x) => (Array.isArray(x) ? JSON.stringify(x) : x);
8+
9+
const macro = (t, iterable, r, expected) => {
10+
t.deepEqual(list(combinations(iterable, r)), expected);
11+
};
12+
13+
macro.title = (title, iterable, r, expected) =>
14+
title ?? `combinations(${repr(iterable)}, ${r}) is ${repr(expected)}`;
15+
16+
test(macro, 'ABCD', 2, [
17+
['A', 'B'],
18+
['A', 'C'],
19+
['A', 'D'],
20+
['B', 'C'],
21+
['B', 'D'],
22+
['C', 'D'],
23+
]);
24+
25+
test(macro, range(0, 4, 1), 3, [
26+
[0, 1, 2],
27+
[0, 1, 3],
28+
[0, 2, 3],
29+
[1, 2, 3],
30+
]);
31+
32+
test(macro, range(0, 4, 1), 4, [[0, 1, 2, 3]]);
33+
test(macro, range(0, 4, 1), 5, []);
34+
test(macro, range(0, 4, 1), 0, [[]]);
35+
test(macro, range(0, 0, 1), 0, [[]]);
36+
test(macro, range(0, 0, 1), 1, []);

0 commit comments

Comments
 (0)