2009年5月11日 星期一

以有涯逐無涯,殆矣。

近幾個月學習狀況不錯,學習效率好也能持久,但總覺得愈學愈多,愈學愈累,偶爾會有種茫然的挫折感。忽然想到莊子的這句:

吾生也有涯,而知也無涯。以有涯逐無涯,殆矣。

原本我曲解了這段話,還振奮了一下,想說要更認真地追求知識。忽然,我發現莊子的本意反而是點出恰到好處的生活方式,於是我的世界改變了。

體悟到這點後,我決定晚上十點後停止電腦科學相關的學習,改看看動畫、或翻翻閒書,或偶而像這樣寫寫 Blog 也不壞。待之後多存點錢,買了電鋼琴還可以來個「彈琴復長嘯」。不知為何,我覺得自己可以用更自在的方式追求更深的知識,讓生活過得趨於平衡。

忽然,又有兩年半前相似的體悟,到外邊小晃了一圈,我似乎走回正確的路了。即使不知道方向,不知道終點何在,我明白自己正踏在想走的路。

題外話,看到現在學習程式語言和機器學習的進展,不禁懷疑過去為何期望這麼久,卻遲遲沒有行動。才想起以前還有許多想做的事,像是增加電腦科學的廣度認知、寫 3D 遊戲、參加各式比賽、做研究寫論文等。許多事若沒有親身嘗試,只會念念不忘,難以打消念頭。經過前幾年的嘗試,才能像現在般沉澱心靈,專心在最有興趣的幾個點上。

2009年5月2日 星期六

空之軌跡

如果不全破的話,是不是故事就可以持續下去永不結束?玩完《空之軌跡》系列後,這樣的想法浮現在我腦裡。這是去年十一月、十二月的事了,愈是喜歡一個作品,愈難下筆。

FC

《空之軌跡》是 Falcom 公司出的系列作,分別為 《空之軌跡 FC》、《空之軌跡 SC》、《空之軌跡 The 3rd》。FC 和 SC 的劇情直接相連,當初全破 FC 後發現劇情急轉直下,嘴裡雖然碎碎唸罵著 Falcom 沒天良,還是立即買了 SC 回來玩。沒想到 SC 故事又比 FC 更龐大,算算兩部玩下來,花了我一百小時,這輩子從來沒這麼密集地玩同一作品。

SC

全破 SC 後,全身充斥著滿滿的感動,又一次地為自己無法以言語表達感動而感到無力,很想分享澎湃的情感,卻擠不出一個字來。就像做了一個很長很美好的夢一般,夢醒後又回到現實世界,接著是深沉的失落感。為了紓解這種失落感,只好上 ptt 看著大家的心得,放著《空之軌跡》的背景音樂,透過不同人從鍵盤下傳達過來的感動,暫時沉浸在《空之軌跡》的世界,直到心情恢復平靜。

只是,一聽到劇中音樂時,又會陷入短暫地感傷,懷念著約書亞、艾絲蒂爾等人。劇中主題曲的歌詞寫得很好,配合歌詞聽音樂,很自然地融入當時的情景。想說的話太多卻無法述諸文字,只好藉由音樂穿插帶出我片段的感受。

《銀の意志、金の翼》,這首當作早晨起床音樂挺不錯的,情緒會很 high。FC 尾聲出現這首時,立即提昇戰鬥氣氛至最高點。

《星の在り処》 (星之所在),FC 片尾曲。配合歌詞聽著,想到艾絲蒂爾當時的感受,眼眶情不自盡地溼了。 ( 含歌詞的版本見這裡,畫質音質較差。 )

《I Swear》,SC 片尾曲。SC 的結束,暗示著艾絲蒂爾等人的旅程暫時到一段落,今後她們也會繼續活躍著。整首歌充斥著希望,但想到故事到此完結,失落感也隨之來襲。

於是我忍不住買了 The 3rd,只為多看他們幾眼。劇情方面,The 3rd 穿插許多支線劇情,帶出各角色之後的發展,大大滿足玩完 SC 的失落感。不過主線劇情相較 FC + SC,遜色不少。在看完 The 3rd 的片尾,畫面上映出「Thank you for playing」的字樣時,我更想和制作小組道謝,謝謝他們做出這樣感人的作品。也不禁想著,那一天我才能參與這樣的大作,將我的感動傳出去呢?

