零碎時間也能練習程式思維:軟體工程師的口語化思考訓練法

11 分鐘閱讀

這篇想展示的其實不是內容,而是一種 AI 的使用方式。
透過這種方式引導它建立一個對話循環,不斷的對你提出問題,不需要是程式問題,也可以是背英文單字、國中數學題、邏輯問題之類的。

來點刺激,動動我們成年人這越來越僵硬的大腦...🫠

這種一來一往的、需要頭腦的交談很適合 Claude!

你可以看見我第一句話忘了提示它我希望的回覆長度,好在後來有成功讓它修正。
事實上直接修改第一個提問也是一種好方法。

琳 avatar

我是一個軟體工程師,請你幫我進行思考訓練。我的需求是在無法實際寫程式的情況下 (例如通勤時間) 透過和你對話,運用零碎的時間進行學習。請你告訴我你可以怎麼進行,並且對我提出第一個範例問題

Claude avatar
Claude

這是個很好的想法!我可以扮演一個思考訓練的夥伴,透過不同類型的問題來幫助你鍛鍊程式設計思維。我們可以專注在以下幾個面向:

  1. 演算法設計與複雜度分析
  2. 系統設計與架構思考
  3. 程式碼優化與重構練習
  4. 除錯思維訓練
  5. 設計模式應用

我們可以從一個簡單的演算法問題開始:

假設你正在開發一個社群媒體應用程式的後端系統。用戶可以發布貼文,而且系統需要即時顯示「幾分鐘前發布」這樣的資訊。例如:

  • 1分鐘內發布顯示「剛剛」
  • 1小時內發布顯示「X分鐘前」
  • 24小時內發布顯示「X小時前」
  • 超過24小時顯示具體日期

請思考:

  1. 你會如何設計這個時間轉換的函式?
  2. 有什麼邊界條件需要考慮?
  3. 如何讓這個函式容易維護且易於擴展?

你可以用口語描述你的思考過程,不需要寫出實際程式碼。

琳 avatar

請你告訴我解答

Claude avatar
Claude

好的,讓我來分析這個問題的解決方案:

  1. 基本設計思路:
  • 輸入會是發文時間的時間戳(timestamp)
  • 需要和當前時間做比較計算差值
  • 根據時間差值分級顯示不同格式
  1. 實作策略: 首先建立一個時間區間的對照表,由小到大判斷:
60秒內 -> "剛剛"
60分鐘內 -> "X分鐘前"
24小時內 -> "X小時前"
超過24小時 -> 具體日期
  1. 需要考慮的邊界條件:
  • 處理負數時間差(未來時間)
  • 跨日期時間計算
  • 不同時區問題
  • 效能考量:如果要處理大量文章列表時的優化
  1. 易維護性與擴展性考量:
  • 使用常數定義時間閾值,方便未來調整
  • 支援多語言
  • 彈性的格式設定
  • 考慮快取機制
  1. 程式架構建議:
class TimeAgoFormatter {
  constructor(locale, timezone) {
    // 設定語言和時區
  }
  
  format(timestamp) {
    // 主要轉換邏輯
  }
  
  private getTimeDiff() {
    // 計算時間差
  }
}
  1. 效能優化方向:
  • 對於文章列表,可以批量處理時間轉換
  • 可以在Redis快取常用的時間格式
  • 前端可以處理秒級的即時更新

這樣的設計既能滿足基本需求,也為未來的功能擴展預留了彈性。你覺得這個設計方案合理嗎?或是你有什麼想補充的地方?

琳 avatar

這個問題太長了。我要運用真的很零碎的時間,請你調整思考訓練的步調

Claude avatar
Claude

抱歉我的解答太長了。讓我們改用更簡短的練習。

試試這個小問題: 給一個已排序的整數陣列 [2,4,6,8,10],如果要插入數字 5,應該插入在哪個位置,好讓陣列保持排序?

這類簡單但需要思考的問題很適合零碎時間。你可以花 1-2 分鐘思考,我們再討論解法。你想試試看嗎?

琳 avatar

和位於中間的數字比大小,直到找到位置

