Given an unique string that represents a sequence of characters, the class should implement three methods (getNextChar, getNextString and the genSequence generator).
How it works
- We give a sequence of characters. For example: "abc"
- We give a starting string. For example: "a"
- The generator yields the following strings infinitely.
The next string of an existing string works like a dictionary, only the length doesn't change as long as there are still characters to fulfill.
a
b
c
aa
ab
ac
ba
..
cc
aaa
aab
This is not homework, but a user in Stack Overflow chat presented the challenge and I considered taking it to a higher level.
class SeqString {
constructor (sequence) {
this._sequence = sequence;
this._first = sequence[0];
this._last = sequence.slice(-1);
return this;
}
getNextChar (char) {
let seq = this._sequence,
index = (seq.indexOf(char) + 1) % seq.length;
return seq[index];
}
getNextString (str) {
let last = str.slice(-1),
init = str.slice(0, str.length - 1),
lastOfSeq = this._last,
firstOfSeq = this._first;
// If it is overflowing
if (last === lastOfSeq) {
let trail = 1,
i = init.length;
// Look for an index that won't overflow
while (i-- && init[i] === lastOfSeq) ++trail;
// If there is no such index, then the result is a new sequence
// with an increased length
if (i === -1) return firstOfSeq.repeat(trail + 1);
// If there is, change the matching character at the index
// and reset every character after that
str = init.slice(0, i) + this.getNextChar(init[i]) +
firstOfSeq.repeat(trail);
return str;
}
return init + this.getNextChar(last);
}
*genSequence (str) {
let newStr = this.getNextString(str);
yield newStr;
yield* this.genSequence(newStr);
}
}
Specific questions
- How can I improve my class functions, while maintaining a balance between performance and readability?
- Tips on how I could make the code more readable for others.
Test cases
I have made a function test, to help debugging.
function test (sequence, startStr, times = 10) {
let it = new SeqString(sequence).genSequence(startStr);
while (times--)
console.log(it.next().value);
}
Examples of output
Alphaset tests
const lowerAlpha = "abcdefghijklmnopqrstuvwxyz";
const alpha = lowerAlpha + lowerAlpha.toUpperCase();
test(alpha, 'abc', 1); // abd
test(alpha, 'BZZ', 1); // Caa
test(alpha, 'Z', 1); // aa
test(alpha, 'ZZ', 1); // aaa
A long sequence for test(alpha, "Stack")
: http://lpaste.net/137336
Other tests
test("pen", "p", 10);
e
n
pp
..
np
test("0123456789", "5", 10);
6
7
8
9
00
01
02
..
It should
- Use ES6 features
- Expose a generator
- Handle every kind of unique sequence
- Be readable