PageRank



轉移公告

計劃把 http://blog.hoamon.info/ 文章全部轉移至 http://www.hoamon.info/blog/ 這裡,而本 Blogger 站台的文章近 500 篇,我預計在 2014-12-31 前移轉完畢,完成後 http://blog.hoamon.info/ 將只作代轉服務,一律把舊連結如 http://blog.hoamon.info/index.html 轉成 http://www.hoamon.info/blog/index.html ,敬請舊雨新知互相走告。

新文章只發佈在 http://www.hoamon.info/blog/

何岳峰 敬上

2007年9月28日 星期五

陣列特殊排序需求

Example: 排序 '140.120.109.1', '140.1.109.2', '14.120.109.1', '120.140.109.2'…等 ip 格式的文字串。這種排序的結果應是將 ip 切成 4 個部份後再來排序的。

>>> a = [4,5,6,1,2,3]
>>> a.sort()
>>> print a
[1,2,3,4,5,6]

上面的例子告訴我們,每個 list 都會有 sort 方法,而它的功能就是把陣列中元素作排序。如果陣列中元素有字串、另一個陣列、其他物件等, sort 方法一樣都可以排序,只是你對一個混合型態的陣列作排序,不容易有實質意義。

而如果陣列中的元素是單型態的,但它們的資料格式長得有點複雜,像是 ip 位置,那麼該如何排序呢!

>>> def sort_by_ip(X, Y):
... x_list = X.split('.')
... y_list = Y.split('.')
... for (i, x) in enumerate(x_list):
... if int(x) > int(y_list[i]):
... return 1
... else:
... return -1
... return 0
...
>>> ip = ['1.1.1.1', '140.120.109.1', '140.1.109.2', '14.120.109.1', '120.140.109.2']
>>> ip.sort(sort_by_ip)
>>> print ip
['1.1.1.1', '14.120.109.1', '120.140.109.2', '140.1.109.2', '140.120.109.1']

我 們利用一個自定的 sort_by_ip 方法來客製化我們的排序需求。陣列的 sort 方法,在執行時,會依序將陣列中的元素以兩個兩個為單位丟給 sort_by_ip 方法來處理,由 sort_by_ip 方法回傳出這兩個元素的大小,如果是前者為大,回傳值為 1 ,如果是後者為大,就回傳 -1 ,相等則回傳 0 。

所以你也就不須煩惱 sort 方法是不是用 quicksort/bubble 演算法,只須考量兩個元素的大小是如何判定的。

當問題只縮小到判定兩者大小時,就十分簡單了,在 sort_by_ip 方法中,我們首先拿到兩個元素的值,然後以 split 方法將其斷成 4 個子元素,再來依序比較這 4 個子元素的大小即可。

再來談一個例子:[{'cost': 10, 'id': 3}, {'cost': 1, 'id': 13}, {'cost': 100, 'id': 33}, {'cost': 84, 'id': 4}]該如何排序,解答如下:

def sort_by_cost(X, Y):
if X['cost'] > Y['cost']: return 1
elif X['cost'] <>
else: return 0

2007年9月23日 星期日

基隆市立信二停車場

用心就是不一樣。

這次到北部遊玩,有幸來到信二停車場,發現到令人感動的管理方式:
  1. 入場以人工方式輸入車號後領卡進場
  2. 每樓層以不同顏色標記
  3. 出場以人工輸入車號判讀停放時間,並檢查是否符合車卡上車號
這麼作有如下幾個優點:
  1. 以顏色區別後,使用者多了一種方式來記住停放車子的樓層。
  2. 出場得符合車卡上的車號,這樣車子被竊的機率降低了。
  3. 出場以人工輸入車號來判讀停放時間,這樣出場時間可以少個幾秒鐘。
缺點有一個:得多花一個人力。

2007年9月21日 星期五

小(大)學生一定要有電腦及網路才可以畢業!

這陣子燦坤、家樂福、全國電子推了幾個廣告,訴求就是「威脅」、「利誘」、「柔性呼喚」要開學的學生或是學生家長,在學涯生活中一定得買台電腦,要不然學習會輸別人的。

