Constant-time anagram comparison using packed bit-width representation.
Standard anagram detection methods have hidden costs:
| Method | Hash Cost | Compare Cost | Key Size |
|---|---|---|---|
| Sorted String | O(n log n) | O(n) | n bytes |
| Count Array | O(n) | O(26) | 104 bytes |
| Packed Bit-Width | O(n) | O(1) | 8 bytes |
This package provides 26× faster comparison than count arrays and n× faster than sorted strings, with 6-13× smaller keys.
pip install packed-anagram-hashfrom packed_anagram_hash import PackedAnagramHasher
# Initialize with your corpus
corpus = ["store", "rotes", "tores", "stare", "rates", "tears"]
hasher = PackedAnagramHasher(corpus)
# Hash words - anagrams produce identical hashes
h1 = hasher.hash("store")
h2 = hasher.hash("rotes")
h3 = hasher.hash("stare")
assert h1 == h2 # True - same letters
assert h1 != h3 # True - different letters
# Group anagrams
groups = hasher.group_anagrams(corpus)
# {hash1: ["store", "rotes", "tores"], hash2: ["stare", "rates", "tears"]}- Pre-compute maximum letter frequency per character in your corpus
- Allocate minimal bits per letter (e.g., 'e' max 4 occurrences → 3 bits)
- Pack into single 64-bit register (~50-60 bits for English)
- Hash by accumulating:
h += (1 << offset[letter])
Addition commutes, so anagrams produce identical hashes. Comparison is single CPU instruction.
Initialize hasher with a corpus to determine bit-widths.
Parameters:
corpus: Iterable of strings to analyze for letter frequencies
Attributes:
bit_widths: List of bits allocated per letter (a-z)offsets: Bit offset for each letter in the packed hashtotal_bits: Total bits used (must be ≤64 for single-register operation)
Compute packed hash for a word.
Parameters:
word: String to hash (case-insensitive, non-alphabetic characters ignored)
Returns:
- 64-bit integer hash
Group words by anagram equivalence.
Parameters:
words: Iterable of strings to group
Returns:
- Dictionary mapping hash → list of anagram words
Check if two words are anagrams.
For corpora requiring >64 bits (extremely long words or large alphabets), the algorithm extends to multiple registers. See the paper for details.
If you use this in academic work:
@software{brown_2025_packed_anagram,
author = {Brown, Nicholas David},
title = {Packed Bit-Width Anagram Hashing: A Constant-Time
Comparison Algorithm for Anagram Equivalence},
year = 2025,
publisher = {Zenodo},
doi = {10.5281/zenodo.18168195},
url = {https://doi.org/10.5281/zenodo.18168195}
}CC0 1.0 Universal - Public Domain. Use freely.