雜記 › 技術筆記 › 8 個元素算得出 40320 條卻只列 5000 行:排列計算器的兩道互不相干的上限、重複元素按 3! 計數與 n≤20 的過程斷點

8 個元素算得出 40320 條卻只列 5000 行:排列計算器的兩道互不相干的上限、重複元素按 3! 計數與 n≤20 的過程斷點

排列數算得出 40320 條,清單只寫 5000 行:兩道互不相干的閘、重複元素按 n! 出條數、n≤20 才給展開與約分、呼叫點 0 處的死函式,全在字串層逐筆實測。

40320 條與 5000 行同屏

元素框裡敲 8 個單字母,「排列總數」欄寫著 40,320,清單拉到底只有 5000 行,尾行補一句「共 40320 種排列,僅顯示前 5000 種」。把 permutation.html(實測 233 行 / 9158 位元組)逐字摘進純 Node 探針跑一圈才發現,它有兩把互不相干的尺:一把管算數,一把管往螢幕上寫幾行,而中間那臺生成排列的機器不認「元素長得一樣」。

兩道閘各判各的

L177 的 if (n > 8) 判的是切分之後的元素個數:9 項以上四組原文得到同一句 toast「元素數量超過 8 個,排列數過多,請減少元素」,且這條 return 在 heap 之前,清單長度為 0。

L215 的 maxShow = Math.min(perms.length, 5000) 判的卻是顯示行數,perms 在記憶體裡始終滿著:n=7 實生 5040、只寫 5000 行、藏 40 條,n=8 實生 40320、同樣只寫 5000 行、藏 35320 條。5000 落在 720 與 5040 之間,9 檔裡只有 2 檔撞尾行。測的這一頁是排列計算器。

元素個數 → 實生條數 → 寫到螢幕上的行數 n = 6 720 720 尾行不出現 n = 7 5040 5000 藏 40 淡色實生 5040,深色寫出 5000 n = 8 40320 5000 藏 35320、12.4008% n = 5:120 → 120 行

圖 1:同一批 n 檔上,實生條數與顯示行數各是多少。

heap 只按下標交換

heap 全程按 k 的奇偶交換兩枚下標,從不比較元素值,所以重複元素按 n! 出條數:A, A, B 出 6 行、去重 3 條;A, A, A 出 6 行且全同、去重 1;甲 / 甲 / 乙 也是 6 行 3 條。介面兩處(總數欄與「n! =」統計行)都寫 n!,不寫不重複條數;批次 40 組原文裡去重數小於寫出行數的有 11 組。這些都只是這一頁的行為,推不出「這類工具都這樣」。

實生 / 去重 / 露在前 5000 行裡 A, A, B 6 行 3 條 全部可見 A, A, B, C, D, E, F, G 40320 行 20160 條 前 5000 行裡 2520 種 A, A, A, A, B, B, B, B 40320 行 70 種 前 5000 行裡 35 種

圖 2:介面那個數與兩本真實的帳。

展開與約分只在 n ≤ 20 給

L136 那道 if (n <= 20) 決定過程面板給幾行:n=5,r=3 給 4 行,n=20,r=7 仍 4 行且約分行 7 個因子、結果 390,700,800;n=21,r=1 起只剩 3 行,展開與約分整段換成一行「結果」(n=22,r=22 同)。約分行的因子個數恆等於 r,r=0 時那一格寫成「約分: = 1」。

generate 側沒有這道分支:calc 對 n 沒上限,n=100000、r=2 照樣給 9,999,900,000,只是耗時 9553.75 ms。階乘本身在階乘計算那頁。

分隔正則先替你改了 n

L170 的字元類 /[,、\s,\n]+/ 把兩種逗號、頓號、換行連空白類一起當分隔。New York, 北京 因此解析成 3 個元素,介面按 3!=6 報條數,而使用者想的是 2 個;反過來 A;B 只切出 1 個元素——全形分號不在字元類裡,半形分號、豎線、連字號同樣不分。

兩條靜默路徑分開:trim 後為空走 L164,原文只由分隔符組成時 n 為 0、走 L173,兩者都是面板隱藏、無 toast、總數欄沒被寫過。L173 不是死程式碼,一個逗號就命中。

