词字母重组

把一组字母重新排列,先按多重集排列数公式算出「一共有多少种排法」,再用大小写与重音折叠的口径去和词表比对,列出这组字母真正能拼出的英文单词。

比较与筛选
5 个字母(1 个):level
3 个字母(3 个):eel eve lee

提示:字母与最短词长输入框里按 Enter 直接重排;词表文本框里 Enter 是换行,请按 Ctrl / Cmd + Enter 触发。全部计算在本地完成,不上传任何内容。

使用方法

  1. 在「要重排的字母」里填一串字母,示例值是 LEVEL。允许 2~20 个字母,大小写随意。
  2. 在「最短词长」里填一个 2~12 的整数,示例值是 3,也就是只关心长度 3 及以上的词,避免把 le、ev 这类不在词表里的碎片也算进来。
  3. 「折叠大小写与重音」默认勾选:此时 É 与 e、E 与 e 会被当成同一个字母;取消勾选后大小写与重音就按原样区分。
  4. 「自定义词表」里默认放了一份常用英文短词,你可以整段替换成自己的单词表——词典越大,能命中的真词越全。
  5. 点「重排字母」(或在字母、最短词长输入框里直接按 Enter),结果区给出四张统计卡和最长的词排在前面的词表;点「复制结果」带走,或点「导出 CSV」把排列数对照表存成表格。

词字母重组能解决什么问题

一是看清「有多少种排法」这个数量级。很多人以为 5 个字母只有几十种排法,其实 5 个互不相同的字母有 120 种;一旦出现重复字母,排法数会按重复字母的阶乘成倍缩水,LEVEL 只有 30 种。词字母重组把这些数先算清楚,再谈「其中哪些是真词」。

二是把「排法」和「真词」这两件事分开。排列数是纯数学结论,闭式公式一步可得;而「这串字母是不是一个英文单词」无法用数学推导,只能拿词表逐条核对。本工具把这两种完全不同的判定放在同一次计算里,先给总数、再给真词。

三是换一个词表就换一套结论。词典、专有名词、化学式缩写、自己的项目代号,都可以粘进「自定义词表」;同一个字母组在不同词表下命中的词数完全不同,这一点任何写死词库的工具都做不到。

四是做拼字类谜题时的辅助。给一手字母找出全部可用词、或者反过来验证「某个答案是不是真能由这些字母拼出来」,都只需要把字母填进去看一眼命中列表。

本页不做这些事:不做中文分词,不判断词义与词性,不给单词打分排序(只按长度降序、同长按字典序),也不会去网络上查外部词库。

原理:排列数公式、大小写与重音折叠、字典校验

排列数用多重集排列公式,而不是逐个枚举。给 n 个字母,若每个字母都不同,排法是 n!;若有字母重复,重复的字母互换位置其实得到同一串,所以要除掉每种字母出现次数的阶乘,公式是 n! ÷ (m₁!·m₂!·…·m_k!),其中 m_i 是第 i 种字母的个数。LEVEL 的多重集是 L 两个、E 两个、V 一个,于是排法 = 5! ÷ (2! × 2! × 1!) = 120 ÷ 4 = 30。BANANA 的 A 三个、N 两个、B 一个,排法 = 6! ÷ (3! × 2!) = 720 ÷ 12 = 60。这个公式是闭式的,不需要真的把 30 种或 60 种打出来。

折叠这一步交给 Intl.Collator 和 Unicode 规范化。折叠一个字符分两步:先用 "É".normalize("NFD") 把它拆成 E 加上组合附加符号 U+0301,再把 U+0300–U+036F 这一段组合符号删掉,最后转小写,得到 e。规范化形式由 Unicode 标准附件 UAX #15 定义,排序与比较的规则来自 UTS #10,浏览器把它们实现成了 Intl.Collator。构造时用的参数是 sensitivity:"base":base 会同时忽略大小写和重音,accent 只忽略大小写、保留重音,variant 两者都区分。usage:"search" 让比较器按搜索场景(而不是排序场景)去判等。所以把 Café 填进来,折叠后就是 cafe,能和词表里的 cafe 对上。

「能拼出哪些真词」只能走字典校验,这是和排列数完全不同的路径。判定一个词 w 能不能由字母组 S 拼成,本质是判断 w 的字母多重集是不是 S 的子集:把两者的字母都数成计数字典,只要 w 里每种字母的个数都不超过 S 里的个数,就成立。这一步的代价是词表条目数乘以单词长度,也就是 O(词表大小 × 单词长度)。如果反过来用「生成式重排」——先把 n! 种排列全造出来再逐个查词表——12 个互不相同的字母就是 479,001,600 种串,绝大多数根本不是单词,纯属浪费;这也是本页选字典校验而不是生成式重排的原因。

数值一律用 BigInt。JS 的 Number 只能精确表示到 2⁵³ − 1 = 9,007,199,254,740,991。无重复字母时 18! = 6,402,373,705,728,000 还在这个范围里,到了 19! = 121,645,100,408,832,000 就已经超出 13.51 倍,继续用 Number 会静默丢精度。所以排列数的阶乘与相除全部走 BigInt,再格式化成带千分位的字符串显示。

完整示例(数值仅作演示)