這是商人的詭計,與情人節買花、普渡要旺旺的道理是一樣的。但在聽我說下去前,請你們先去看看一個高級知識份子的文章「不要學電腦,不要學英文」,以下三個網址的內容都一樣的:
http://home.pchome.com.tw/internet/intro33/new_page_8.htm
http://blog.yam.com/eyesfun/article/8155310
http://www.pczone.com.tw/vbb3/thread/21/71021/

看完了嗎?還沒,請記住,我的文章沒他好,如果你不看他的,卻繼續看我的,那代表你沒眼光。再給你 3 分鐘。

曾在南投縣北山國中上過一個學期的資訊課。學期開始,我就為同學們介紹什麼是資訊、什麼是電腦,電腦不等同資訊;資訊也不等同電腦,所以我們上課其實不是一直在用電腦的,我會上點數學、講些社會上應用電腦資訊的例子,像是快遞如何透過資訊系統協助送貨、 7-11 如何管理庫存…之類的。

而最重要的一點是,我出的作業,一定要在課堂上作完。

因為我知道不是每個小朋友家裡都有電腦及網路的。台灣雖然是開發中國家,雖然是資訊產品的最大出口國之一,但還是有人家裡不能買或不願買一台電腦,辦條網路線的。

家裡沒有電腦,我是一點都不覺得有什麼關係的,尤其對小朋友來說,電腦對他們一點都不重要。何必為了 1 個月花 3 小時作一個文書處理作業買台電腦回家呢!況且如果老師真的出了電腦作業,也真的要求小朋友帶回家作出來,那也沒有關係,至少對市區學生來說,我們多半都有圖書館,圖書館裡有電腦、網路可以使用,像是欣榮紀念圖書館中還有 Ubuntu 可以用呢!又或者學校的電腦教室也可以使用呀!要不然學費中的電腦使用費是繳心酸的嗎(但大部份的家長其實不知道電腦使用費有一部份是花在教師電腦及全校網路連線費)?

但以上所說,不代表現在學校老師了解這個現象

我的姪子、姪女目前就讀南光國小,就常遇到老師要他們回家打報告、找資料,打報告是沒問題啦!因為家裡有電腦,但找資料的話,卻因沒有網路,所以他們就會跟家裡大人說:「要到姑丈家,或是舅舅家用網路。」於是 3 分鐘找資料,剩下的時間玩網路遊戲。

所以當我聽到老師又出網路作業回家作的時候,心裡就不高興。對小朋友來說,在網路上找資料一點都不重要。重要的應該是教他們「如何利用資訊」。甚至我還覺得根本不要教所謂的文書處理軟體、影像處理軟體、網頁製作軟體等,這些東西對他們未來的益處不若「如何利用資訊」來得重要。

資訊有很多形式,紙本的、口述的、數位的、網路的…,資訊的儲存位置也有很多地方,其中對小朋友(其實對大朋友也是)最有幫助的是圖書館。但學校老師常常不教(或許是他們也不會運用圖書館),只(會)用 Google 找資料的人是愚蠢又懶惰的。

而事實上,許多國中小電腦老師也只會教小朋友文書處理軟體,於是國小教一遍,國中又教一遍,搞得小朋友認為電腦就是這樣子,除了網路遊戲外,其他都是一整個無聊。

如果可以,我希望電腦可以晚一點教。

拿我親身的實例來說:高四(1995)時,我爸就買了一台 Win95 的電腦,要拿來幹什麼,我不知道,但當我上大學時,它成了我寫作業的工具,利用它來打報告及玩 NHL 97 ,一直到研究所,我才踏入重灌電腦/程式設計的行列,我還記得高中工藝課看不懂老師寫的 basic 程式,只好看同學打三國志 3 的情景,但比起這些國高中就有在玩電腦的同學,現在與他們相比,在電腦科學/應用上並不輸他們呀。

如果可以,我真的希望電腦可以晚一點教,因為有太多更重要的東西要學了。

django's models 中殺了父物件時,預設也會殺了子物件

如果你宣告了兩個 model:

