crossword-algo-wordlywit
v2.0.0
Published
Powerful crossword puzzle generation algorithm with difficulty levels and American-style symmetric grids
Maintainers
Readme
crossword-algo-wordlywit v2.0
A powerful crossword puzzle generation algorithm with two modes: custom (party/manual) and standard (AI-generated with dictionary fill).
Features
- 🎯 Two Generation Modes - Custom (your words only) and Standard (with dictionary fill)
- 📚 Built-in Dictionary - 15,000+ crossword-friendly English words
- 📊 4 Difficulty Levels - Easy, Medium, Hard, Expert
- 📐 Auto Grid Sizing - Automatically calculated based on word count
- 🔄 American-Style Grids - Rotational symmetry support
- 🧹 Graceful Handling - Silently skips words that can't fit
Installation
npm install crossword-algo-wordlywitQuick Start
Custom Mode (Party/Manual Crosswords)
Use when users provide ALL their own words and clues:
import { generateCrossword } from 'crossword-algo-wordlywit';
const result = generateCrossword({
words: [
{ answer: "BIRTHDAY", clue: "Annual celebration day" },
{ answer: "CAKE", clue: "Sweet party dessert" },
{ answer: "CANDLES", clue: "What you blow out" },
// ... user's custom words
],
difficulty: "easy",
mode: "custom" // Default - uses ONLY these words
});Standard Mode (AI-Generated with Dictionary Fill)
Use when LLM generates theme words and you want a denser grid:
const result = generateCrossword({
words: llmGeneratedWords, // Theme words from GPT-4o-mini
difficulty: "hard",
mode: "standard", // Uses dictionary to fill gaps
targetWordCount: 25,
topic: "World History"
});
// Dictionary words that need clues from LLM:
console.log(result.fillWordsNeedingClues);
// ["ATLAS", "EMPIRE", "TREATY", ...]API Reference
generateCrossword(config)
Config Options
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| words | WordInput[] | ✅ | - | Array of word/clue pairs |
| difficulty | 'easy' \| 'medium' \| 'hard' \| 'expert' | ✅ | - | Difficulty level |
| mode | 'custom' \| 'standard' | ❌ | 'custom' | Generation mode |
| topic | string | ❌ | - | Topic metadata |
| targetWordCount | number | ❌ | all | Target words to place |
| minWordLength | number | ❌ | 3 | Minimum word length |
Return Value: CrosswordResult
interface CrosswordResult {
grid: Cell[][]; // Full cell objects with metadata
letters: string[][]; // Simple 2D letter array
width: number;
height: number;
placements: PlacedWord[]; // All placed words with positions
acrossClues: NumberedClue[];
downClues: NumberedClue[];
unplacedWords: WordInput[]; // Words that couldn't fit
fillWordsNeedingClues: string[]; // 🆕 Dictionary words needing LLM clues
topic?: string;
difficulty: Difficulty;
mode: GenerationMode; // 🆕 Which mode was used
stats: {
totalWordsProvided: number;
wordsPlaced: number;
wordsSkipped: number;
fillWordsUsed: number; // 🆕 Count of dictionary fill words
gridDensity: number;
};
}Generation Modes Explained
custom Mode (Default)
- Uses only the words you provide
- Best for: Party games, educational crosswords, user-created puzzles
- Grid adapts to available words
- All clues come from your input
standard Mode
- Places your themed words first
- Fills remaining spaces with dictionary words
- Returns
fillWordsNeedingCluesfor LLM clue generation - Creates denser, newspaper-style crosswords
Integration with Lovable
For Manual/Party Crosswords
// User provides their own words and clues
const result = generateCrossword({
words: userProvidedWords,
difficulty: selectedDifficulty,
mode: 'custom'
});
// Render directly - all clues are ready
renderCrossword(result);For AI-Generated Crosswords
// Step 1: LLM generates theme words
const themeWords = await generateWordsWithLLM(topic, difficulty, 15);
// Step 2: Generate crossword with dictionary fill
const result = generateCrossword({
words: themeWords,
difficulty,
mode: 'standard',
targetWordCount: 25,
topic
});
// Step 3: Generate clues for dictionary fill words
if (result.fillWordsNeedingClues.length > 0) {
const fillClues = await generateCluesWithLLM(
result.fillWordsNeedingClues,
topic,
difficulty
);
// Merge clues into result
for (const placement of result.placements) {
if (!placement.clue) {
placement.clue = fillClues[placement.answer] || "No clue available";
}
}
}
// Step 4: Render complete crossword
renderCrossword(result);Difficulty Levels
| Level | Grid Size | Intersections | Description | |-------|-----------|---------------|-------------| | Easy | Large | 1-2 per word | Spacious, beginner-friendly | | Medium | Balanced | 1-3 per word | Standard crossword feel | | Hard | Compact | 2-4 per word | Dense, challenging | | Expert | Tight | 2-6 per word | Maximum density |
Dictionary Utilities
Access the built-in dictionary directly:
import {
getWords,
getWordsByLength,
isValidWord,
getDictionaryStats
} from 'crossword-algo-wordlywit';
// Get all words
const allWords = getWords({ minLength: 4, maxLength: 8 });
// Get words of specific length
const fiveLetterWords = getWordsByLength(5);
// Check if word exists
const valid = isValidWord('HELLO'); // true
// Get statistics
const stats = getDictionaryStats();
// { totalWords: 15000+, byLength: { 3: 430, 4: 2100, ... } }TypeScript Support
Full TypeScript support with exported types:
import type {
CrosswordConfig,
CrosswordResult,
Difficulty,
GenerationMode,
WordInput,
PlacedWord,
NumberedClue,
Cell,
} from 'crossword-algo-wordlywit';Changelog
See CHANGELOG.md for version history.
License
MIT © WordlyWit
