EngTW / English-for-Programmers

《程式英文》:用英文提昇程式可讀性
971 stars 45 forks source link

1431. Kids With the Greatest Number of Candies #71

Closed twy30 closed 3 years ago

twy30 commented 3 years ago

https://leetcode.com/problems/kids-with-the-greatest-number-of-candies/

using System.Collections.Generic;
using System.Linq;

public class Solution
{
    public IList<bool> KidsWithCandies(int[] candies, int extraCandies)
    {
        // 「糖果的數量」(複數)
        var candyCounts = candies;

        // 「『額外的糖果』的數量」
        var extraCandyCount = extraCandies;

        // 「最大的『糖果的數量』」
        var maxCandyCount = candyCounts.Max();

        return candyCounts
        .Select(candyCount => candyCount + extraCandyCount >= maxCandyCount)
        .ToArray();
    }
}

請參考「刷 LeetCode 練習命名」 https://github.com/EngTW/English-for-Programmers/issues/69 😊

LPenny-github commented 3 years ago

這樣說有點丟臉,但 大大,我看不懂題目 orz

twy30 commented 3 years ago

@LPenny-github

這樣說有點丟臉,但 大大,我看不懂題目 orz

每個人學語言都是從零開始學起的 😊


題目原文:

Given the array candies and the integer extraCandies, where candies[i] represents the number of candies that the ith kid has.

For each kid check if there is a way to distribute extraCandies among the kids such that he or she can have the greatest number of candies among them. Notice that multiple kids can have the greatest number of candies.

拆解如下:

解讀如下:


以題目中的範例一(Example 1)為例。

Input: candies = [2,3,5,1,3], extraCandies = 3
Output: [true,true,true,false,true] 

答案是 true, true, true, false, true ,因為:


如果還有疑問,歡迎提出 😊

LPenny-github commented 3 years ago