class Journal(models.Model):
publishdate = models.DateField()
price = models.IntegerField()

class Article(models.Model):
journal = models.ForeignKeyField(Journal)
content = models.TextField()

那麼當你使用

>>> j = Journal.objects.get(publishdate=datetime.date(2007, 10, 1))
>>> j.delete()

時,會一併把 2007/10/1 出版的期刊內所有的文章紀錄一併刪除。

OpenSolaris 嚐鮮!

一直耳聞 Solaris 的效能不錯,現下 Sun 也把 Solaris Open 出來了,趁著這次 R51 的 OS 常 Hang up ,所以就拿 OpenSolaris 11 來重灌。大概花了三個小時。安裝約一個半,使用約一個小時。最後我的結論是 NB 不應該灌 OpenSolaris ,因為開機花了四分鐘,關機花了二分半,當然這不表示它的效能不好,而是它著眼的不是個人應用。

總結它的優點有:
  1. 嘸蝦米內建
  2. JDS 介面比 Gnome 好看
  3. 安裝不難(或許是我灌過太多 Linux 套件了)
  4. Java 相關應用完整
缺點就只有一個,它是伺服器導向的,不太適合個人應用,舉個例子來說:它不能安裝 Skype ,或許再等等吧! OpenSolaris 應該會朝著個人應用發展的。

注意!!如果你的硬碟已有 Linux 啟動磁區的話,那麼 Sun OS 的磁區是不能與它共存的。建議另外拿顆硬碟來玩吧!

下面是幾張桌面截圖:







2007年9月18日 星期二

動態規劃問題

一個大問題本身是由許多小問題所組成,且求解小問題的概念,也就是求解大問題的概念,像這種大問題就可以使用動態規劃來求解,而事實上,我倒覺得動態規劃求解觀念就是遞迴觀念。

假設有一發電廠欲規劃三年內符合總需求機組數的每年購買機組數以使購買總成本最低,如下圖:


我們可以依序購買 3,1,3 ,其成本為6+1+10=17,也可以任序購買 3,2,2 ,其成本為3+4+5=12,如此我們可知 3,2,2 的購買方式比較好。而最佳解該如何求得?以最簡單想法來看,就是把每年的選擇窮舉出來即可,以上題計,只要找出 4^3 種方式,比較那些方式符合總需求機組數且成本最低即可。

但窮舉法總有一天跑不完,如果你的問題是有二十種選擇,且要規劃二十年的話,電腦就沒這能耐跑出來了。

所以此題的作法是把大問題切成小問題,我們不用管三年後該怎麼買,而是永遠只考慮下一年要怎麼買。

從第一年開始,因為至少購買一組,所以我們留下三種購買方式 {1, 2, 3} ,到第二年時,我們把第一年的 1 組,去加上第二年的可購買組數 [0, 1, 2, 3] ,可得到 {1, 2, 3, 4} ;把第一年的 2 組,去加上 [0, 1, 2, 3] 可得到 {2, 3, 4, 5};
依此觀念可得
{1, 2, 3, 4}
{2, 3, 4, 5}
{3, 4, 5, 6}
等方式,這也就是下一年(也就是第二年)的可能購買方式組合。接下來,我們把下一年(也就是第二年)的總數量為 X 的組合找出來,然後留下成本最低的那一種,結果我們可知下一年(也就是第二年)會留下 3, 4, 5, 6 等四種總數量的購買方式:

在第二年的總購買量為 3 時: 1, 2(成本為2+4); 2, 1(成本為3+1); 3, 0(成本為6+0) => 應選 2,1 這一組。
在第二年的總購買量為 4 時: 1, 3(2+5); 2, 2(3+4); 3, 1(6+1) => 剛好都一樣,隨便選 1, 3 吧!
在第二年的總購買量為 5 時: 2, 3(3+5); 3, 2(6+4) => 2, 3
在第二年的總購買量為 6 時: 3, 3(6+5) => 3, 3

所以我們得到在第二年總購買量可為 {3, 4, 5, 6} 而它們的購買方式為 (2, 1), (1, 3), (2, 3), (3, 3) 等四種。

