漫談程式設計與競賽

兒子回來短短兩周很快的就又回到美國實習了, 兩周裡, 健康檢查, 看牙, 看眼睛, 回阿嬤家, 回外婆家, 拜訪老師朋友外, 還兼忙著積欠的期末考和批改作業, 剩下的空檔不多, 我們聊到一些他在大學裡的生活, 當然也聊到他最近參加的ACM-ICPC的心得。 兒子一向話不多, 難得可以聊到他有興趣的話題, 讓他侃侃而談, 於是我很自然地, 想把它記錄下來。以下的紀錄是我問他答的內容摘要, 完全是根據兒子個人的經驗, 和我這個外行人自己猜想演繹出來的說法, 如有偏頗請多包涵。 本來想寫成一篇較正式的訪談記錄, 但當媽媽的實在有很多地方聽不懂, 只好一直請他打比方, 所以有一些奇怪的對話出現, 大家不妨一笑置之。

 

請問學習程式設計就是學習電腦語言嗎?

應該說學習程式設計大於學習電腦語言,
語言是一種工具, 學會使用工具後是否能巧妙的運用會因為個人不同的經驗, 手法, 技巧和 習慣等許多因素, 而呈現出不同的結果。電腦語言是因為程式設計的需要而被開發出來的。一個電腦語言從剛開發出來到成熟廣為大家使用, 常常是歷經數年甚至是數十年的演變, 由多人貢獻而集大成的結果。我們學習程式設計, 如果有一個較大氣的高度就比較能理解電腦語言的語法設計邏輯, 同時也較能看出問題所在, 精準地設計出合用的程式。

 

那麼你覺得學習程式設計要從哪一種語言入門較恰當呢?

初學者可找一個適合自己的程式語言, 比較高階的。

 

什麼是高階低階?

高階語言提供的架構比較多, 他將電腦許多計算和細節包裝起來, 使用者比較可以輕易做出複雜的東西, 例如 Python, 但相對地它的速度就比較慢。

 

那麼請問你會用哪幾種程式語言? 精熟哪幾種程式語言?

會用的語言有C++, Java, JavaScript, Perl
比較擅長使用的是Haskell, Python, Scala

 

請問你最喜歡使用的語言是那種語言?

是Haskell, 因為它比較優雅, 不容易出錯, 比較函數導向, 適合用來解數學問題。

 

又不是在形容女孩子, 優雅?? 函數導向聽不太懂欸, 可以舉例它應用在什麼地方嗎?

最有名的其中之一就是 FaceBook 的 anti spam 系統, 用的就是 Haskell。

 

但是, 好像如果想參加競賽, 就必須學 C++ 是嗎?

是的, 因為它的速度比較快。而且有很多競賽系統只支援C++。
(兒子曾參加過的競賽和其性質最後面有整理介紹)

 

所以想要參加競賽需要很會用C++嗎?

算是, 不過競賽考的經常是演算法, 學習演算法其實更重要。

 

演算法又是什麼? 演算法要怎麼學呢?

演算法是數學的一個分支。我們學演算法的方法就是多看書, 多做題目練習。

 

演算法長得像什麼樣子? 像是數學理論或公式嗎?

不是公式, 你可以說他長得比較像菜譜, 一個步驟一個步驟的教你達到某一個目的。

 

菜圃? 你是說食譜吧? (你的中文退步了....)

哈, 對食譜, 做菜的食譜。

 

那會需要一一背起來嗎?

通常不用, 如果你了解原理的話, 就會明瞭為什麼要這麼做了。

 

所以我們在應用演算法時, 可以自己加油添醋, 減鹽少糖, 也可以把三杯雞改成三杯杏鮑菇?

可以這麼說, 當然改了配方會影響到一些電腦運算的細節, 譬如速度會改變, 或變得更適合某一部電腦, 或也有可能被調整成更適合多部電腦同時計算等等

 

媽媽聽到食譜這個妙喻就蠻高興的, 哈哈, 我好像更了解我兒子一點了。

關於演算法, 爸爸曾舉過一個簡單的例子, 例如你在一串排好順序的數字裡要找到某一個數字, 要怎麼開始呢? 有學過迴圈的人, 就會想說應該是要用迴圈, 從第一個位置裡的數字開始比對,直到找到一個和我們想要找的數字完全相等為止, 但是如果你會用二分法(常用演算法之一), 先比較他和中央數的大小, 然後再把搜尋範圍縮小到前半部或後半部, 依此方法再二分為某1/4的部分, 某1/8的部分等等, 就可以更有效率的去找到這個數字。 市面上, 網路上有很多演算法的書和網站, 收集前人智慧巧算的經驗, 多參考這些資料可以很快吸取高手演算的智慧精華, 最好再多花時間練習, 就會像多研究食譜的廚師一樣朝大廚的路邁進。

 

再回到C++, 除了競賽之外, C++還可以應用在什麼地方?

和Java, Python, JavaScript 一樣, C++也可以用來寫遊戲, 寫網頁, 不過因為它比較低階, 用C++來寫是很辛苦的, 大家通常是用其他語言, 例如用JavaScript 來設計可以和使用者互動的網頁, 用Java 來寫Android App, 用 Python 設計遊戲等等。不過, 所有以上的語言事實上都具備以上的兩種或多種的功能, 以上語言的應用的大致分類只可以說是大家公認的傾向而已。 而且這樣的分類也會因不同系統支援不同語言或者和每個人使用習慣及愛好, 而有所不同。 例如要寫 i-phone 的APP 就只好學 Objective-C 或他們自家的 Swift , 又例如如果你已經很會用 python 了, 也沒必要因為偶爾的需要而又花很多時間去學C++, Python 雖然較慢, 但應該還是夠用的。(不過大部分寫程式的人因為實際應用和系統轉換的需要, 其實都不知不覺地學了好幾種語言)

 