最後,以 The 3rd 的片尾曲,《空を见上げて》,做為結尾吧,可惜只有音樂無畫面:

sora-no-kiseki-3rd-ed-image

再見了,《空之軌跡》,謝謝你帶給我這段美好的日子。期許著有那麼一天,我也能將你傳達給我的感動,透過我的雙手,制作出足以感動他人的作品。

2009年5月1日 星期五

Python 排序的技巧

用 Python 排序時相較於 C、Java 多了效率議題。由於 Python 內建函數 (built-in function) 是用 C 實作的,排序時盡可能用內建函數效率會快上不少,詳細的數據比較可以參見 Python Cookbook,這篇做個簡單的整理。

背景知識

本篇需要 list comprehensionmap 的基本觀念,若不清楚的話可以先了解它們再往下看。

排序 list 和 dict

先來看程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
d = { 'a': 2, 'b': 1 }
# return keys ordered by key
print sorted(d)                                      # ['a', 'b']
# return values ordered by key
print map(d.get, sorted(d))                          # [2, 1]
# return keys ordered by value
print sorted(d, key=d.get)                           # ['b', 'a']
# return values ordered by value
print sorted(d.values())                             # [1, 2]
# return (key, value) pairs order by key
print sorted(d.items())                              # [('a', 2), ('b', 1)]
# return (key, value) pairs order by value
print sorted(d.items(), key=operator.itemgetter(1))  # [('b', 1), ('a', 2)]

上面的程式列出所有排序 dict ( 在一些語言裡稱為 hash table) 的方法,這裡用到幾個技巧,分別說明一下。

return values ordered by key:Python 的 method call 其實和 function call 差不多,obj.func(x) 相當於傳回 func(obj, x),所以 d.get 一樣可以傳進 map 裡,結果是會取回 d 的 value。關於 function 和 method 的說明,可以參考《理解 python 的 method 和 function 兼谈 descriptor 》

return keys ordered by value:同上的技巧,注意參數 key 有做最佳化處理,使得 d 的每個元素只會呼叫一次 d.get ( 而不是比較次數 O(N*logN) 次 ),不用擔心取 key 的函式會被重覆執行。

return (key, value) pairs order by value:這部份的 code 和排序 list 一樣,關鍵在於用了 operator.itemgetter,它的文件說明摘錄如下:

Return a callable object that fetches the given item(s) from its operand.
After, f=itemgetter(2), the call f(r) returns r[2].

以程式碼來表示的話,類似於這麼寫:

1
2
def itemgetter(n):
    return lambda r: r[n]

只要資料轉成 list of lists 的形式,就可以用 operator.itemgetter 處理。轉成 list of lists 的時間和資料數量成正比,相對於套入用 python 寫的 comparator 來說,快上不少。module operator 裡有許多好用的函式,在套用 map、max、sort 等內建函式時,可以配合使用,一來不用自己重寫小函式,二來內建函式用 C 實作,速度快上許多。

Decorate-Sort-Undecorate (DSU)

若要比較的方式比較複雜,像是希望有 stable sort,或是比較的 key 不只一個,可以套用 DSU 的解法。這裡以 stable sort 為例 (程式引用自 Python Cookbook):

1
2
3
4
def stable_sorted_copy(alist, _indices=xrange(sys.maxint)):
    decorated = zip(alist, _indices)
    decorated.sort()
    return [ item for item, index in decorated ]

DSU 的關鍵在於先把每筆資料轉成 [key1, key2, ..., original item] 的形式,如此一來內建的 sort 就會依 key1, key2, … 的順序排序,排好後再取回 original item。同樣的,排序 object 依欄位值或 method 傳回值,都可以套用 DSU。而 stable sort 的情況比較不同,是將資料轉成 [original item, original position ],排序後再取回 original item。

附帶一提,xrange 是 generator,使用 generator 好處可以參見 PEP 289: Generator Expressions

參考資料

備註

發表這篇後,才發現去年的今天我在寫 Ruby。物換星移,忽然有淡淡的懷舊感傷。