再接下一年,我們把 {3, 4, 5, 6} 再分別與第三年的 [0, 1, 2, 3] 來作組合得到:

在第三年的總購買量為 7 時: (1, 3), 3(成本為7+10); (2, 3), 2(成本為8+5); (3, 3), 1(成本為11+2) => 所以選擇 2, 3, 2,其總成本為 13 。
在第三年的總購買量為 8 時: (2, 3), 3(8+10); (3, 3), 2(11+5) => 3, 3, 2(16)
在第三年的總購買量為 9 時: (3, 3), 3(11+10) => 3, 3, 3(21)

由此,我們選擇 2, 3, 2 為我們的三年購買方式,其總成本為最低,只有 13 。

以上是例題的簡單說明。

我們會把發電廠的完整問題,以 Python 程式解出。程式說明如下:

解答的資料結構:

Res = {
27: {
'cost': 40 , 'list': [5, 1, 3, 10, 2, 0, 0, 6, 0, 0],
'costlist': [10, 1, 4, 15, 2, 0, 0, 8, 0, 0]
},
....
}

27 代表當年度的總機組數量, cost 值代表在每年購買量為 [5, 1, 3, 10, 2, 0, 0, 6, 0, 0] 時的總成本,
costlist 陣列則是每年購買成本。

成本矩陣:

Cost = [
[0 , 2 , 5 , 7 , 9 , 10 , 12 , 16 , 18 , 19 , 20], # 第一年在各種購買量下的成本。
[0 , 1 , 5 , 7 , 9 , 12 , 15 , 18 , 21 , 25 , 27], # 第二年在各種購買量下的成本。
[0 , 2 , 3 , 4 , 7 , 9 , 10 , 13 , 15 , 19 , 22],
[0 , 1 , 2 , 6 , 7 , 8 , 10 , 11 , 12 , 14 , 15],
[0 , 1 , 2 , 4 , 5 , 7 , 11 , 12 , 14 , 16 , 18],
[0 , 2 , 3 , 6 , 9 , 11 , 12 , 13 , 16 , 17 , 21],
[0 , 2 , 6 , 7 , 8 , 9 , 11 , 14 , 16 , 20 , 22],
[0 , 2 , 4 , 5 , 6 , 7 , 8 , 12 , 14 , 17 , 19],
[0 , 1 , 3 , 5 , 8 , 9 , 10 , 12 , 13 , 17 , 18],
[0 , 3 , 7 , 10 , 12 , 15 , 18 , 21 , 24 , 25 , 27],
]

需求矩陣:

Limit = [3 , 4 , 9 , 11 , 14 , 18 , 18 , 21 , 24 , 27]

運算流程:

主要概念是把前一年度的購買組合與本年度的購買組作交叉組合配對,
會得到本年度的購買組合,每一購買組合的形式如下:

27: {
'cost': 40 , 'list': [5, 1, 3, 10, 2, 0, 0, 6, 0, 0],
'costlist': [10, 1, 4, 15, 2, 0, 0, 8, 0, 0]
},

27 代表當年度的總機組數量, cost 值代表在每年購買量為
[5, 1, 3, 10, 2, 0, 0, 6, 0, 0] 時的總成本,
costlist 陣列則是每年購買成本。

跑完當年度的購買組合後,就把不滿足需求量機組數的購買組合刪除。

等 10 個年度跑完後,再利用 sort_by_cost
函式作排序,把最便宜的購買組合放到最前面。

延伸閱讀:

sort_by_cost 函式的原理:請參考
http://wiki.python.org/moin/HowTo/Sorting#head-10e70070894a1bdb7580127b5cf764a44a2d6d29

for k_i in [k for k in Res.keys() if k < Limit[i]]: del Res[k_i] 的語法等價於:

toDel_k = []
for k in Res.keys():
if k < Limit[i]: toDel_k.append(k)

for k in toDel_k:
del Res[k]


完整程式下載: http://www.hoamon.info/_d/dynamic_programming.py

讓 Trac 支援 Email on Change

