import Random from "./Random";
const bow = Symbol("Beginning of word");
const eow = Symbol("Ending of word");
export { bow, eow };
type StringOrSymbol = symbol | string;
type RawDataForMapping = Array<string>;
interface TempMapping {
// @ts-ignore Waiting for https://github.com/Microsoft/TypeScript/pull/26797
[key: StringOrSymbol]: {
// @ts-ignore Waiting for https://github.com/Microsoft/TypeScript/pull/26797
[key: StringOrSymbol]: number;
};
}
export interface Mapping {
// @ts-ignore Waiting for https://github.com/Microsoft/TypeScript/pull/26797
[key: StringOrSymbol]: Array<[number, StringOrSymbol]>;
}
interface MarkovOptions {
minLen: number;
maxLen: number;
}
export const generateMapping = (raw: RawDataForMapping): Mapping => {
const mapping: TempMapping = {
[bow]: {
[eow]: 0,
},
};
for (const word of raw) {
const lowWord = word.toLowerCase();
for (let i = 0; i < lowWord.length; ++i) {
const char = lowWord[i];
if (i === 0) {
if (!(char in mapping[bow])) {
mapping[bow][char] = 0;
}
mapping[bow][char] += 1;
}
if (!(char in mapping)) {
mapping[char] = {
[eow]: 0,
};
}
let nextChar: StringOrSymbol = eow;
if (i < lowWord.length - 1) {
nextChar = lowWord[i + 1];
}
if (!(nextChar in mapping[char])) {
mapping[char][nextChar] = 0;
}
mapping[char][nextChar] += 1;
}
}
const keys = (Object.keys(mapping) as Array<StringOrSymbol>).concat([bow]);
for (const key of keys) {
const entries: Array<[StringOrSymbol, number]> = Object.entries(mapping[key]);
if (eow in mapping[key]) {
entries.push([eow, mapping[key][eow]]);
}
mapping[key] = entries.map(entry => entry.reverse());
}
return mapping;
};
export const generateChain = (
mapping: Mapping,
random: Random,
{ minLen, maxLen }: MarkovOptions,
) => {
let word = "";
let curLetter: StringOrSymbol = bow;
for (let i = 0; i < maxLen; ++i) {
curLetter = random.weighted(mapping[curLetter]);
if (curLetter === eow) {
if (i >= minLen) {
break;
} else {
curLetter = random.weighted(mapping[bow]);
}
}
word += curLetter as string;
}
return word;
};
Comments
0 B
|👍
/👎
0 B
|👍
/👎