/** * @name calculateReadingTime * @description Calculates the reading time for a given content based on an average reading speed of 200 words per minute. * * @param {string} content - The content for which to calculate the reading time. * @returns {number} The estimated reading time in minutes, rounded up to the nearest whole number. * * @example * const time = calculateReadingTime("This is a sample content to test the reading time calculation."); * console.log(time); // Outputs: 1 */ export function calculateReadingTime(content: string) { if (!content || content.trim().length === 0) return 0; const wordsPerMinute = 200; const words = content.split(/\s+/).length; return Math.ceil(words / wordsPerMinute); } /** * @name formatDate * @description Formats a date string into a more readable format. * * @param {string} dateString - The date string to format. * @returns {string} The formatted date string in the format "dd MMMM". * * @example * const formattedDate = formatDate("2023-10-01T12:00:00Z"); * console.log(formattedDate); // Outputs: "9 Apr" */ export function formatDate(dateString: string) { const date = new Date(dateString); const month = date.toLocaleDateString('ru-RU', { month: 'short', }); return `${date.getDate()} ${month.charAt(0).toUpperCase() + month.slice(1, -1)}`; } /** * @name formatDateTime * @description Formats a date string into a more readable format with time. * * @param {string} dateString - The date string to format. * @returns {string} The formatted date string in the format "dd.MMMM.yyyy в HH:mm". * * @example * const formattedDateTime = formatDateTime("2023-10-01T12:00:00Z"); * console.log(formattedDateTime); // Outputs: "1.04.2025 в 12:00" */ export function formatDateTime(dateString: string) { const date = new Date(dateString); const onlyDate = date.toLocaleDateString('ru-RU', { year: 'numeric', month: 'numeric', day: 'numeric', }); const time = date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit', }); return `${onlyDate} в ${time}`; } /** * @name pluralize * @description Returns a pluralized form of a word based on the count. * * @param {number} count - The count to determine the pluralization. * @param {string[]} forms - An array containing the singular, plural, and genitive forms of the word. * @returns {string} The appropriate form of the word based on the count. * * @example * const word = pluralize(1, ['яблоко', 'яблока', 'яблок']); * console.log(word); // Outputs: "яблоко" */ export function pluralize(count: number, forms: string[]) { const [singular, plural, genitive] = forms; if (count === 1) return singular; if (count > 1 && count < 5) return plural; return genitive; } /** * @name computeLPS * @description Computes the Longest Prefix Suffix (LPS) array for the KMP algorithm. * * @param {string} pattern - The pattern for which to compute the LPS array. * @returns {number[]} The LPS array where lps[i] is the length of the longest proper prefix which is also a suffix for the substring pattern[0..i]. * * @example * const lps = computeLPS("ABABAC"); * console.log(lps); // Outputs: [0, 0, 1, 2, 0, 1] */ function computeLPS(pattern: string) { const lps = Array.from({ length: pattern.length }).fill(0); let len = 0; let i = 1; while (i < pattern.length) { if (pattern[i] === pattern[len]) { len++; lps[i] = len; i++; } else { if (len !== 0) { len = lps[len - 1]!; } else { lps[i] = 0; i++; } } } return lps; } /** * @name kmpSearch * @description Implements the Knuth-Morris-Pratt (KMP) algorithm for substring search. * * @param {string} text - The text in which to search for the pattern. * @param {string} pattern - The pattern to search for in the text. * @returns {boolean} Returns true if the pattern is found in the text, otherwise false. * * @example * const found = kmpSearch("hello world", "world"); * console.log(found); // Outputs: true */ export function kmpSearch(text: string, pattern: string) { if (pattern.length === 0) return true; if (text.length === 0) return false; const textLower = text.toLowerCase(); const patternLower = pattern.toLowerCase(); const lps = computeLPS(patternLower); let i = 0; // index for text let j = 0; // index for pattern while (i < textLower.length) { if (patternLower[j] === textLower[i]) { i++; j++; } if (j === patternLower.length) { return true; // Found match } else if (i < textLower.length && patternLower[j] !== textLower[i]) { if (j !== 0) { j = lps[j - 1]!; } else { i++; } } } return false; }