大家好,我是 A Fei,今天是連假最後一天,雖然正在忙轉職根本沒有放假的感覺,但看到手機裡親友們一些祝福的話,還是蠻窩心的,希望明天轉職成功後再跟大夥一起烤肉、喝酒,也希望疫情趕快結束。
今天我們要做的題目跟編碼有關,話說很久很久以前,電腦剛起步的時代,ASCII 作為最早的編碼語言,主要顯示的語言僅限於英文字母,1986 年最後一次更新時共定義了 128 個字元,但人們很快就發現 128 個字元根本不夠用,而且對其他語言使用者根本不公平,於是又有了 EASCII 支援其他西歐國家語言。隨著電腦普及,萬國碼 Unicode 被制定了出來了,2021 年 9 月公布的最新版本,當中已經收錄超過 14 萬個字元,是現在全球最泛用的電腦編碼。(如果有講錯或遺漏還望讀者指正)
科普時間結束,讓我們直接看看今天的題目:
(題目來源為 Codewars)
Welcome.
In this kata you are required to, given a string, replace every letter with its position in the alphabet.
If anything in the text isn't a letter, ignore it and don't return it.
"a" = 1, "b" = 2, etc.
Example
alphabet_position("The sunset sets at twelve o' clock.")
Should return "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"
(as a string)
題目要我們把一段字串依照 "a" = 1, "b" = 2 ... 的規則解析(沒有分大寫小),並且忽略掉非字母的字元,最後回傳一段字串(如 example 那樣)。
以下為我的解答:
def alphabet_position(text)
text.downcase.bytes.map{ |char| char - 96 }.select{ |char| char >= 1 && char <= 26 }.join(' ')
end
首先,我們必須把整段字串轉為小寫,這裡是使用 downcase 方法。
再來就是重頭戲 bytes 方法,根據 Ruby官方文件所述,它會「returns an array of bytes in str」,那問題來了,什麼是 bytes?我們直接對題目的 example 用看看(別忘了先 downcase):
"The sunset sets at twelve o' clock.".downcase.bytes
# => [116, 104, 101, 32, 115, 117, 110, 115, 101, 116, 32, 115, 101, 116, 115, 32, 97, 116, 32, 116, 119, 101, 108, 118, 101, 32, 111, 39, 32, 99, 108, 111, 99, 107, 46]
很神奇地,我們得到了一推數字,那這些數字是哪來的?還記得稍早所提的 ASCII 嗎,讓我們查查 ASCII 的編碼表(維基百科),可以發現 a ~ z 字母的編碼為 97 ~ 122,再去比對output 每個元素對應的原字元位置,不難發現它們的一致性,也就是 "a" = 97, "b" = 98 ... "z" = 122。
然後,只要再對陣列中的每個元素進行運算,減去 96 讓 "a" = 1, "b" = 2 ... 就符合題目要的規則了。最後,只要篩掉(select 方法)其他字元的數字,再把陣列重新合成字串(join 方法),就大功告成了!
對比評分最高的解答:
def alphabet_position(text)
text.gsub(/[^a-z]/i, '').chars.map{ |c| c.downcase.ord - 96 }.join(' ')
end
它是先用 gsub 將英文字母檢索出來,再使用 chars 方法,依照官網所述,它會「returns an array of characters in str」,將字串打散成字母,並回傳一個陣列。值得一提的是,這邊的 ord 和 bytes 有點類似,但 ord 是回傳 integer ordinal,英文的話是沒什麼差,如果是其他語言的話結果會不相同。
今天的解題就到這啦,祝大家中秋節月圓人圓,明天上班活力滿點~掰