页面打开时的默认条件与下面完全一致:字母 LEVEL、最短词长 3、勾选折叠、内置词表。

  • LEVEL 共 5 个字母,互不相同的字母只有 L、E、V 三个,重复情况是 L 两个、E 两个、V 一个;
  • 不重复排法 = 5! ÷ (2! × 2!) = 30 种,正好是 5! = 120 的四分之一;
  • 30 种排法里,能对上内置词表的真词只有整词 level 一个;
  • 把最短词长降到 3 后,还能命中由部分字母组成的 eel、eve、lee,合计 4 个词;
  • 换一组字母 LISTEN:6 个字母互不重复,排法 = 6! = 720 种,其中长度正好 6 的真词有 listen、silent、enlist、tinsel、inlets 共 5 个,它们互为同字母不同序的整词。

再看一个折叠的例子:把 Café 填进去并保持折叠勾选,é 会被折成 e,字母组变成 C、A、F、E,最短 3 个字母能命中 cafe、face、ace 三个词;一旦取消勾选折叠,é 就成为一个独立字母、不再等于 e,词表里的 cafe、face、ace 全都缺一个 e,命中列表直接变成 0 个。

字母数、重复度与排列数对照表

下表把不同字母数与重复情况下的不重复排法数列出来。规律很直接:字母每多一个(且互不重复),排法就乘以新的字母数;出现一对重复字母,就把总数除以 2,两对就除以 4,三重就除以 6。

字母数重复情形示例不重复排法数
1无重复a1
2无重复ab2
3无重复abc6
4无重复abcd24
5无重复abcde120
5一对重复apple60
5两对重复level30
5三重重复eerie20
6无重复listen720
6一对重复banana60
7无重复abcdefg5,040
8无重复abcdefgh40,320

点「加载更多行」补上 9~12 个字母的几档,点「复制对照表」复制成制表符分隔的文本,点「导出 CSV」存成带 BOM 的 CSV(Excel 打开中文不乱码)。

输入范围、边界与精度说明

  • 字母数 2~20。少于 2 个无法构成任何一词,直接拒绝;超过 20 个时排法数会冲到 20! 量级(约 2.43×10¹⁸ 种),显示位数和计算量都不划算,也说明你多半是误粘贴了整段文本。
  • 最短词长 2~12,且不能超过字母总数。最短词长只是筛掉短词,不影响排列数;但它大于字母数时不可能命中任何词,本页会直接报错而不是返回空列表。
  • 数字、中文和绝大多数标点会被拒绝,空格、逗号、分号、顿号、连字符会被当作分隔符忽略。这样你可以直接粘 L-E-V-E-L 或 LEVEL, LISTEN 这种写法而不必先手工清理。
  • 折叠开关只影响「字母是否相同」的判断,不改变排列数公式本身。折叠后 E 与 e 被视为同一种字母,重复计数照常累加;不折叠时它们算两种字母,排法数会变大。
  • 词表为空时直接报错。本页不会偷偷用内置词表兜底——你清空它就是真的没有词表可查,返回空结果会让人误以为「一个词都拼不出」。
  • 「真词」的判定完全取决于你给的词表。内置词表是常见英文短词示例,不含词形变化(复数、过去式)与专有名词;要查这类词请把它们补进词表。
  • 排列数是精确整数,不是近似值。用 BigInt 算,超过 2⁵³ − 1 也不会丢位;统计卡里的数字带千分位只是为了好读。

常见问题

排列数 30 就是「能拼出 30 个单词」吗?

不是。30 是 LEVEL 这五个字母的全部不重复排法数,是纯数学结论;这 30 种排列里绝大多数串不是英文单词,真正落在词表里的只有 level 一个整词,加上短词才凑到 4 个。排列数和真词数是两个互不相干的口径,别混用。

为什么 LEVEL 只有 30 种排法,而 LISTEN 有 720 种?

因为重复字母要除掉重复的排列。LEVEL 里 L 和 E 各出现两次,5! ÷ (2! × 2!) = 30;LISTEN 六个字母互不重复,6! = 720。字母越重复,排法缩水越厉害,但也都还在同一个数量级,真正拉开差距的是字母数量本身。

大小写不同算不算不同的排列?

取决于折叠开关。勾选折叠(默认)时 E 与 e 是同一种字母,不额外增加排法;取消折叠后它们算两种字母,同一个字母组会因为大小写混用而多出大量排列。

带重音的字母是怎么处理的?

勾选折叠时走 Unicode 规范化:先把 é 拆成 e 加组合符号,再删掉组合符号,于是 é 等于 e,Café 折叠后就是 cafe。这正是 Intl.Collator 里 sensitivity:"base" 的行为;换成 "accent" 就只忽略大小写、保留重音。

词表里的词可以有大写和空格吗?

词表按字母扫描,空格、换行、逗号、分号都当分隔符,大写会被折成小写,所以你可以直接粘一段正常的英文文本进去,本页只从中提取单词。长度小于 2 的片段会被忽略。

为什么我贴了一大段英文,结果反而变少了?

因为词表变成了那段文本,里面能被这些字母拼出来的词自然有限。词表越大命中越全,但前提是这段词表本身包含你想找的词;想恢复内置词表点「载入示例」即可。

超过 20 个字母为什么被拒?

不是算不动排列数,而是数量级已经失去意义:20 个互不相同的字母有约 2.43×10¹⁸ 种排法,比 2⁵³ − 1 大出好几个数量级,显示和判读都无益;而且真词查找会退化成「在一大堆字母里翻词表」,结果多半是噪声。

结果会不会因为刷新页面而改变?

不会。词字母重组完全没有随机环节,同一份字母和同一份词表每次得到的结果逐字相同;刷新后输入回到页面默认值,点「重排字母」即可复现。

相关工具