
文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载在台球 9-ball 项目中想要得到所有合法摆球方式的完整清单本质是一个带固定锚点的排列permutation枚举问题1 号球锁定在菱形顶端、9 号球锁定在菱形中心剩下的 28 号七颗球可以任意换位。本文以 math/generate-permutations-of-all-valid-9-ball-racks.md 这份笔记为主线讲解如何用 Ruby 的Array#permutation优雅地生成全部 5040 种合法摆法并逐行拆解实现、给出验证与落地扩展方案。9-ball 摆球问题定义与规则约束美式 9-ball九球的摆球采用菱形diamond布局总共 9 颗球排成 1-2-3-2-1 的五行结构。合法的摆球必须同时满足两条硬性约束1 号球必须放在菱形顶端head即尖角那一颗9 号球必须放在菱形正中心即第三行三颗球中间的那一颗。在满足这两条约束之后其余 7 颗球2 号到 8 号可以任意摆放。如果我们把 9 个位置映射为一个长度为 9 的数组位置布局如下数组下标菱形位置0顶端head固定 1 号球1、2第二行两颗球3、5第三行左右两颗球4第三行中间中心固定 9 号球6、7第四行两颗球8第五行底端这样一来问题被精确地规约为为下标 1、2、3、5、6、7、8 这 7 个位置填入 28 号七颗球的所有不同次序。组合数学建模为什么答案是 7! 5040每个合法摆法都可以看作集合{2, 3, 4, 5, 6, 7, 8}的一个全排列每一颗球在七个位置中恰好出现一次。这正是组合数学中的排列permutation问题在初等组合数学中k-排列k-permutations或称为部分排列是从一个集合中选出 k 个不同元素的有序排列当 k 等于集合大小时它们就是通常意义上的全排列。当集合大小恰好等于要填的位置数都是 7时排列数就是阶乘7! 7 × 6 × 5 × 4 × 3 × 2 × 1 5040也就是说合法的 9-ball 摆球方式一共有5040 种。这个数字不依赖任何实现方式纯粹由组合数学决定固定 1、9 两颗球后剩余 7 颗球的自由度为7!。用 Ruby 的 Array#permutation 枚举全部摆法Ruby 的Array类内置了#permutation方法专门用于枚举排列不传参数时[a, b, c].permutation生成集合内全部元素的全排列即n!个当集合有 7 个元素时恰好生成7! 5040个。传入参数k时生成 k-排列部分排列例如[2,3,4,5,6,7,8].permutation(3)只生成每行 3 个元素的排列。无块调用时返回一个惰性的Enumerator可以用to_a或count等 Enumerable 方法消费带块调用时逐项 yield 并在结束后返回原数组本身。针对 9-ball 问题只需对七颗自由球做全排列再在每个排列的固定位置插入 1 号球和 9 号球即可。完整代码如下来自原笔记逐字可用[2,3,4,5,6,7,8].permutation.map do |perm| [1, *perm[0..2], 9, *perm[3..7]] end.to_a [[1, 2, 3, 4, 9, 5, 6, 7, 8], [1, 2, 3, 4, 9, 5, 6, 8, 7], [1, 2, 3, 4, 9, 5, 7, 6, 8], [1, 2, 3, 4, 9, 5, 7, 8, 6], [1, 2, 3, 4, 9, 5, 8, 6, 7], [1, 2, 3, 4, 9, 5, 8, 7, 6], [1, 2, 3, 4, 9, 6, 5, 7, 8], ... [1, 8, 7, 6, 9, 5, 3, 2, 4], [1, 8, 7, 6, 9, 5, 3, 4, 2], [1, 8, 7, 6, 9, 5, 4, 2, 3], [1, 8, 7, 6, 9, 5, 4, 3, 2]]这段代码只有两行主体逻辑却完整表达了全部规则约束是用数据结构承载规则的典型示范。代码逐行拆解1. 生成七颗自由球的全排列[2,3,4,5,6,7,8].permutation#permutation不带参数时生成包含全部元素的全排列。注意它是惰性的不传入块时返回Enumerator真正的排列序列只在被消费如map、to_a、count时才逐一生成因此即使有 5040 项也不会一次性占满内存。2. 把排列拆成中心之前与中心之后两段perm[0..2] # 下标 0、1、2共 3 个元素 perm[3..7] # 下标 3、4、5、6共 4 个元素perm是长度 7 的排列数组。perm[0..2]取前三个自由球负责填到 9 号球中心位置之前的下标 1、2、3perm[3..7]取剩余四个自由球填到中心位置之后的下标 5、6、7、8。切片两端合计恰好 7 颗球一个不重不漏。3. 用 splat 展开并锚定 1 号与 9 号[1, *perm[0..2], 9, *perm[3..7]]Ruby 的 splat 运算符*会把数组展开成多个元素插入到新的数组字面量中。这里在字面量里固定写入1顶端和9中心再把两段自由球展开到对应位置最终每行都是一个满足全部约束的长度为 9 的摆法数组。4. map 后 to_a 物化结果.map do |perm| ... end.to_amap消费Enumerator并把每个排列转换成对应的 9 球数组to_a把整个序列物化为可重复使用的Array。去掉to_a得到的是惰性枚举器适合后续链式处理例如配合count、select、sample。验证与落地扩展校验数量与约束可以用 Enumerable 方法直接验证结果符合数学预期racks [2,3,4,5,6,7,8].permutation.map do |perm| [1, *perm[0..2], 9, *perm[3..7]] end racks.count # 5040与 7! 一致 racks.uniq.count # 5040无重复 racks.all? { |r| r.first 1 } # 1 号球总在顶端 racks.all? { |r| r[4] 9 } # 9 号球总在中心 racks.all? { |r| r.sort (1..9).to_a } # 每行都是 1..9 各一次这四个断言分别对应排列数正确、无重复、两条硬性约束成立、每颗球恰好出现一次四者共同构成对结果完整性的充分验证。将全量清单导出到文件如果要把 5040 种摆法持久化可以直接把结果逐行写出File.write(9-ball-racks.txt, racks.map(:join).join(\n))随机采样一副合法摆球从全量清单中随机取一局比手工洗牌更可控racks.sample # 例如 [1, 5, 8, 3, 9, 2, 7, 4, 6]惰性枚举的其他消费方式因为#permutation返回Enumerator在构造阶段并不实际生成 5040 个数组还可以直接消费而无需物化[2,3,4,5,6,7,8].permutation.lazy .map { |perm| [1, *perm[0..2], 9, *perm[3..7]] } .first(5) # 只取前 5 种避免全量计算这个思路在自由球数量变大排列数指数增长时尤为重要。小结9-ball 合法摆球的枚举是一个教科书级的组合数学应用先用规则约束把问题降维为7 个元素的排列再用7! 5040确定规模最后用 Ruby 内置的Array#permutation加 splat 数组构造两行代码便完整产出全部合法摆法。原笔记收录于 math/generate-permutations-of-all-valid-9-ball-racks.md同目录下的 math/convert-arbitrary-number-to-probability-with-sigmoid.md 是另一篇数学主题笔记仓库 README.md 按类别索引了全部 TIL 笔记Ruby 相关的更多数组与 Enumerable 技巧可参考 ruby/summing-collections.md、ruby/get-specific-values-from-hashes-and-arrays.md 等条目。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐tech-interview-for-developer 算法篇排列、组合与子集枚举的 Java 递归回溯全解순열 조합tech interview for developer 算法篇排列、组合与子集枚举的 Java 递归回溯全解순열 조합 排列与组合是算法面试与编程竞教程知识库TypeScript 枚举完全指南数字枚举、字符串枚举、const 枚举与外部枚举TypeScript 枚举完全指南数字枚举、字符串枚举、const 枚举与外部枚举 导读本指南以 TypeScript 中文使用手册 https://lin文档教程TypeScript枚举类型详解数字枚举与字符串枚举的完整用法TypeScript枚举类型详解数字枚举与字符串枚举的完整用法 TypeScript枚举类型是TypeScript中一个强大的特性它允许我们定义一组命名的常文档教程上一篇LinkSwift九大网盘直链下载的终极解决方案下一篇Pilot Shell Console架构揭秘Bun、Express、React与SQLite技术栈完整拆解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考