-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
45e94c1
commit bea3bd0
Showing
3 changed files
with
86 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* Property-based test for Split on New Chars, | ||
* ensuring that the output meets the specifications outlined in the challenge description. | ||
*/ | ||
|
||
import { expect, test } from '@jest/globals'; | ||
import fc from 'fast-check'; | ||
import splitOnNewChars from './split-on-new-chars'; | ||
import { uniqueEverseen } from 'itertools'; | ||
|
||
/** | ||
* Arbitrary for inputs to `splitOnNewChars`. | ||
* | ||
* Characters are taken from a set of size 5 | ||
* so that generated strings are more likely to repeat characters. | ||
*/ | ||
const testString = fc.stringOf(fc.constantFrom('a', 'b', 'c', 'd', 'e')); | ||
|
||
test('satisfies required properties', () => { | ||
fc.assert( | ||
fc.property(testString, (str: string) => { | ||
const arr = splitOnNewChars(str); | ||
expect(arr.join('')).toStrictEqual(str); | ||
expect(indicesOfSplit(arr)).toStrictEqual( | ||
charFirstOccurrences(str), | ||
); | ||
}), | ||
); | ||
}); | ||
|
||
/** | ||
* Given a split of a string, | ||
* return the index at which each substring begins in the original string. | ||
* | ||
* Example: `['aa', 'baba', 'ccabac'] => [0, 2, 6]` \ | ||
* In `'aababaccabac'` (`['aa', 'baba', 'ccabac'].join('')`), \ | ||
* `'aa'` begins at index 0, `'baba'` begins at index 2, and `'ccabac'` begins at index 6. | ||
*/ | ||
function indicesOfSplit(arr: string[]): number[] { | ||
const indices = []; | ||
let currIndex = 0; | ||
for (const substring of arr) { | ||
indices.push(currIndex); | ||
currIndex += substring.length; | ||
} | ||
return indices; | ||
} | ||
|
||
/** | ||
* Return the index of the first occurrence of each character in the given string. | ||
* | ||
* Example: `'aababaccabac' => [0, 2, 6]` \ | ||
* `'a'` first occurs at index 0, `'b'` first occurs at index 2, and `'c'` first occurs at index 6. | ||
*/ | ||
function charFirstOccurrences(str: string): number[] { | ||
return [...uniqueEverseen(str)].map((char) => str.indexOf(char)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Problem (taken from | ||
* https://codegolf.stackexchange.com/questions/156170/split-string-on-first-occurrence-of-each-character): | ||
* transform a string `str` into a list of strings `arr` such that: | ||
* - `arr.join('') === str` | ||
* - A new substring begins precisely when | ||
* a previously unencountered character is encountered in the string. | ||
* | ||
* For example, `'aababaccabac'` should be split into `['aa', 'baba', 'ccabac']`. | ||
*/ | ||
|
||
/** Split the given string at newly encountered characters, as per the challenge description. */ | ||
export default function splitOnNewChars(str: string): string[] { | ||
/* | ||
Note: V8 apparently optimizes repeated string concatenation to not be quadratic time, | ||
so the elements of `arr` can be strings rather than arrays of characters. | ||
*/ | ||
const arr: string[] = []; | ||
const encounteredChars = new Set(); | ||
for (const char of str) { | ||
if (!encounteredChars.has(char)) { | ||
encounteredChars.add(char); | ||
arr.push(''); | ||
} | ||
arr[arr.length - 1] += char; | ||
} | ||
return arr; | ||
} |