Advertisement
Telokis

Markov1.ts

Mar 5th, 2020
996
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Random from "./Random";
  2.  
  3. const bow = Symbol("Beginning of word");
  4. const eow = Symbol("Ending of word");
  5.  
  6. export { bow, eow };
  7.  
  8. type StringOrSymbol = symbol | string;
  9. type RawDataForMapping = Array<string>;
  10.  
  11. interface TempMapping {
  12.     // @ts-ignore Waiting for https://github.com/Microsoft/TypeScript/pull/26797
  13.     [key: StringOrSymbol]: {
  14.         // @ts-ignore Waiting for https://github.com/Microsoft/TypeScript/pull/26797
  15.         [key: StringOrSymbol]: number;
  16.     };
  17. }
  18.  
  19. export interface Mapping {
  20.     // @ts-ignore Waiting for https://github.com/Microsoft/TypeScript/pull/26797
  21.     [key: StringOrSymbol]: Array<[number, StringOrSymbol]>;
  22. }
  23.  
  24. interface MarkovOptions {
  25.     minLen: number;
  26.     maxLen: number;
  27. }
  28.  
  29. export const generateMapping = (raw: RawDataForMapping): Mapping => {
  30.     const mapping: TempMapping = {
  31.         [bow]: {
  32.             [eow]: 0,
  33.         },
  34.     };
  35.  
  36.     for (const word of raw) {
  37.         const lowWord = word.toLowerCase();
  38.  
  39.         for (let i = 0; i < lowWord.length; ++i) {
  40.             const char = lowWord[i];
  41.  
  42.             if (i === 0) {
  43.                 if (!(char in mapping[bow])) {
  44.                     mapping[bow][char] = 0;
  45.                 }
  46.  
  47.                 mapping[bow][char] += 1;
  48.             }
  49.  
  50.             if (!(char in mapping)) {
  51.                 mapping[char] = {
  52.                     [eow]: 0,
  53.                 };
  54.             }
  55.  
  56.             let nextChar: StringOrSymbol = eow;
  57.  
  58.             if (i < lowWord.length - 1) {
  59.                 nextChar = lowWord[i + 1];
  60.             }
  61.  
  62.             if (!(nextChar in mapping[char])) {
  63.                 mapping[char][nextChar] = 0;
  64.             }
  65.  
  66.             mapping[char][nextChar] += 1;
  67.         }
  68.     }
  69.  
  70.     const keys = (Object.keys(mapping) as Array<StringOrSymbol>).concat([bow]);
  71.  
  72.     for (const key of keys) {
  73.         const entries: Array<[StringOrSymbol, number]> = Object.entries(mapping[key]);
  74.  
  75.         if (eow in mapping[key]) {
  76.             entries.push([eow, mapping[key][eow]]);
  77.         }
  78.  
  79.         mapping[key] = entries.map(entry => entry.reverse());
  80.     }
  81.  
  82.     return mapping;
  83. };
  84.  
  85. export const generateChain = (
  86.     mapping: Mapping,
  87.     random: Random,
  88.     { minLen, maxLen }: MarkovOptions,
  89. ) => {
  90.     let word = "";
  91.     let curLetter: StringOrSymbol = bow;
  92.  
  93.     for (let i = 0; i < maxLen; ++i) {
  94.         curLetter = random.weighted(mapping[curLetter]);
  95.  
  96.         if (curLetter === eow) {
  97.             if (i >= minLen) {
  98.                 break;
  99.             } else {
  100.                 curLetter = random.weighted(mapping[bow]);
  101.             }
  102.         }
  103.  
  104.         word += curLetter as string;
  105.     }
  106.  
  107.     return word;
  108. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement