Skip to content

Commit

Permalink
Fix #4: start/end strings are optional
Browse files Browse the repository at this point in the history
  • Loading branch information
fasiha committed May 23, 2019
1 parent 5997f18 commit 95b9a91
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 8 deletions.
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ As a convenience, the following pre-generated symbol table are provided:
- `base36`: `0-9a-z` (lower- and upper-case accepted, to match `Number.toString`),
- `alphabet`: `a-z` (lower- and upper-case accepted).

You may also omit the start and/or end strings, and provide only the number of strings to subdivide the entire string space. (Even this number may also be omitted if you just want one string in the middle of the string space.)
```js
var mudder = require('mudder'); // only in Node
var strings = mudder.base62.mudder('alphaNUM341C', 'beta', 3);
var strings = mudder.base62.mudder(1000);
console.log(strings);
// [ 'az', 'b', 'bR' ]
// [ '03', '07', '0B', ... 'zo', 'zs', 'zw' ]
```

## API
Expand All @@ -50,7 +51,13 @@ There are very few restrictions on what symbols the `SymbolTable` constructor ac

### Generate strings

`m.mudder(start, end[, number[, base]])` for strings, or array-of-strings, `start` and `end`, returns a `number`-length (default one) array of strings. `base` is an integer defaulting to the size of the symbol table `m`, but can be less than it if you, for some reason, wish to use only a subset of the symbol table. `start` can be lexicographically less than or greater than `end`, but in either case, the returned array will be lexicographically sorted between them. If the symbol table was *not* prefix-free, the function will refuse to operate on *strings* `start`/`end` because, without the prefix-free criterion, a string can’t be parsed unambiguously: you have to split the string into an array of stringy symbols yourself. Invalid or unrecognized symbols are silently ignored.
**`m.mudder(start = '', end = '' [, number[, base]])`** for strings, or array-of-strings, `start` and `end`, returns a `number`-length (default one) array of strings. `base` is an integer defaulting to the size of the symbol table `m`, but can be less than it if you, for some reason, wish to use only a subset of the symbol table. `start` can be lexicographically less than or greater than `end`, but in either case, the returned array will be lexicographically sorted between them.

If `start` or `end` are non-truthy, the first is replaced by the first symbol, and the second is replaced by repeating the final symbol several times (e.g., for a numeric symbol table, `start` would default to `0` and `end` to `999999` or similar).

> If the symbol table was *not* prefix-free, the function will refuse to operate on *strings* `start`/`end` because, without the prefix-free criterion, a string can’t be parsed unambiguously: you have to split the string into an array of stringy symbols yourself. Invalid or unrecognized symbols are silently ignored.
**`m.mudder(number = 1)`** is equivalent to `m.mudder('', '', number)`. See above.

### For fun: string–number conversion

Expand Down Expand Up @@ -928,11 +935,19 @@ function truncateLexHigher(lo, hi) {
}

SymbolTable.prototype.mudder = function(a, b, numStrings, base) {
if (typeof a === 'number'){
numStrings = a;
a = '';
b = '';
}
a = a || this.num2sym[0];
b = b || this.num2sym[this.num2sym.length - 1].repeat(6);
numStrings = numStrings || 1;
base = base || this.maxBase;
[a, b] = truncateLexHigher(a, b);
const ad = this.stringToDigits(a, base);
const bd = this.stringToDigits(b, base);
const intermediateDigits = longLinspace(ad, bd, base, numStrings || 1);
const intermediateDigits = longLinspace(ad, bd, base, numStrings);
let finalDigits = intermediateDigits.map(
v => v.res.concat(this.roundFraction(v.rem, v.den, base)));
finalDigits.unshift(ad);
Expand Down
7 changes: 4 additions & 3 deletions dist/mudder.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,19 @@ function truncateLexHigher(lo, hi) {
}

SymbolTable.prototype.mudder = function(a, b, numStrings, base) {
if (typeof a === 'number'){
numStrings = a;
a = '';
b = '';
}
a = a || this.num2sym[0];
b = b || this.num2sym[this.num2sym.length - 1].repeat(6);
numStrings = numStrings || 1;
base = base || this.maxBase;
[a, b] = truncateLexHigher(a, b);
const ad = this.stringToDigits(a, base);
const bd = this.stringToDigits(b, base);
const intermediateDigits = longLinspace(ad, bd, base, numStrings || 1);
const intermediateDigits = longLinspace(ad, bd, base, numStrings);
let finalDigits = intermediateDigits.map(
v => v.res.concat(this.roundFraction(v.rem, v.den, base)));
finalDigits.unshift(ad);
Expand Down
15 changes: 15 additions & 0 deletions test/mudder-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,18 @@ tape('Fixes #2: throws when fed lexicographically-adjacent strings',
}
test.end();
});

tape('Fixes #3: allow calling mudder with just number', function(test) {
for (const abc of [mudder.alphabet.mudder(100), mudder.base36.mudder(100),
mudder.base62.mudder(100)]) {
test.ok(abc.every((c, i) => (!i) || (abc[i - 1] < c)));
}
test.ok(mudder.alphabet.mudder());
test.end();
});

tape('More #3: no need to define start/end', function(test) {
test.ok(mudder.base36.mudder('', 'foo', 30));
test.ok(mudder.base36.mudder('foo', '', 30));
test.end();
});

0 comments on commit 95b9a91

Please sign in to comment.