一點哲學探討
DANGER
本頁面充滿了個人主觀意見。請批判性閱讀。
本章預設讀者瞭解至少一種形碼。
You could have invented Moran——魔然設計的邏輯
魔然方案可以看作是沿着「智能拼音掛接」路子走到盡頭的產物。具體來說,整個設計是從一個根本出發點開始,依邏輯不斷推演得到的產物:
- 想打詞
- 爲了打詞輕鬆,詞語編碼應該以音碼爲主
- 爲了詞語碼長短,以雙拼爲基礎
- 爲了詞語編碼空間儘可能大(雙拼離散較差),選擇不定長編碼
- 爲了不定長編碼、兼容純雙拼、自動造詞等功能,選擇基於整句實現
- 爲了解決整句的不確定性(在開啓了用戶詞庫時),設置固定簡碼
- 爲了讓簡碼的條反可以延續到整句,整句必須支持輔助碼混輸,並且整句用的輔助碼必須和簡碼中用到的形碼是一致的
(其實上面每一步都值得寫一小節來解釋我的理由,不過這裏就從略了。)
因此,整個魔然方案是完整的一體,各模式其實並不能分開來看。(除了輔篩是例外,它可以乾淨利落地拆成別的方案。)
The Consistency Question——簡繁字形的兼容性
雖然上面說得一套一套的,但是魔然最初的出發點並不是「我覺得市面上的方案都不適合我!我要做一個最強的輸入方案!」,而是一個小小的想法:「我要實驗一下有沒有方案可以同時兼容簡繁字形!」——當時,我還在使用形碼。
這個想法最初來自於 2022 年筆者對小鶴音形的嘗試,發現雖然小鶴音形的碼表是簡體字,但是轉換成繁體後,大部分字的編碼其實不變。再加上考慮另一個極端:純音碼可以無縫兼容簡繁字形。那是不是只要形的部分越少,兼容性就越好?
在初期嘗試的過程中,我很快確立了部首優先的原則,即第三碼應該是部首,不是拆字拆出來的第一個部件。這是因爲它有很多我最初甚至沒有預料到的好處:
- 漢字中部首不出現在左邊或上面的情況比想象中得多,可以提高三碼離散。
- 如:「栽載哉」分別可以用 zlm zli zlk 輸入,「墓幕暮慕募」分別可以用 mut muj muo mux mul 輸入,「形型」分別是 xyp 和 xyt 而不會被「开」干擾
- 部首和字義有強關聯,拆字時往往不用思考字形,而是只需要想到字義,就能打出這個字。
- 如:壟(與土有關),攀(與手有關),憂(與心有關),暮(與日有關),毫(與毛有關)
- 部首往往可以恰好把一類字的不同字形歸類在一起。
- 如:「
勸勧劝」都是qrl,「憂忧」都是ybx
- 如:「
最初的魔然字詞碼表是同時容納簡體和繁體的,但是後來發現雖然整體上一致性很高,但是高頻字中還是有不少字三碼不一致。很多用戶反饋自己不會繁體字,需要一個純簡體的碼表,於是這才另外製作了簡化字版本。——筆者雖然日常打簡化字不少,但是依然使用繁體版,所以筆者認爲只要您不抗拒繁體字(碰到三碼不一致的情況時,您的第一反應是「又學到了」而不是「又被坑到了」),都可以先嘗試嘗試繁體版,也許有意外之喜呢。
因此,我認爲關於簡繁字形的實驗本身已經完結了。結論是:成功!雖不算 100% 完美,但完全可以接受,甚至超出預期。
The Unreasonable Effectiveness——爲什麼魔然如此好用
背景
如果您讀了上兩節,可能會注意到魔然一開始並不是爲了「降低碼長」「提高打字速度」等目標設計的,而是作者個人的一個小小實驗品,單純是爲了實驗音形碼對簡繁字形的兼容性。從另一個方面說,也是爲了解決作者個人一個極小衆的需求。
而其他設計,也都恰好只是這個需求催生來的——我只是希望音的部分夠多(哪怕我長時間不用,也可以快速撿起來),而恰好我想少點選重,所以選擇以「掛接用法」爲藍本而已。
當時(2023年初),我使用的是一款名爲虎碼的形碼方案。我做魔然單純是一個實驗,打算在得到結論後,就回到虎碼。唯一沒想到的是,這個實驗竟然相當成功,以至於我逐漸「樂不思虎」,在魔然扎根了,至今已經使用快 2 年。
但與之相對的是一個顯然的悖論:自然碼本身並不是一個追求性能的方案。單字重碼率不低,詞重更是不低。以通常視角來看,它不應該好用啊!
理論預言錯得這麼離譜,讓我不得不做了一些分析:魔然究竟爲什麼好用?傳統的評價指標到底「錯」在哪?
或許,我們選擇的指標根本不對——一個新的輸入法評價指標
筆者認爲,在全拼都能滿足大部分用戶的大背景下,漢字輸入最重要的指標已經不是硬性的「碼長」「確定性」等,而是一種(虛無縹緲的)「輕鬆感」「流暢感」,或者說,是實際輸入中「輸入法本身存在感的稀薄程度」。
Note:我認爲任何輸入法方案作者都應該注意到這一點:如果輸入法評測所用的硬性數據指標真的那麼重要,那全拼根本不應該成爲最流行的輸入法。
因此,任何評價輸入法的指標都應該接受全拼檢驗:你所預言的「好用程度」必須與全拼的流行程度一致。假設你選取的評價標準得到的結論是「全拼是最差的輸入法」,那必須解釋爲什麼你的預言和現實不符。
如果以「輸入法本身的存在感稀薄程度」爲標準,我們可以立即注意到:
- 音碼(以智能拼音和智能雙拼爲代表)的存在感在選重時會顯現出來。
- 形碼的存在感在 (1) 拆字 (2) 選重 時顯現出來。
並且存在感會隨時間累加:上面提到的事件如果耗時越長,存在感就越強。
因此,爲了讓輸入更流暢,我們需要最小化拆字和選重的負擔。下面我們來看看各輸入法是怎麼做的:
- 智能拼音:不斷提高智能化程度,通過大量數據分析字詞頻率和關聯,減少選字頻率
- 形碼:
- 針對拆字的存在感:
- 強調訓練高頻字條反,從而降低拆字頻率
- 設計更大的字根從而讓拆字更直觀,從而降低拆字用時
- 針對選重的存在感:設計更大的字根、更怪的拆字、亂序分佈字根、出簡讓全、出簡不出全等方法,從而降低選重率
- 或者可以直接打純單,這樣就完全沒有詞重帶來的存在感了
- 針對拆字的存在感:
那麼魔然所屬的雙拼加形類別呢?
- 針對拆字的存在感:
- 通過設置簡碼,降低了拆字頻率(一簡和二簡不需要拆字)
- 通過只取首末、字根音托,降低拆字耗時(思維負擔的減少體現在時間縮短上)
- 通過置前兩碼爲音碼,拆字與輸入音碼可以同步進行,降低拆字的實際耗時
- 針對選重的存在感:
- 輸入整句時,可以復用智能拼音的算法和一切成果
- 通過輔助碼,可以降低選重的耗時
- 通過有策略地拆單,可以降低選重的頻率
總的來說,雙拼加形是對智能拼音的一個嚴格改進:它具有智能拼音的一切優勢(從而有相同量級的選重頻率),又有智能拼音所不具有的更多能力(這些能力可以降低選重頻率),代價是一點學習成本。
在這裏,我提出一個初步的量化方法:
存在感 = 選重頻率 * 平均選重耗時 * w1 + 拆字頻率 * 平均拆字耗時 * w2
(其中 w1 和 w2 是特定的加權係數,表示用戶對這種存在感的厭惡程度:如果用戶極度厭惡拆字(即提筆忘字還覺得這不是個事兒),那麼他可以把 w2 設置爲一個很大的數字。一般來說,爲了討論簡便,不妨就設置 w1 = w2 = 1。)
「存在感」衡量了「僅僅因爲輸入法本身問題、導致用戶額外付出的時間」(對不存在拆字和選重的方案也可以提出類似的指標),而在一個理想的輸入法裏,這個值應該是0。它並不衡量用戶本身導致的輸入錯誤問題(即鍵準不計入計算)。
事實上,在引入一些假設的前提下,存在感的確可以是 0:
- 智能拼音用戶在合適的文本上,可以做到 0。
- 形碼用戶對所有字全部條反,只打純單,可以做到 0。
- 雙拼加形用戶預判所有重碼,單字條反,可以做到 0。
上面的公式中並沒有出現碼長、手感等很多輸入法發燒友熟悉的指標。或許……這並不是一個巧合?事實上,我們可能都有過這樣的體會:用過一個方案,覺得它非常順手,但是絕對速度卻不快;或者用過一個方案,絕對速度不低,但是怎麼用怎麼覺得不爽。
因此,我認爲「存在感」可以較好地從用戶側終端衡量輸入法的實際體感好用程度。每個輸入法的存在感值甚至可以通過實驗測量出來。
這個指標可以用來測試用戶本身。試設想以下場景:
- 某方案事實上是無理碼,故在無外界幫助的情況下,拆字耗時可設想爲無窮大,而用戶不可避免地會碰到之前沒打過的字,需要現拆,或
- 某拼音輸入法每打一字都需要選字,且輸入法的順序完全錯誤,使得選字耗時極長
則用戶必然不會選擇這樣的方案。這意味着,用戶必然存在一個「存在感耐受」的上限。
上限可以用於選擇最適合用戶的方案:若用戶通過估算或實驗得到了自己的耐受上限,就可以選擇存在感在該上限以下的、性能最佳的輸入方案——也就是對自己來說最優的輸入法。這個指標也提供了一個評價方案的新維度。如果在任何情況下,方案A的絕對性能都較方案B更差,且存在感都更高,那麼我們就有必要嚴肅地質疑這樣的方案的意義爲何了。
這個指標很有可能是不完備的。在本文中,我們假設 w1 和 w2 都只是用戶本身的偏好,但這可能不對。例如,對拼音用戶來說,選重是日常生活的一部分,所以碰到選重時不會有嚴重的抗拒心理;而對形碼用戶來說,任何一次非預期的選重都會帶來嚴重的負反饋。這意味着上式中的 w1 和 w2 可能還與方案本身有關,而不只與用戶有關。
或許,收益與難度不成正比——爲易學性正名
從樸素的理解看來,一分耕耘一分收穫,那麼自然方案上限要高,自然也會更難。下更大力氣練習,速度也會提升。那麼我們是不是應該總是追求高上限、追求「更難」的方案呢?選擇此類方案,意味着有更高的理論上限,就算自己不想練習到那麼高的水準,也可以停在自己喜歡的水平上,以後想精進了可以隨時精進。
在筆者看來,並非如此。甚至恰恰相反,大部分人應該更多看看那些「簡單」的方案。我們不妨解構一下所謂的「難度」究竟是什麼。以典型的形碼爲例,從一個用戶的角度出發,要打一段話,用戶需要進行這些活動:
- 斷句分詞;
- 對詞語進行編碼,進一步地,
- 對單字進行編碼,將單字拆分爲字根;
- 將字根映射到鍵盤鍵位上。
熟習形碼的用戶可能會立刻反對上面的說法:「不,我已經條反了單字/詞語,所以我不需要再拆字/想字根了!」但假設一個用戶從未進行專項學習和刻意練習,它將不得不經過這幾道工序。事實上,通過刻意練習,從而跳過了一部分步驟,這正是所謂的 學習成本 。(當然,也正是因爲字詞有固定的打法,這樣的刻意練習才成爲可能。)
至此,我們把 方案難度 還原成了有明確定義的幾項學習成本。你付出多少學習成本,就能跳過某些字詞的某些步驟,從而提升速度。
接着,另一些形碼愛好者或許會指出,上面的流程其實有些囫圇,如一些方案的字根是非常有規律的,而步驟 5 渾而言之,對這些方案不公平。另一些人也會指出,其實拆字往往不是直接拆到字根,而是拆成大塊組件,然後再把大塊組件拆成字根,這樣學得更快。的確如此:根據排列組合的基本原理,流程越長,每個步驟中的學習成本就可以越少,而平均每字上的學習成本也越低。設有
舉一個簡單的例子。假設我們要編碼 10000 個字:
- 方案 A:只有一個步驟,所以我們需要死記這 10000 個字的編碼,成本爲 10000 單位。
- 方案 B:有兩個步驟,每個步驟有 100 單位成本,總體上也可以覆蓋 10000 個字,但成本只有 100+100=200。
但既然如此,我們爲什麼不構造一個步驟非常多、從而非常簡單的方案呢?這是因爲「步驟」的設計本身不能太天馬行空,還是要符合人類的直覺。此外,爲了讓編碼簡單,一般應該讓多個步驟的編碼結果做非常簡單的映射和組合,否則編碼會非常困難。一個例子就是五筆的識別碼,它的原理很簡單,但還是被大部分用戶詬病。
要點就在這裏:步驟本身沒法太多。因此,爲了提升性能,許多方案會(1)增大步驟內的內容量 和/或 (2)減少步驟。預期是用戶付出學習成本後,可以直接形成條反,而更少的步驟,可以強迫條反更快形成、生字編碼時的反應迴路更短。但上述簡易模型和均值不等式指出,當我們嘗試把步驟減半時,學習成本的上升遠遠超出 2 倍。以 10000 字爲例,4 步驟的方案 A 成本可能是
假設小張選擇了 A 方案,而平行宇宙中的大張選擇了 B 方案,那麼在相同的練習量(字數)下,小張和大張都可以以高速打出條反了的常用字,但要學會剩下的字,大張需要付出遠遠超出小張的學習成本。更雪上加霜的是,這些字可能由於過於低頻,而永遠無法條反。也就是說小張更容易條反更多的字,最終在相同練習量時可以打出比大張更快的速度。換句話說,易學方案的「條反轉化率」更高。
雖然上面的分析比較粗糙,但我相信應該可以論證:易學的方案在實踐上更容易打出高速。至少這是有理論上的可能的。因此,筆者認爲不應該盲目鄙視易學方案,更絕不應該在不追求高速時選擇高難方案,因爲理論分析已經指出「選擇高難方案並停留在低水平」的性價比低於「直接選擇一個易學的方案」。
或許,單字重碼率沒那麼重要——雙拼加形的特殊性
上一節的討論是完全基於單字的,這是因爲形碼打詞的基礎也是單字——大部分形碼的詞語編碼也無非是單字編碼的拼合。
對雙拼加形,表面上看詞語也是單字編碼的拼合,但事實上需要注意到雙拼加形的單字編碼是兩種異質信息(音和形)的拼合。打詞時,可以完全繞過形,即打詞的學習成本其實反而低於打單,與形碼是完全相反的:對很多人(包括筆者)來說,打詞越多,思維負擔越輕。而更有趣的是,打詞的碼長一般也比打單更短。綜合來說,對雙拼加形來說,打詞速度更快。或者更直白地說,打詞和打單是兩種不同的心理過程,打詞是其中更輕鬆的那個。
既然實際輸入中打詞是不可或缺的一部分,總體過程就是:斷句分詞→詞語直接打音碼→餘下的單字通過打單的方式輸入。在這種模式中,打單量其實並不多,而且大部分需要打的單字都是有語法功用的詞,如「的」「地」「得」「了」「者」「式」「就」等,或者是一些頻繁單用的字,如「打」「去」「走」「跑」「提」「喝」「喫」等。只要給這些字固定打法,其實日常打字的不確定性就已經減少很多了。
「那如果一定要打生僻字呢?重碼率高怎麼盲打?」這裏或許我們應該反過來問:如果有大量生僻字本身是重碼的,那麼爲什麼要期望可以盲打「任何一個生僻字」呢?你在打這個字之前,是無法預判這個字有沒有重碼、是否需要選重的,所以無論你打哪個生僻字,都無法避免看候選窗。因此,不妨採取最激進的策略:乾脆放棄所有生僻字的選重性能,爲易學易用優化。
「難道詞語(音碼)就沒有重碼嗎?」不,詞語不僅有重碼,而且還不少!但這些重碼主要來自二字詞。因此,打二字詞時一般需要打輔助碼,從而減少不確定性。
「但這不就又引入了新的難度了嗎?」是的,但或許,我們可以不付出更多成本就能解決這個問題?
INFO
下面的討論只適用於默認模式。
要解決詞重,一個方法是引入越來越智能的語法模型。但魔然探索了另一條路。
魔然首創的「整句輔助碼混輸」(俗稱「句中輔」)可以與固定簡碼聯動,從而引入了一種特殊的功能—— 以單馭詞 。
舉例來說,一個熟習簡碼的用戶,會習慣於使用 lig 輸入「力」、用 lih 輸入「利」。那麼他在打詞時,輸入 lig 和 lih 其實也是下意識的,這就意味着,他可以在不付出任何額外適應和學習成本的前提下,完美區分:
- 有利yblih 有力yblig
- 權利qrlih 權力qrlig
另一方面,即使這個字在前面,也不用擔心,只要無腦打字即可:
- 易用yioys 已用yivys
- 使用uiys 適用uizys
而這個學習過程是雙向的。熟練打單字時,打詞會直接得到幾乎免費的加成。另一方面,即使對單字不熟悉,那麼打詞加輔打到第三碼,也會對未來在打這個單字時有所加成。
換句話說,熟練掌握單字後,並不只能打單,還可以大幅提升打詞的確定性。這與定長碼的「單-詞對立」不同,與「智能拼音掛接碼表」不同,甚至與「直接輔助碼輸入法」不同。比較相近的是形碼整句輸入,但我相信到目前爲止的討論已經給你足夠的啓發。 😃
或許,選重並不影響確定性——次選的妙用
打字速度的一方面是重碼率,它決定了我們打字過程中遇到的「驚喜」有多少。而另一方面就是碼長,它在某種程度上更顯著地影響實際打字速度。許多全拼用戶反對雙拼的理由就是,雙拼沒有簡拼,而全拼使用簡拼時,碼長是很短的。他們是對的。至少對於一些常見場景來說,簡拼的碼長可以遠遠低於雙拼。
在魔然中,根據筆者的實際打字實踐,6 碼輸入三字詞不僅準確度高,其實也沒那麼煩。而在輸入一些超長詞(大於 8 碼)時,會感覺有點麻煩。因爲以前用過定長碼,就會覺得很多按鍵是沒意義的——明明能 4 碼解決,爲什麼要打那麼多鍵?比如「維特根斯坦」,用簡拼只要打 wtgst 就可以了,而雙拼需要打 wztegfsitj 十碼!按鍵越多,其實就越容易犯錯,錯了又要苦哈哈刪改。
出於這種考慮,魔然默認開啓了 inject_fixed_words 設置,在輸入 4 碼時可以注入碼表裏的長詞,並且一定注入到次選位上。有趣的是,因爲注入位置是固定的,反而導致默認模式在打長詞時確定性比字詞模式還要高!字詞模式中,4 碼的單字、二字詞、長詞全部混在一起,按頻率排序,在實際看到候選之前其實很難預判到底按哪個鍵。但在默認模式的開箱設置中,4 碼只要有詞就一定是詞;而對於長詞,只要知道有這個詞,一般只需要無腦按分號。比如上面提到的「維特根斯坦」,也只需要打 wtgt,比簡拼還短。
這種設計不僅壓縮了長詞的碼長,其實還提高了長詞的輸入確定性(相比字詞模式)和誤鍵可能性(相比打全雙拼),可謂兩全其美。
另一方面,爲了避免從四碼到整句輸入時的割裂感,開箱設置中強烈傾向於讓四碼首選是二字詞,且它是動態調頻的。魔然預期在一段時間後,候選可以逐漸收斂到適合自己的順序。對於少數不收斂的情況,可以使用 pin 功能強行固定,從而完全打造適合自己的詞序。(當然,也可以直接打開「固詞模式」。即使在固詞模式下你也在養用戶詞庫,這是魔然的一個絕技。)
結論
魔然方案體現了一種有別於以往的音形輸入方案的設計取向。筆者認爲魔然式的輸入方案有如下特點:
- 編碼維度:結合通用雙拼和直觀形輔,降低學習成本。但是難以輸入不知道讀音的字。
- 交互維度:以詞語爲主。「以單馭詞」打破單字和詞組的隔閡,將單字熟練度直接轉換成區分重音詞的能力。缺點是碼長相比四碼方案更長。
- 性能維度:單字簡碼是主要的確定性來源。將長詞注入 4 碼次選位,不僅壓縮碼長,還通過固定注入位置提高了確定性。
- 體感維度:承認低頻字詞輸入的不可預測性,轉而優化日常高頻輸入的流暢度(選重耗時和拆字耗時)。但選字無法完全避免。
這種設計取向並不適合所有人,但如果你認同這些理念,不妨一試!
The Dialectical Reversal——談談「簡繁通打」
很多和我一樣有傳承字輸入需求的用戶,往往要麼使用純音碼,要麼使用純形碼。純音碼暫且不論,形碼則往往只優先考慮一種字形,另一種字形則後置。對於需要經常切換兩種字形的用戶來說極爲不便,因此便產生了所謂的「簡繁通打」的說法:讓簡體字和繁體字的編碼不重碼。例如, 馬 和 马 放在不同的按鍵上。典型的方案有徐碼和宇浩碼。
INFO
我個人認爲「簡繁通打」是有誤導的宣傳命名。沒有細看定義的用戶容易誤解「只有簡繁通打的方案才能輸入繁體字/簡體字」。但事實並非如此。一個不簡繁通打的方案完全可以收錄整個 Unicode 字集——那當然也可以輸入繁體字。本節討論中暫且繼續使用該命名。
這類「簡繁通打」方案聲稱自己解決了字形切換問題。當然,在一定程度上,的確如此。設若你需要臨時輸入繁(簡)體字,直接打繁(簡)體字編碼即可。這類方案的實質是通過編碼強行將「全等異體字」分離,目標是在無上下文/無模式切換的情況下,快速輸入另一種異體字。
然而,在我看來,此類方案有着以下缺陷:
- 若設置簡碼,而簡碼空間有限,則必然會優先一種字形。這又重新產生了簡繁之間的不平等性。
- 一些方案認爲這是必要的妥協,提供多種簡碼表。
- 一些方案認爲這是嚴重的問題,直接放棄簡碼,用戶應該只打全碼。
- 還有一些提供簡繁混頻排的簡碼表,但這會降低碼表效率。(我曾見過某方案中
爲為为中的多個均被設置成一簡。)
- 需要額外記憶另一種字形的字根映射。若另一種字形用得不多,遺忘後會比較麻煩。
- 由於簡繁字形編碼不同,如果需要大量輸入另一種字形,則需要建立兩套條反。
由於這些缺陷,私以爲大字根的簡繁通打方案的優化目標,其實受衆很小——大概需要接近 1:1 比例日常輸入簡繁字形,以至於能建立兩套穩定條反而不遺忘。但即使在這種情況下,學習成本也比較高。
問題在於,簡繁之間一般是異體字的關係,而且大部分是全等異體字。所謂的全等異體字就是音義皆同,只有字形不同的一組字,如 連 和 连 就是一組全等異體字。但我們爲什麼一定要「分離」才能「通打」呢?是不是其實「合併」更容易「通打」?以前似乎沒有人提出過這樣的看法。
私以爲答案是肯定的。要支持多種字形,同時還要降低使用負擔,那麼要做的不是「分離」,而應是「合併」。更需考慮到,簡體和繁體只是全等異體字的一小個側面。對於一个字來說,它可以有不止兩種異體。具體選用哪種異體字,是由「正字法」給出的——大陸的規範字、臺灣的正體字、香港用字標準、日本當用漢字表等,都是「正字法」。
假如說,我們恰好可以讓全等異體字重碼(與「簡繁通打」類方案恰恰相反),那「正字法」就可以通過一套配置文件給出。通過簡單的模式切換,就可以輕鬆輸出「簡」「繁」「日」乃至別的正字法標準,同時我們思維上並不做任何切換,並且輸入效率不受影響。
也就是說,我們需要追求的是「全等異體字之間」恰恰應該重碼,而不是全等異體字關係的字之間應該不重碼。
自然碼巧妙的設計幾乎完美實現了這個目標。雙拼的 2 碼音碼和自然碼的「部首優先」規則,使得絕大多數字全等異體字都具有相同的 3 碼。如在使用魔然時打開「字集增廣模式」,往往在輸入 3 碼時,可以看到一大批形似的字,並且一般還真就是異體字關係。如输入 lqe 可以看到「 陸陆𲉊𨸪𨽐𨽰 」,只有一個「 𨻧 」不屬其列。更神奇的是,很多異體字 4 碼也真的就剛好重碼(試試輸入 yjtmo)。
總的來說,在異體字處理上,我認爲(受控的)「合」遠遠好於「分」。「分」唯一的好處是不用切換模式,但收益似乎並不比代價更大。所以我不認同「簡繁通打」。
INFO
開放問題:可否設計一種方案,前 N 碼恰好歸類全等異體字的等價類,而輸入 N+M 碼又可以把同一個等價類中的字區分開?