1 "use strict";
  2 const consonants = "bcčćdđfghjklmnpqrsštvwxyzž";
  3 const fileSystem = require("fs");
  4 const input = fileSystem.readFileSync(
  5     "hr.wl", // The Aspell word-list for the Croatian language.
  6     {encoding : "utf-8"});
  7 const wordList = new Set();
  8 let currentWord = "";
  9 for (const character of input)
 10   if (character == '\n' || character == ' ') {
 11     wordList.add(currentWord);
 12     currentWord = "";
 13   } else
 14     currentWord += character.toLowerCase();
 15 const mapWithWordInitialConsonantPairs = new Map();
 16 const mapWithWordFinalConsonantPairs = new Map();
 17 const setWithConsonantPairs = new Set();
 18 const getFirstTwoConsonants = (word) => {
 19   let consonantPair = "";
 20   for (let i = 0; i < word.length; i++)
 21     if (consonants.includes(word[i])) {
 22       consonantPair += word[i];
 23       if (consonantPair.length == 2)
 24         break;
 25     }
 26   while (consonantPair.length < 2)
 27     consonantPair += "0";
 28   return consonantPair;
 29 };
 30 const getLastTwoConsonants = (word) => {
 31   let consonantPair = "";
 32   for (let i = word.length - 1; i >= 0; i--)
 33     if (consonants.includes(word[i])) {
 34       consonantPair = word[i] + consonantPair;
 35       if (consonantPair.length == 2)
 36         break;
 37     }
 38   while (consonantPair.length < 2)
 39     consonantPair = "0" + consonantPair;
 40   return consonantPair;
 41 };
 42 for (const word of wordList) {
 43   mapWithWordInitialConsonantPairs.set(
 44       getFirstTwoConsonants(word),
 45       (mapWithWordInitialConsonantPairs.get(getFirstTwoConsonants(word)) || 0) +
 46           1);
 47   mapWithWordFinalConsonantPairs.set(
 48       getLastTwoConsonants(word),
 49       (mapWithWordFinalConsonantPairs.get(getLastTwoConsonants(word)) || 0) +
 50           1);
 51   setWithConsonantPairs.add(getFirstTwoConsonants(word));
 52   setWithConsonantPairs.add(getLastTwoConsonants(word));
 53 }
 54 let maximalNumber = 0;
 55 console.log("Consonant pair\tWords starting with it\tWords ending with it");
 56 for (const consonantPair of setWithConsonantPairs) {
 57   console.log(consonantPair + "\t" +
 58               (mapWithWordInitialConsonantPairs.get(consonantPair) || 0) +
 59               "\t" + (mapWithWordFinalConsonantPairs.get(consonantPair) || 0));
 60   maximalNumber = Math.max(
 61       maximalNumber,
 62       Math.sqrt(mapWithWordInitialConsonantPairs.get(consonantPair) || 0),
 63       Math.sqrt(mapWithWordFinalConsonantPairs.get(consonantPair) || 0));
 64 }
 65 console.log("The maximal number is:" + maximalNumber);
 66 let svg = `<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
 67 <svg
 68         width="${(consonants.length + 3) * 30}"
 69         height="${(consonants.length + 4) * 30}"
 70         version="1.1"
 71         xmlns="http://www.w3.org/2000/svg"
 72 >
 73 <rect x="0" y="0" width="100%" height="100%" fill="white" />
 74 <text x="400" y="20">Prvi suglasnik u paru</text>
 75 <g transform="rotate(-90 20 500)"><text x="20" y="500">Drugi suglasnik u paru</text></g>
 76 `;
 77 for (let i = 0; i < (consonants + "0").length; i++)
 78   svg += `<text x="${(i + 2) * 30 + 12}" y="${15 + 30}">${
 79       (consonants + "0")[i]}</text>
 80         <text x="${12 + 30}" y="${(i + 1) * 30 + 7 + 30}">${
 81       (consonants + "0")[i]}</text>
 82         `;
 83 svg += `<line x1="${60}" y1="${30}" x2="${60}" y2="${
 84     ((consonants + "0").length + 1) * 30 + 30}" stroke="black" />
 85 <line x1="${30}" y1="${20 + 30}" x2="${
 86     ((consonants + "0").length + 1) * 30 +
 87     30}" y2="${20 + 30}" stroke="black" />`;
 88 for (let i = 0; i < (consonants + "0").length; i++)
 89   for (let j = 0; j < (consonants + "0").length; j++) {
 90     const consonantPair = (consonants + "0")[i] + (consonants + "0")[j];
 91     const proportionInBeginning =
 92         Math.sqrt(mapWithWordInitialConsonantPairs.get(consonantPair) || 0) /
 93         maximalNumber;
 94     const proportionAtTheEnd =
 95         Math.sqrt(mapWithWordFinalConsonantPairs.get(consonantPair) || 0) /
 96         maximalNumber;
 97     console.log(`The consonant pair ${consonantPair} has proportions ${
 98         proportionInBeginning} and ${proportionAtTheEnd}.`);
 99     const rx = (i + 2) * 30 + 15;
100     const ry = (j + 2) * 30 + 3;
101     svg += `<circle cx="${rx}" cy="${ry}" stroke="red" stroke-width="1" r="${
102         proportionInBeginning * 13}"  fill="rgba(255,0,0,0.5)" />
103                         <rect x="${rx - proportionAtTheEnd * 13}" y="${
104         ry - proportionAtTheEnd *
105                  13}" width="${proportionAtTheEnd * 2 * 13}" height="${
106         proportionAtTheEnd * 2 *
107         13}"  fill="rgba(0,0,255,0.5)" stroke="blue" stroke-width="1" />
108                         `;
109   }
110 svg += `<rect x="10" y="${
111     ((consonants + "0").length + 2) * 30 +
112     5}" stroke="blue" stroke-width="1" width="10" height="10"  fill="rgba(0,0,255,0.5)" /><text x="30" y="${
113     ((consonants + "0").length + 2) * 30 +
114     15}"> - Frekvencija para suglasnika na kraju riječi</text>
115 <circle cx="380" cy="${
116     ((consonants + "0").length + 2) * 30 +
117     10}" stroke-width="1" stroke="red" r="5"  fill="rgba(255,0,0,0.5)" /><text x="400" y="${
118     ((consonants + "0").length + 2) * 30 +
119     15}"> - Frekvencija para suglasnika na početku riječi</text>
120 `
121 svg += "</svg>";
122 fileSystem.writeFileSync("table-diagram-for-Croatian.svg", svg);