Skip to main content
Glama
counting.ts6.03 kB
/** * Counting tools for character and pattern analysis */ import { createVisualBreakdown, createDensitySummary, formatFrequencyTable } from '../utils/visualization.js'; // ============================================================================ // count_letter - Count occurrences of a specific letter // ============================================================================ export interface CountLetterInput { text: string; letter: string; case_sensitive: boolean; } export interface CountLetterOutput { text: string; letter: string; count: number; case_sensitive: boolean; positions: number[]; visual: string; density: string; } export function countLetter(input: CountLetterInput): CountLetterOutput { const { text, letter, case_sensitive } = input; // Normalize the letter to search for const searchLetter = case_sensitive ? letter : letter.toLowerCase(); const searchText = case_sensitive ? text : text.toLowerCase(); const positions: number[] = []; for (let i = 0; i < searchText.length; i++) { if (searchText[i] === searchLetter) { positions.push(i); } } const visual = createVisualBreakdown(text, positions, letter); const density = createDensitySummary(positions.length, text.length, letter); return { text, letter, count: positions.length, case_sensitive, positions, visual, density, }; } // ============================================================================ // count_letters - Count occurrences of multiple letters at once // ============================================================================ export interface CountLettersInput { text: string; letters: string[]; case_sensitive: boolean; } export interface LetterCount { letter: string; count: number; positions: number[]; } export interface CountLettersOutput { text: string; letters_searched: string[]; case_sensitive: boolean; results: LetterCount[]; total_matches: number; } export function countLetters(input: CountLettersInput): CountLettersOutput { const { text, letters, case_sensitive } = input; const results: LetterCount[] = letters.map(letter => { const searchLetter = case_sensitive ? letter : letter.toLowerCase(); const searchText = case_sensitive ? text : text.toLowerCase(); const positions: number[] = []; for (let i = 0; i < searchText.length; i++) { if (searchText[i] === searchLetter) { positions.push(i); } } return { letter, count: positions.length, positions, }; }); const total_matches = results.reduce((sum, r) => sum + r.count, 0); return { text, letters_searched: letters, case_sensitive, results, total_matches, }; } // ============================================================================ // count_substring - Count occurrences of a substring/pattern // ============================================================================ export interface CountSubstringInput { text: string; substring: string; case_sensitive: boolean; overlapping: boolean; } export interface CountSubstringOutput { text: string; substring: string; count: number; case_sensitive: boolean; overlapping: boolean; positions: number[]; } export function countSubstring(input: CountSubstringInput): CountSubstringOutput { const { text, substring, case_sensitive, overlapping } = input; if (substring.length === 0) { return { text, substring, count: 0, case_sensitive, overlapping, positions: [], }; } const searchText = case_sensitive ? text : text.toLowerCase(); const searchSubstring = case_sensitive ? substring : substring.toLowerCase(); const positions: number[] = []; let startIndex = 0; while (startIndex < searchText.length) { const foundIndex = searchText.indexOf(searchSubstring, startIndex); if (foundIndex === -1) break; positions.push(foundIndex); startIndex = overlapping ? foundIndex + 1 : foundIndex + searchSubstring.length; } return { text, substring, count: positions.length, case_sensitive, overlapping, positions, }; } // ============================================================================ // letter_frequency - Get frequency distribution of all letters // ============================================================================ export interface LetterFrequencyInput { text: string; case_sensitive: boolean; include_spaces: boolean; include_punctuation: boolean; letters_only: boolean; } export interface LetterFrequencyOutput { text: string; total_characters: number; unique_characters: number; frequency: Record<string, number>; frequency_table: string; most_common: Array<{ char: string; count: number }>; least_common: Array<{ char: string; count: number }>; } export function letterFrequency(input: LetterFrequencyInput): LetterFrequencyOutput { const { text, case_sensitive, include_spaces, include_punctuation, letters_only } = input; const frequency: Record<string, number> = {}; const processedText = case_sensitive ? text : text.toLowerCase(); for (const char of processedText) { // Filter based on options if (letters_only && !/[a-zA-Z]/.test(char)) continue; if (!include_spaces && char === ' ') continue; if (!include_punctuation && /[^\w\s]/.test(char)) continue; frequency[char] = (frequency[char] || 0) + 1; } const entries = Object.entries(frequency).sort((a, b) => b[1] - a[1]); const most_common = entries.slice(0, 5).map(([char, count]) => ({ char, count })); const least_common = entries.slice(-5).reverse().map(([char, count]) => ({ char, count })); return { text, total_characters: Object.values(frequency).reduce((a, b) => a + b, 0), unique_characters: Object.keys(frequency).length, frequency, frequency_table: formatFrequencyTable(frequency), most_common, least_common, }; }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Aaryan-Kapoor/mcp-character-tools'

If you have feedback or need assistance with the MCP directory API, please join our Discord server