看完大大的答案,完全不知道自己在幹嘛 XDDDDDDD 而且,動作很慢到 issue 關閉才寫出來 orz 還是厚著臉皮請求關於命名的建議,十分感謝 orz (C#)

 public bool[] KidsWithCandies(int[] candyCount, int extraCandyCount)
        {
            //找出孩子們擁有糖果的最大數
            int maxNumberOfCandies = candyCount.Max();

            //把最大數 減去 多餘糖果數 為基數
            int basicNumber = maxNumberOfCandies - extraCandyCount;

            //預備放置結果的容器
            bool[] cankidHaveMaxNumberOfCandies =new bool[candyCount.Length];

            //若孩子擁有的糖果 >= 基數,則為 true,否則為 false
            for (int i = 0; i < candyCount.Length; ++i)
            {
                cankidHaveMaxNumberOfCandies[i] = candyCount[i] >= basicNumber? true:false; 
            }
            return cankidHaveMaxNumberOfCandies;
        }
twy30 commented 3 years ago

@LPenny-github

每個人都是從零開始學起的 😊


關於命名的建議

 public bool[] KidsWithCandies(int[] candyCount, int extraCandyCount)

因為 candyCountint[], 我會傾向於用複數 candyCounts

            //找出孩子們擁有糖果的最大數
            int maxNumberOfCandies = candyCount.Max();

這裡 maxNumberOfCandies 讀起來很好懂;熟悉美式英文的人應該能從 Of 判斷出這個變數名稱就只有一種讀法: (max (number of candies))

            //把最大數 減去 多餘糖果數 為基數
            int basicNumber = maxNumberOfCandies - extraCandyCount;

我對這個變數的理解是:「就算能拿到額外的糖果,最起碼要已經有這麼多的糖果,才能與已知的『最大的糖果數』打平」。

是故,或許可以這個命名這個變數: minRequiredNumberOfCandies

            //預備放置結果的容器
            bool[] cankidHaveMaxNumberOfCandies =new bool[candyCount.Length];

我會把 kid 改成 Kid ,其餘部分我覺得讀得懂。

LPenny-github commented 3 years ago

@twy30 非常感謝大大 orz

我還有額外兩個問題 😆:

  1. 照我的命名好像很多字都會超過 三個單字,還是說 介係詞 可以不算成 ?(異想天開 😅

    像是 :maxNumberOfCandiesOf 🤔

  2. 最後一句

    我會把 kid 改成 Kid

    指的是 把 cankidHaveMaxNumberOfCandies 改成 Kid ? 還是把 cankidHaveMaxNumberOfCandies 改成 cankidsHaveMaxNumberOfCandies 呢?

以上,謝謝大大 😉

twy30 commented 3 years ago

@LPenny-github 不客氣 😊


  1. 照我的命名好像很多字都會超過 三個單字,還是說 介係詞 可以不算成 ?(異想天開 😅 像是 :maxNumberOfCandiesOf 🤔

的確可以這麼說 🤔

經你這麼一說,我覺得更完整的說法是:

我會這麼想,

  1. 程式跑出來結果正確最重要
  2. 清楚表達程式碼的意圖(想要如何解決什麼樣的問題)次之
    • 用母語(中文)寫註解、或寫出來的英文不是最精簡都沒關係
    • 「清楚、完整、正確」的文件,還可以請它人來翻譯、訂正英文
    • 「不清楚、不完整、不正確」的文件,就只能通靈了 😅
  3. 基本功站穩後,繼續精進英文語法、程式語言語法
  1. 最後一句

    我會把 kid 改成 Kid

    指的是 把 cankidHaveMaxNumberOfCandies 改成 Kid ? 還是把 cankidHaveMaxNumberOfCandies 改成 cankidsHaveMaxNumberOfCandies 呢?

這裡的確是我沒說清楚 😅

也就是說

LPenny-github commented 3 years ago

@twy30

感謝大大明燈 orz 我還會繼續(以龜速 😅)寫下去的 😆

lddr99 commented 3 years ago

覺得這題目敘述很迂迴是正常的嗎?是因為題目目標是敘述情境,而不是考試?我自己將題目簡單理解成:將每個小孩的個人糖果數量加上額外的糖果數量,是否成為小孩中糖果數量最多的人(允許同排名),將結果以布林的形態放入 Array 中

# ruby
def kids_with_candies(kid_candy_nums, extra_candy_num)
    kid_candy_nums.map do |candy_num|
        (candy_num + extra_candy_num) >= kid_candy_nums.max
    end
end

幾個問題想請教

  1. each 或是 map 的方式遍歷數組時,已經知道外層變數代表的意思,裡面每個參數是否還需要完整的命名?(以這邊為例是 kid_candy_nums > candy_num
  2. 之前一直認為需要將變數所代表事務放在變數名稱最後方,以最大糖果數量為例,可能會取做 maxCandyNumber,因為變數內容代表為數字,所以將 Number 放在後方,如果是 Array 或是 Collection (List) 則會以複數結尾 kidCandies = List<Candy>,但其實像 maxNumberOfCandies 命名把表達的事物以 of 的方式提前,以大大的經驗來說更容易閱讀(沒有模糊空間)嗎?
twy30 commented 3 years ago

@lddr99

覺得這題目敘述很迂迴是正常的嗎?是因為題目目標是敘述情境,而不是考試?

我也覺得題目有點「刻意而為」 😅


each 或是 map 的方式遍歷數組時,已經知道外層變數代表的意思,裡面每個參數是否還需要完整的命名?(以這邊為例是 kid_candy_nums > candy_num

在這個特定的例子中,我會說「可以不用完整的命名」,因為我 覺得 這個 Ruby 方法與 map 結構「不難懂」。

如果用 num 甚至 n 來取代 candy_num (如下) ,我仍預期讀者能從「 n 被使用的方式」來解讀這段程式碼。

def kids_with_candies(kid_candy_nums, extra_candy_num)
    kid_candy_nums.map do |n|
        (n + extra_candy_num) >= kid_candy_nums.max
    end
end

這裡有個關鍵的考量點:「怎麼樣的程式碼才算是『不難懂』?」 🤔

我目前沒有很好的答案,但我從「知覺負載(cognitive load)」這個觀念得到了一些思考方向。

「知覺負載」是從「工作記憶資源」的角度來判斷一件事情的難度,以這個例子來說,

我沒有辦法量化以上的東西會佔用多少工作記憶資源,但我會 覺得 這是一般程式設計師的工作記憶可以處理的,所以我會說「這段程式碼不難懂」。

反過來說, 如果 這個 Ruby 方法是十來行,含有多個 map 結構,那麼,我就會選擇給予每個 enumerator 完整的命名,試圖減輕讀者的知覺負載。

twy30 commented 3 years ago

@lddr99

之前一直認為需要將變數所代表事務放在變數名稱最後方,以最大糖果數量為例,可能會取做 maxCandyNumber,因為變數內容代表為數字,所以將 Number 放在後方,如果是 Array 或是 Collection (List) 則會以複數結尾 kidCandies = List<Candy>,但其實像 maxNumberOfCandies 命名把表達的事物以 of 的方式提前,以大大的經驗來說更容易閱讀(沒有模糊空間)嗎?

在這個特定的例子中,我會覺得 maxCandyNumbermaxNumberOfCandies 好一點點,因為它短一點點;而 maxNumberOfCandies 並沒有比 maxCandyNumber 更清楚。


如果我們換個例子,例如,假設我們有一堆寶石,我們要分類計算這些寶石 (如下)

// C#
var gemCountByType = new Dictionary<GemType, int>();
var gemCountByColor = new Dictionary<GemColor, int>();
var gemCountBySize = new Dictionary<GemSize, int>();

這時候 gemCountByColor 就會比 gemColorCount 來得清楚。


或許可以這樣結論:每個人可以選擇適合自己的方向,例如:

lddr99 commented 3 years ago

@twy30 十分感謝花時間解答

我目前沒有很好的答案,但我從「知覺負載(cognitive load)」這個觀唸得到了一些思考方向。

「知覺負載」是從「工作記憶資源」的角度來判斷一件事情的難度,以這個例子來說, …

酷!第一次知道這個詞,一直覺得這件事情是開發時的盲點,常常因為當下查資料或是實作時間較長,進而提昇熟悉度、減少了當下自己的知覺負載,但隨著時間推移、熟悉度下降,下次看到就打回原型。

twy30 commented 3 years ago

@lddr99 不客氣 😊


當下查資料或是實作時間較長,進而提昇熟悉度、減少了當下自己的知覺負載

隨著時間推移、熟悉度下降,下次看到就打回原型。

是的,我主觀認為「命名這件事很難」的原因之一就是「腦中已經有某知識K的人很難想像如何去跟一個不存在的人解釋那知識K」。

也就是「腦中已經有某知識K的人」不知道「那現實中(尚)不存在的讀者已經知道什麼、不知道什麼、想知道什麼」 😅

就很難為腦中的知識K找到一個適當的形體。

twy30 commented 3 years ago

@lddr99

「知覺負載(cognitive load)」

酷!第一次知道這個詞

在這裡 https://github.com/EngTW/English-for-Programmers/blob/master/notes/2020-11-27-cognitive-load.md#%E7%9F%A5%E8%A6%BA%E8%B2%A0%E8%BC%89 有些「知覺負載」的補充資料,有興趣可以看看 😊


順便問一下,像這種

與之前的

比起來,有沒有覺得哪種比較實用?或著特別偏好哪種格式、討論的方向? 😊

lddr99 commented 3 years ago

@twy30 感謝回覆,不好意思沒有先爬過討論區 🙇‍♂️

第二種資訊文給參考答案的方式,我想對大部分人來說可能比較實用,對於英文不夠好的人來說,查很多資料可能不如多看看別人的命名方式,當然能知道原因是最好的。

格式的話,第二種在閱讀上會覺得比較零散一點,如果以選擇題解答的方式,不知道會不會比較清楚

可數生物這個段落為例(學生人數的變數命名):

1. studentCount        // ✔︎ 尤其適合為「用來計數的變數」命名
2. numberOfStudents    // ✔︎
3. amountOfStudents    // ✖︎ 用於不可數名詞
4. numberOfStudent     // ✖︎ numberOf + 生物(複數)
5. studentNumber       // ✖︎ 在語意上是「號碼」的意思,意思會變成學生號碼
6. countOfStudent      // ✖︎ 在語法上通常不會這樣寫

ref: Amount of, number of or quantity of?

在想說以 github 這樣擁有大量程式碼的平台,如果能夠做出變數命名版的 google trends (variable naming trends?),這樣就能很快的比較出大部分人的命名偏好,精準度夠高的話還能朝 linter 發展XXD


第一個論述文比較有趣的是還有很多討論可以延伸,我可能會把單一單字的縮寫(cnt, qty)跟特定名詞的縮寫(hp)分開討論,之前在 DDD 看過一個名詞是 Ubiquitous Language,針特定領域或是容易混淆的用字建立一份用語表,或許可以解決像 hp 用字上的歧異。

其他找到可以參考的文件:Acceptable Abbreviations and Acronyms (apple)General Naming Conventions (microsoft)

twy30 commented 3 years ago

@lddr99

第一個論述文比較有趣的是還有很多討論可以延伸

第二種資訊文給參考答案的方式,我想對大部分人來說可能比較實用

格式的話,第二種在閱讀上會覺得比較零散一點

感謝你詳細的回覆 (例子、引用資料) 😊

我試試重新整理一下這些資料,以「實用性」為主:


在想說以 github 這樣擁有大量程式碼的平台,如果能夠做出變數命名版的 google trends (variable naming trends?),這樣就能很快的比較出大部分人的命名偏好,精準度夠高的話還能朝 linter 發展

有看過這樣的工具: https://unbug.github.io/codelf/ ;輸入 (簡體) 中文,然後列出對應的英文變數名稱做為參考。

我自己有手動挑選幾個大型的專案 (例如 Chromium, Linux kernel, Visual Studio Code ) 來比較「相似字」的使用頻率 (例如 verify / validate ; connect / attach ) ;的確是個很有趣的方向 😊