Claude avatar
Claude

對的方向! 讓我們更細緻地分析一下你的解法:

你說「和位於中間的數字比大小」,這聽起來像是二分搜尋法(Binary Search)的思維。在這個例子中:

  1. 和中間數字 6 比較,5 比較小
  2. 所以要插入在 6 的左邊,也就是位置 2 (如果從 0 開始數)

最後陣列會變成: [2,4,5,6,8,10]

你的解法時間複雜度是 O(log n),比單純從頭掃到尾 O(n) 更有效率!

要不要試試下一個問題?給你一個字串 "hello",如何判斷它是否是回文(palindrome)?你可以用 30 秒想想。

琳 avatar

解釋一下回文

Claude avatar
Claude

回文(palindrome)是指一個字串從前面讀和從後面讀都是一樣的。例如:

  • "mom" 是回文
  • "wow" 是回文
  • "racecar" 是回文
  • "hello" 不是回文

所以 "hello" 從前面讀是 "hello",從後面讀是 "olleh",因為不一樣所以不是回文。

現在你知道什麼是回文了,要試試看判斷一個字串是否是回文的方法嗎?

琳 avatar

將第一個字母和最後一個比較 若是相同,再比較第二個字母和倒數第二個字母

Claude avatar
Claude

完全正確!這就是檢查回文的經典方法:

  1. 第一個和最後一個比較
  2. 如果相同,往內縮一格繼續比
  3. 如果不同,就可以確定不是回文
  4. 直到比完所有字母或兩邊相遇

用這個方法: "hello" -> 'h' vs 'o' 不同 -> 不是回文 "wow" -> 'w' vs 'w' 相同 -> 'o' vs 'o' 相同 -> 是回文

來試試下一個小問題: 一個數字陣列 [1,2,2,3,3,3],如何快速找出陣列中出現最多次的數字?

琳 avatar

告訴我答案

Claude avatar
Claude

這個問題有幾個解法,我來說明最直觀的方式:

使用一個計數器(雜湊表/Hash Map)來記錄每個數字出現的次數:

  1. 掃描陣列一遍
  2. 每遇到一個數字,就在計數器中把該數字的計數+1
  3. 最後找出計數最大的數字

用 [1,2,2,3,3,3] 示範:

  • 1 出現 1 次
  • 2 出現 2 次
  • 3 出現 3 次

所以答案是 3(出現最多次)

來試下一題: 給你一個數字 235,如何判斷它是不是由小到大排列的數字?(即每個位數都比前一個大)

你要繼續嗎?

琳 avatar

使用餘數運算子%10,每次都能取出最後一個位數,然後逐個取出比較

Claude avatar
Claude

沒錯!你抓到重點了。使用 %10 和除法可以從右到左取出每個位數:

235 % 10 = 5 (個位) 235 / 10 = 23 23 % 10 = 3 (十位) 23 / 10 = 2 (百位)

然後比較:5 > 3 且 3 > 2,所以 235 確實是由小到大排列。

來個類似但稍微不同的問題: 給你一個數字 12321,如何判斷它是不是迴文數? (提示:可以用剛才學到的取位數技巧)

琳 avatar

告訴我答案

Claude avatar
Claude

使用 %10 和除法來解這個迴文數問題,步驟是:

  1. 從原始數字開始,每次用 %10 取出最後一位數
  2. 將取出的數字重新組合成一個新數字(相當於把原數字反轉)
  3. 最後比較原數字和反轉後的數字是否相同

以 12321 為例:

原數: 12321
取出 1 (12321 % 10),新數: 1
取出 2 (1232 % 10),新數: 12
取出 3 (123 % 10),新數: 123
取出 2 (12 % 10),新數: 1232
取出 1 (1 % 10),新數: 12321

比較 12321 == 12321,相同,所以是迴文數。

要不要試試這個問題: 陣列 [1,4,3,2,5] 中有一個數字不見了(1-5 應該都要有),如何找出消失的數字?

對了,這種簡單的程式遊戲讓我想到 A=B
這款遊戲很好玩,超推!