fmt 是呼叫點 0 處的死函式

詞邊界正則數下來,fmt 只命中 L102 的定義、呼叫點 0 處,fmtBig 命中 6 處,顯示全走 BigInt 字串。Number 那把尺躺著,卻藏不住兩處分界:寫法分界在 22!,它寫作 1.1240007277776077e+21 而值仍精確;精度分界在 23!,BigInt 口徑 25852016738884976640000、回讀 double 得 25852016738884978212864,是兩個不同的數。

onclick 是拼出來的

L218 把 join 後的元素串塞進單引號實參,只轉義單引號。字串層兩條實測:元素含單引號時屬性串是 copyItem(this, 'A\', B'),解析這段 JS 得回 A', B,與該行可見文字去掉行號前綴後相同;元素含雙引號時,onclick 的值在第一個雙引號處就閉合,屬性正則只能取到 copyItem(this, 'A 這半截;元素含小於號時該字元原樣進 innerHTML,瀏覽器解析成什麼未實測。

兩套口徑分開:innerHTML 注入後的結構、toast 呈現與 2500 ms、複製回饋與按鈕文字 1500 ms 還原、type=number 把 5.7 與 1e3 寫進 value 什麼、渲染 2019032 位元組清單串要多久,本批未開瀏覽器,一律標未實測。字串這側能說:n=8 時清單裡 onclick 片段數是 5000,第 40320 條沒有複製入口——節點不存在。

切回去一定重跑

L82 切回哪側重跑哪側:切回 calc 後結果欄是按 n=12、r=2 重算的 132,不是切走前的 60;r 大於 n 時函式在寫 textContent 之前就 return,節點留著舊串而 display 已是 none,generate 側換成 9 項後那 2019012 字元一字未清。

15 條文案判定

config/tools.php 第 885 行起該條目與模板兩枚 hint 逐條判:一致 7、衝突 2、部分一致 6。

文案實測判定
每個排列可複製n=8 時清單只有 5000 個可點條目,另 35320 條無入口衝突
從 n 個不同元素中取出 r 個不校驗互不相同,A, A, B 按 3!=6 計衝突
最多支援 8 個元素(8! = 40320 種排列)8 與 40320 成立,5000 沒寫進任何文案部分一致

5000 在模板裡命中 3 處(L215、L220、L221)全在程式碼裡,5040 命中 0 處,唯一露出它的是尾行,且不帶千分位,與同屏的 40,320 兩種寫法。排列與組合的概念區分舊文排列與組合講過,不重講。

Q:那 40320 到底算錯沒有?

沒算錯。40,320 既是 factorialBig(8),也是 8 個元素實生的 perms.length;誤會只在把總數欄當成行數——螢幕上停在 5000 行,另 35320 條還在記憶體裡,沒有出口。

Q:有重複元素時怎麼只留一條?

這一頁沒有去重開關,兩處都寫 n!。字串層的折算是 n! 除以各值出現次數之階乘的積:A,A,B,C,D,E,F,G 由 40320 折成 20160,那一檔在前 5000 行裡只露出 2520 種。

Q:切一下 tab 結果就變了,是沒儲存嗎?

是重跑不是遺失:切回必按當前輸入再算一次,非法輸入只藏面板、不覆寫舊串,於是「隱藏但殘留」。

📎 相關文章

投放連結的裝配順序與大小寫摺疊:UTM 產生器六態標註、兩道硬上限與五欄各用一把尺實測 2026-11-12 13 格演算法表與 7 道驗簽閘門:JWT 工具頁驗簽側的分支比解碼側更窄,逐演算法真簽真驗矩陣 2026-11-12 拖到 4 和拖到 8,螢幕上都是 43890 個塊:馬賽克預覽與導出的兩套塊網格、三檔會崩與 6px 誤觸閾值 2026-11-10 位圖進 SVG 只是換了個盒子:232 字節的容器常數、一個從不生效的「base64 嵌入」勾選,與四檔縮放下紋絲不動的 142064 個字元 2026-11-10 轉完悄悄少了 271 個字符:Markdown 轉 HTML 的洞協議、64 輪回填與 20 條提示上限 2026-11-10