當 Trac 系統上有人增加/修改了一篇 wiki 、 ticket ,它能直接以 email 的方式讓其他人知道。

方法是:只要在 trac.ini 中編輯以下選項即可。

smtp_enabled = true
smtp_server = localhost
smtp_from = dontreply@mailserver
smtp_replyto = dontreply@mailserver
smtp_always_cc = XXX@gmail.com, YYY@gmail.com
always_notify_owner = true # 任何改變也會寄給「被指派的人」
always_notify_reporter = true # 任何改變也會寄給「創ticket的人」
always_notify_updater = true # 寄給改變這個 ticket 狀態的人

smtp_server 是寄信伺服器,如果你是在 hinet 的網路之下,可使用 msa.hinet.net ,它不會擋你。smtp_from, smtp_replyto 不重要,因為你不期待有人針對通知信回信。而 smtp_always_cc 則是每封通知信一定要寄的對象。

修改後,再重啟 apache 即可。

另外當你使用 ticket 時,要讓多人知道這個 ticket ,請使用 Cc: 欄位,其值為收信地址,若多值請用逗號隔開。

2007年9月7日 星期五

VirtualBox 1.5 讓我太感動了


如何感動!還是看圖容易。請看!

IE 及 MSN 是活在 Ubuntu 當中的。

這樣我又都多了個好理由來鼓勵大家轉到 Linux 陣營了。

呀~~我都快哭了。

快上 http://www.virtualbox.org/了解實情。

python2.5真的與2.4有差

在 Ubuntu 上開發程式的環境是 2.5 ,但網頁伺服器是用 Fedora Core 5 ,所以它的版本還在 2.4 ,已經跑過無數個程式了,一直都是相容的,直到今天。

在 2.5 中,抓日期物件如下:

dateobj = datetime.datetime.strptime('2007-1-1', '%Y-%m-%d').date()

但在 2.4 中,卻不能這樣用,因為 datetime.datetime 並沒有 strptime 函式。那麼 strptime 函式在那裡呢!在 time 下。所以要改成如下的寫法:

dateobj = datetime.date(*time.strptime('2007-1-1', '%Y-%m-%d')[:3])

這樣在 2.4 及 2.5 下才能同時正確執行。

不過,我認為 2.5 改得好,因為我一直認為 time 物件是用來抓時間用的,而 datetime 是用作時間日期格式轉換用的, strptime 放在 datetime.datetime 下比較適合。

2007年9月5日 星期三

取消回復光碟的申請

以下是我寫給 Lenovo 客服的信。
>>>>>>>>>>>>>>>>>>>>>>>
客服人員:
您好,我於 8/24 申請回復光碟,但至今尚未收到。以下是我的資料。如果貴公司尚未寄出回復光碟,請取消我的申請,因為我已經放棄在 R51 上安裝 Windows XP 了,專心投入 Ubuntu 7.04 的懷抱。謝謝。

姓名:何X峰
身分證號碼或護照號碼:B1********
IBM機器序號(S/N):99CMDZ7
IBM機器型號(M/T):1829J6V
隨機版作業系統版本:Home Edition
客戶地址:545 投縣埔里鎮******
行動電話/室內電話:0911776XXX
電子郵件地址: hoamon@hoamon.info
回復光碟-最遲歸還日:2007-09-06

是否願意收到IBM相關訊息:no

---------- Forwarded message ----------
From: Mail Service <psginfo@tw.lenovo.com >
Date: Aug 24, 2007 8:05 PM
Subject: Lenovo Notice : 回復光碟申請成功 (本信件由系統寄送請勿直接回覆)
To: hoamon@hoamon.info

Lenovo 個人電腦服務部

----------------------------------------------------------

親愛的 Lenovo 用戶您好,

非常感謝您對 Lenovo 的支持

我們已經收到您的回復光碟申請表,並會盡快將光碟寄出.

如您仍然有任何疑問,請來信至pchelp@tw. ibm.com或是撥打0800000700免費專線,我們會盡力為您解答

非常感謝您的配合.

謝謝

Related Posts Plugin for WordPress, Blogger...