再來談談競賽, 競賽是可以鍛鍊或可以教得出來的嗎?

競賽雖然好玩, 但初學者如果只以競賽為目標來學寫程式, 並不太恰當。 競賽因為有時間限制, 參賽者必須在很短的時間內解出問題將答案送出, 是不太可能好好去寫出一個架構完整的程式的。 短時間內寫出來的程式通常只是呈現解答想法的一個草案而已。但是在程式設計裡, 好好的組織自己寫的程式, 讓它看起來脈絡清楚, 方便作者自己後來維護及修改以及便利開放給其他人使用等其實是更重要的課題。

而這些都需要時間慢慢去磨, 是沒辦法急就章完成。所以, 競賽的刺激畢竟只是一時的, 學寫程式時, 真正要念茲在茲的反而是寫出來的程式是否層次分明, 邏輯統一, 架構完整。

並且, 如果只是急功好利的為競賽而學習, 是不太可能得到好名次的。唯有紮紮實實的在想法上和架構上下功夫, 才能真正地寫出貼心好用的程式, 競賽就當成是認識同好, 偶爾為之的遊戲和聚會就好。平常該多練習的反而應該是這些基本功, 而不是速成花招。抱著這樣的心理去參加競賽, 反而比較能拿到較好的名次。

話又說回來, 競賽還是值得參加的, 可以藉著參加共同活動和同好切磋討論, 也在此見識到真正寫程式的高手快手, 每次競賽不論名次都是趣味的。如果你喜歡程式設計, 喜歡花時間思考題目, 喜歡鍛鍊自己用程式解題, 那麼參加程式設計競賽就像是每天慢跑的人去參加馬拉松那樣自然。參賽的確是有一些技巧是要注意的, 但每天的鍛鍊還是得靠自己有興趣才比較能持久。

 

那麼你經常花很多時間鍛鍊解題嗎?

其實不多, 學校課業很重, 還有社團活動, 都占用很多時間。但我有參加SIPB社團, 曾經有一次把他們社辦裡播放音樂的 program 多加一些功能讓它更好用(perl)。 我也會更改自己的電腦上處理資料的方式, 偶爾解一些數學題目, 也寫過一些小遊戲 (java script, python), 也會用程式畫謎題 (scala) 註, 括號裡是他應用的程式

 

我有觀察到你們參加NPSC和ICPC時雖然沒有網路可以搜尋, 但是你們可以帶一些書面筆記入場, 可以請問你們帶了哪些東西嗎?

我們帶一些用途較廣但比較複雜的演算法筆記。就是那些可能用的上, 但比較長, 一時寫不完全的演算法。

 

啊, 就好像是帶一些比較難做的菜的食譜去比賽一樣, 我懂了。我記得你們隊的三個成員好像都才大一大二, 可以說說看你們三人是如何認識的, 怎麼會想到湊成一隊呢?

2014 IOI 競賽在台灣舉行, S和A兩人都有來參加, 那時我們就知道彼此了。後來三人都進了MIT, 剛進去那一學期MIT有一個選拔的初賽, 我們三人都去了, 在那裏又重逢就很自然而然的湊成一隊了。

 

比賽時你們三人之間是如何分工合作的呢?

A 最會寫程式, 打字最快, 所以他掌鍵盤。S演算法很厲害, 我們三個人總是一起討論, 然後告訴A想法, 由他寫出來。像這次比賽他寫了7題。我也寫了兩題, 那兩題我講不太出來就只好自己下去寫, 我沒A會寫, 有一些 bug 找好久才找到。但幸好前七題我們寫得很快, 所以我們在時間上贏了其他隊伍, 拿到第六名。

 

今年的比賽差一點點拿到金牌, 會不會覺得有點可惜, 想要明年再來呢?

關於這一點, 我們三個人已經討論過了, S想到國外交換學生一年, A可能會繼續在社團裡擔任幹部, 我則想花一些時間思考一下未來想讀或做研究的方向, 也想再多參加一些其他社團。 大學裡有很多其他更有趣的事可以做, 所以應該不會再參加 ICPC 了。

 

啊, 這個答案有點讓人意外, 我還以為你玩得很高興, 明年想再去玩呢。 不過看到你們對未來充滿了計畫和憧憬, 媽媽很感動也很高興。祝福你們! 媽媽給你帶點鳳梨酥去給他們吃好嗎?

(媽媽實在有點無厘頭, 但是媽媽就只是想著孩子吃飽穿暖比較重要嚜。祝福你, 兒子!)

 

網路上的程式設計競賽網站有

Codeforces
often has weekly 2-hour contests, 多種語言

Topcoder
has 75-minute contests, but I don’t use it much nowadays, the arena is a little annoying
they both have two divisions of different difficulties with easy to hard problems

Google Code jam
多種語言 yearly

Facebook hacker cup
多種語言 yearly

IPSC
多種語言 (每年六月) 益智趣味性(但很多高手都會參加)

台灣目前的程式設計競賽活動有

國中, NPCS
高中, NPCS, IOI, HP Code War, 青年程式設計競賽
大學, ACM ICPC,