剛剛洗澡的時候,忽然領悟了寫寫讀書心得的意義。
以前我是不太喜歡寫東西的,尤其是讀書心得這種東西嘛,大概就是在書上畫畫線吧,也可能是因為沒看過什麼大作,即使看完就忘了,也沒什麼大不了的。
但是後來不知不覺衍伸出一種使命,就是我是不是應該留點什麼下來,尤其當找工作後,爬了一些文,或看了一些有頭有臉的部落格,間接驗證了我的這種想法。但我不是名人、不是理論學者、更沒有前衛者般的觀察眼,現階段的我確實找不到可以留下來的東西,佐證我活過的這段時間。
所以,寫心得,慢慢的演變成一種中心思想,一種紀錄、一種成長、一種在微黃燈光下獨自探索心靈與思考的過程,這是平靜的,緩慢的,也無從急躁起。
我也喜歡"累積"的感覺。累積會讓一個人變得有故事,有深度,而我熱愛這種深度所帶來的穩重感。但你不會把累積兩個字寫在臉上,而是裝在大腦裡,寫在筆記本裡,在飛躍的時代,就是寫在部落格裡。而累積的內容,會由當下自己決定的目標而定,但,無論如何,他就是一個使命,一個對自己交代的過程,這個累積的過程會變成自己生命的縮影,他可能會中斷,可能會移轉,但是當你寫下最新一頁文攢的時候,所有中斷過程的記憶又全都回來了。
我想 ‧ 這就是目前所領悟的 ‧ 心得
過去一週的網頁瀏覽次數
2012年6月6日 星期三
2012年4月9日 星期一
[心得] 華頓商學院最受歡迎的談判課
以上是我認為的談判,但是照字面這樣講應該多少都會覺得很勢利,什麼論點阿目的的,但其實放寬心想,就是在幫自己爭取權利,而最好的情況就是得到額外的報酬~!
一開始這本書跟我想得有點不同,我以為書中應該會講解關於人性解讀這種比較隱晦的層面,偏向心理學分析的論點,可是其實本書的主軸是放在與人交心,意思就是先表明來意並釋出善意,也就是說我不是來威脅利誘你的,我是想對等的跟你討論一些事情。
這本書中有個很大的重點就是"傾聽",作者舉了一大堆的例子,但是發現有很多過程都在傾聽,作者認為透過傾聽,能讓自己了解對方的觀點,不會錯估情勢,而且這個過程能將重點放在對方身上,對方會有被重視的感覺。我在幾年前開始感受這個情況,也覺得這是一個很好的起手勢,讓對方感覺和善和重視對方就是好的開始。
而其他地方則說了談判的一些重點,例如找對的人談,也就是能決定大局的人、直白的說出心裡感受,例如我認為我們在A議題上似乎無法取得共識,因為一百種人就有一百種觀點,直接點出要點會比無目的的轉圈圈好,當然這其中有些許的心理學意味~
這交涉的過程有點像是打太極的藝術吧~一開始緩慢的,但是能切重要點,不是威嚇對方,而是讓對方發自內心的願意給予優待。
當然我心中的疑惑就是,對,作者是歐美人士,大家都知道歐美的文化和東方的文化存在者極大差異,雖然作者希望提的是一個全世界都通用的方式,但是我認為歐美的文化影響還是太深,恐怕在閱讀上必須要對內容作適時的批判才行。
看完後是挺有收穫的啦~不過作者強調這種技術只看書是不行的,所以我還是在實戰中失敗了...想到上次去住旅館VOD不能看的事情,我完全沒有想到談判這件事,果然還是太嫩了...
我認為這本書是值得一讀再讀的,雖然其中沒有大量的心理學戰術,但是書中的醍醐味確實很值得回味和檢討,只看一遍是記不起來的。
2012年2月27日 星期一
[PTT轉錄] 關於OOP和檔案開啟
我對於OOP的概念一直不敢說懂,我想沒受過正規教育可能是原因之一。
今早在PTT上看到一篇討論檔案開啟在設計上的問題,原PO希望作一個class A專門用來處理開檔,再把讀到的檔案給其他物件或東東用。然而當檔案錯誤或無法被開啟時,原PO希望A有一個防範的機制,讓後續使用這個A來讀檔的物件不要去使用這個錯誤的結果。
因此這邊提到了一個OOP的概念:一個class作一件事,就把這件事作好。
物件架構是一層一層疊架的,當底層的物件沒有作好完整的工作時,上層的物件就會出現if... else等冗碼。在回文中某位大大舉了個例子:
A.DataTable = B.GetDataTable()
當B.GetDataTable在產生資料過程裏,有可能遇到error或空資料,很多人就會直接認為若是error,就丟null出來。結果A沒有看說明(b也沒寫),就直接接收,null reference錯誤。這是誰的錯?
文中大大的觀點認為,就算有error,B也要return一個空的table回去。然而最重要的,應該是如何讓之後的程式知道有錯誤發生??
較佳的作法應該是B在自己的class有錯誤時,throw new Exception("B已知的錯誤"),讓code在運行時有excpetion發生的機會,其他物件(包含A)在使用B的時後,自然就會知道B出錯。這是一個很重要的觀念,點破過去認為先return null,再用一堆if else判斷的寫法,有助於在OOP實戰,物件一層一層疊上去時,建立程式運作的穩定性。
因為不是每個人寫code都會去看前人有沒有寫註解阿...有時候自己寫的code年久失修,要回去翻修的時後可能也忘記當時的想法了XD
今早在PTT上看到一篇討論檔案開啟在設計上的問題,原PO希望作一個class A專門用來處理開檔,再把讀到的檔案給其他物件或東東用。然而當檔案錯誤或無法被開啟時,原PO希望A有一個防範的機制,讓後續使用這個A來讀檔的物件不要去使用這個錯誤的結果。
因此這邊提到了一個OOP的概念:一個class作一件事,就把這件事作好。
物件架構是一層一層疊架的,當底層的物件沒有作好完整的工作時,上層的物件就會出現if... else等冗碼。在回文中某位大大舉了個例子:
A.DataTable = B.GetDataTable()
當B.GetDataTable在產生資料過程裏,有可能遇到error或空資料,很多人就會直接認為若是error,就丟null出來。結果A沒有看說明(b也沒寫),就直接接收,null reference錯誤。這是誰的錯?
文中大大的觀點認為,就算有error,B也要return一個空的table回去。然而最重要的,應該是如何讓之後的程式知道有錯誤發生??
較佳的作法應該是B在自己的class有錯誤時,throw new Exception("B已知的錯誤"),讓code在運行時有excpetion發生的機會,其他物件(包含A)在使用B的時後,自然就會知道B出錯。這是一個很重要的觀念,點破過去認為先return null,再用一堆if else判斷的寫法,有助於在OOP實戰,物件一層一層疊上去時,建立程式運作的穩定性。
因為不是每個人寫code都會去看前人有沒有寫註解阿...有時候自己寫的code年久失修,要回去翻修的時後可能也忘記當時的想法了XD
2012年1月14日 星期六
openGL - 何時該用glPushMatrix() 和 glPopMatrix()
這問題困擾了我一陣子,有很大的因素是被這學期的圖學作業影響...
回到正提,這問題在"openGL編程指南"中說的有點隱晦(個人認為)。
這問題是發生在我使用了gluLookAt()函式後發現的,從書中範例我們可以感受一件事,glPushMatrix()和glPopMatrix()的目的是為了讓編程過程變得簡單且容易了解,但我似乎無法清楚定義"應該在何時加入這兩個函數會讓程式變得容易理解"。
首先要先認清一件事,openGL FAQ 8.010開宗明義即說明:在openGL中的攝影機,永遠都在原點(0,0,0)的位置,openGL為了假裝出移動攝影機的樣子,必須移動場景對整個世界場景做攝影機的逆空間轉換。(OpenGL FAQ and Troubleshooting Guide - Q8),而gluLookAt()函式,是個工具函式,意思就是它包裝了一些openGL的基本函式在內,並不是一個原生函式,套用上面說的話,表示gluLookAt()中使用了一些glTranslate()或glRotate()等類型的函式,所以如果程式中寫了一行gluLookAt(0,0,3,0,0,0,0,1,0),實際上是把所有的物體都先往-Z軸推離攝影機3的距離,才繼續之後的轉換。
那麼現在來想一個簡單的程式,我希望攝影機放在(0,0,3) 且朝著(0,0,-5)看著,而有一個球可以在(0,0,-4)的位置自轉,因此球和攝影機應該要相距7的距離,程式可能如下:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,3,0,0,-5,0,1,0);
glLoadIdentity();
glTranslatef(0,0,-4);
glRotatef(year,0,1,0);
glutSolidSphere(1,40,40);
老師說做任何事之前要先將當前矩陣(current matrix, CM)清空,確保轉換正確,所以第4行的glLoadIdentity()做了這件事。但是別忘記第3行的gluLookAt()先把東西都推離了3的距離,再把球更推離了4的距離,而這個glLoadIdentity()的存在,抹殺了gluLookAt()的目的,導致球只離攝影機4的距離,結果錯誤。
因此,你可以說:" 那我把glLoadIdentity()拿掉吧! ",會造成什麼結果? 結果就是每次球旋轉時,也相對的更遠了一點,結果還是錯。
從這邊可以發現,其實,我們並不是要一個會把CM完全清空的方法,也不是放任不管,而是我們需要一個手段可以"記錄CM的樣子",並且在事情做完後,CM可以回復到"之前記憶的樣子",而這就是glPushMatrix()和glPopMatrix()的功能!!
glPushMatrix()將當前矩陣push入一個stack,反之glPopMatrix()取出stack頂端的矩陣,因此我們就可以"記憶gluLookAt()後的CM長像",並且在所有轉換都做完之後,又再度回到"gluLookAt()後的CM長像",而且重點是這兩個函數是硬體實作且hard dependent,速度更快,因此可以用一句話形容:
glPushMatrix()是記住自己現在的位置,而glPopMatrix()是回到之前記住的位置!!
所以當你需要記住目前位置,且要再回到原位,而撰寫程式時不想要一直考慮CM有沒有跑掉的時後,就是使用這兩個函數的時機點了。
而stack的深度與硬體有關,可以用glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, *GLint *params)來查詢,或者到OpenGL capabilities report: GL_MAX_MODELVIEW_STACK_DEPTH查詢你的顯示卡/顯示晶片是否是常見的32深度。
回到正提,這問題在"openGL編程指南"中說的有點隱晦(個人認為)。
這問題是發生在我使用了gluLookAt()函式後發現的,從書中範例我們可以感受一件事,glPushMatrix()和glPopMatrix()的目的是為了讓編程過程變得簡單且容易了解,但我似乎無法清楚定義"應該在何時加入這兩個函數會讓程式變得容易理解"。
首先要先認清一件事,openGL FAQ 8.010開宗明義即說明:在openGL中的攝影機,永遠都在原點(0,0,0)的位置,openGL為了假裝出移動攝影機的樣子,必須移動場景對整個世界場景做攝影機的逆空間轉換。(OpenGL FAQ and Troubleshooting Guide - Q8),而gluLookAt()函式,是個工具函式,意思就是它包裝了一些openGL的基本函式在內,並不是一個原生函式,套用上面說的話,表示gluLookAt()中使用了一些glTranslate()或glRotate()等類型的函式,所以如果程式中寫了一行gluLookAt(0,0,3,0,0,0,0,1,0),實際上是把所有的物體都先往-Z軸推離攝影機3的距離,才繼續之後的轉換。
那麼現在來想一個簡單的程式,我希望攝影機放在(0,0,3) 且朝著(0,0,-5)看著,而有一個球可以在(0,0,-4)的位置自轉,因此球和攝影機應該要相距7的距離,程式可能如下:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,3,0,0,-5,0,1,0);
glLoadIdentity();
glTranslatef(0,0,-4);
glRotatef(year,0,1,0);
glutSolidSphere(1,40,40);
老師說做任何事之前要先將當前矩陣(current matrix, CM)清空,確保轉換正確,所以第4行的glLoadIdentity()做了這件事。但是別忘記第3行的gluLookAt()先把東西都推離了3的距離,再把球更推離了4的距離,而這個glLoadIdentity()的存在,抹殺了gluLookAt()的目的,導致球只離攝影機4的距離,結果錯誤。
因此,你可以說:" 那我把glLoadIdentity()拿掉吧! ",會造成什麼結果? 結果就是每次球旋轉時,也相對的更遠了一點,結果還是錯。
從這邊可以發現,其實,我們並不是要一個會把CM完全清空的方法,也不是放任不管,而是我們需要一個手段可以"記錄CM的樣子",並且在事情做完後,CM可以回復到"之前記憶的樣子",而這就是glPushMatrix()和glPopMatrix()的功能!!
glPushMatrix()將當前矩陣push入一個stack,反之glPopMatrix()取出stack頂端的矩陣,因此我們就可以"記憶gluLookAt()後的CM長像",並且在所有轉換都做完之後,又再度回到"gluLookAt()後的CM長像",而且重點是這兩個函數是硬體實作且hard dependent,速度更快,因此可以用一句話形容:
glPushMatrix()是記住自己現在的位置,而glPopMatrix()是回到之前記住的位置!!
所以當你需要記住目前位置,且要再回到原位,而撰寫程式時不想要一直考慮CM有沒有跑掉的時後,就是使用這兩個函數的時機點了。
而stack的深度與硬體有關,可以用glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, *GLint *params)來查詢,或者到OpenGL capabilities report: GL_MAX_MODELVIEW_STACK_DEPTH查詢你的顯示卡/顯示晶片是否是常見的32深度。
2012年1月12日 星期四
[心得] 盜墓筆記
話說我這個人其實很少看小說,我還記得上一本小說叫做"藍熊船長的奇幻大冒險",聽名子就覺得有點幼稚XD,那是我好幾年前看的小說了,而今天我要說的是這本很有名的盜墓筆記。
這一系列的小說是同學推薦的,不然我想我也不會特別去注意有沒有新小說。盜墓筆記源自網路小說,作者為"南派三叔",後來出成書,我個人認為前中段內容十分的精彩! 內容是講述盜墓者吳三邪的故事,七星魯王宮、血屍墓、雲頂天宮、張家古樓等等,太多太多的主題使整篇故事內容豐富,作者文筆也十分了得,在勾勒場景上非常生動,無論是激烈的逃命奔跑,還是一翻兩瞪眼的生死關卡,亦或是闡述似是非是的古史神化,都有種讓讀者身歷其境的臨場感,甚至講到可怕之處,你還會不時的回頭看看身後的陰暗處,是不是也有如同小說中的妖魔鬼怪XD。
此外這篇受人推崇的還有一個原因,就是文中所使用的專有名詞、術語,有許多都是真有其事,或是真有其人,曾有書評寫到:"除非你真的是盜過墓,否則豈能知曉這些古玩器具",不過作者到是一直否認啦~只說自己是個骨董商。我想故事之所以吸引人,就是讓讀者有那種真真假假,假假真真,彷彿故事是真的,但卻又讓你感到疑惑;而在你感到疑惑的瞬間,追求未知的欲望又席捲你的全身,讓你一頁一頁不停的翻下去,我不知道為了讀到最後,熬了多少夜阿(笑)。
這不是什麼勵志小說,我把它歸類為閒書。如圖所示,到雲頂天宮之前非常的精彩,作者有用不完的點子,扣不完的連環謎團,此外,最後的張家古樓也是非常的精彩,我覺得不要去探究小說中那些人物是否真偽,單純的享受三叔給你的不安與恐懼就好XD
但很可惜的我不得不說,結尾收的不好,有太多的連鎖迷團,作者後來都沒辦法釐清了,無法給讀者一個完整的交待,此外結局的鋪陳屬於悲劇英雄式的開放結局,由最佳男配角悶油瓶進入地底青銅巨門後畫下終點,個人認為這結局不具凝聚力,不是大眾所習慣的"長篇小說後應該會有個happy ending",留給讀者的是失落的主角以及文中所宣告的"10年",算是比較可惜的,不過...好歹這個網路連載前前後後也搞的5年!! 也真他X的久阿...
最後感想就是,這是一套可以讓你發洩平日壓力的優良小說XD
這一系列的小說是同學推薦的,不然我想我也不會特別去注意有沒有新小說。盜墓筆記源自網路小說,作者為"南派三叔",後來出成書,我個人認為前中段內容十分的精彩! 內容是講述盜墓者吳三邪的故事,七星魯王宮、血屍墓、雲頂天宮、張家古樓等等,太多太多的主題使整篇故事內容豐富,作者文筆也十分了得,在勾勒場景上非常生動,無論是激烈的逃命奔跑,還是一翻兩瞪眼的生死關卡,亦或是闡述似是非是的古史神化,都有種讓讀者身歷其境的臨場感,甚至講到可怕之處,你還會不時的回頭看看身後的陰暗處,是不是也有如同小說中的妖魔鬼怪XD。
此外這篇受人推崇的還有一個原因,就是文中所使用的專有名詞、術語,有許多都是真有其事,或是真有其人,曾有書評寫到:"除非你真的是盜過墓,否則豈能知曉這些古玩器具",不過作者到是一直否認啦~只說自己是個骨董商。我想故事之所以吸引人,就是讓讀者有那種真真假假,假假真真,彷彿故事是真的,但卻又讓你感到疑惑;而在你感到疑惑的瞬間,追求未知的欲望又席捲你的全身,讓你一頁一頁不停的翻下去,我不知道為了讀到最後,熬了多少夜阿(笑)。
這不是什麼勵志小說,我把它歸類為閒書。如圖所示,到雲頂天宮之前非常的精彩,作者有用不完的點子,扣不完的連環謎團,此外,最後的張家古樓也是非常的精彩,我覺得不要去探究小說中那些人物是否真偽,單純的享受三叔給你的不安與恐懼就好XD
但很可惜的我不得不說,結尾收的不好,有太多的連鎖迷團,作者後來都沒辦法釐清了,無法給讀者一個完整的交待,此外結局的鋪陳屬於悲劇英雄式的開放結局,由最佳男配角悶油瓶進入地底青銅巨門後畫下終點,個人認為這結局不具凝聚力,不是大眾所習慣的"長篇小說後應該會有個happy ending",留給讀者的是失落的主角以及文中所宣告的"10年",算是比較可惜的,不過...好歹這個網路連載前前後後也搞的5年!! 也真他X的久阿...
最後感想就是,這是一套可以讓你發洩平日壓力的優良小說XD
2012年1月9日 星期一
ALGO-maxnum sum of sub matrix/sub array
題目:
for(i=0~n-1)
演算法:
Given an n by n two-dimensional array arr (1 < = n < = 100) of arbitrary integers, find the maximum sub-array. Maximum sub-array is defined to be the sub-array whose sum of integer elements are the maximum possible.
想法:
以暴力法思考:
int sum=0;
for(i=0~n-1)
for(j =0~n-1)
for(p =0~n-1)
for(q =0~n-1)
for(s=i~p)
for(t=j~q)
sum = sum+M[s][t];
若是窮舉n*n中所有的子矩陣和,時間複雜度是O(n^6)。
但這是一個DP approach題目(對不起...我不知道什麼是DP approach...)。
假設給予一個n*n矩陣M,element值可正可負,則我創建另一n*n矩陣S,其中S[i][j]值為M[0][0]~M[i][j]所有元素的和:S[i][j] = M[i][j]+S[i-1][j]+S[i][j-1]-S[i-1][j-1],若i-1<0或j-1<0則該項忽略,初始值S[0][0]=M[0][0]。
for(i=0~n-1)
for(j =0~n-1)
S[i][j] = M[i][j]+S[i-1][j]+S[i][j-1]-S[i-1][j-1];
for(i=0~n-1)
for(j =0~n-1)
for(p =0~n-1)
for(q =0~n-1)
sum = S[p][q]-S[p][j-1]-S[i-1][q]+S[i-1][j-1];
複雜度:
1.建立S矩陣 : O(n^2)
2.DP計算最大子矩陣和 : O(n^4)
----------------------------------------
+ = O(n^4)
類似問題:最大/最小子矩陣和
UVa108
2011年12月13日 星期二
熊熊想到 - 10進為轉N進位
N可以為任意數,EX 8, 16, 15...等等
我們在將一個十進位的數P轉換成2進位時,通常會用除法和餘數組合
令一個int Quotient = P/2
在令一個int Remainder = P%2
Remainder 是我們要個別的結果,我們可以用一個東西把它裝起來
EX : char sum[i] = Remainder ;
而P = P/2 後,進行下一輪計算
依此類推,一直做到 Quotient <=0 在表示上我們用一個容器把它裝起來,陣列是最簡單的。因為列印時會從左而右,所以不失一般性我們從陣列的最後面開始存資料,這樣一來從頭列印的時後就可以顯示成一般人都能讀取的結果。 把這種想法轉成code: int end[SIZE]={0}; void tenToN(int a, int base) { int c=SIZE-1; int Remainder; //簡化code,Quotient省略 while(a > 0)
{
Remainder = a % base;
a = a / base;
end[c--] = Remainder;
}
}
但這code會遇到一個問題,如果要計算某個數的16進位表示法,結果可能有ABCDEFG...,int陣列就不能使用
陣列內容也不能單純的取Remainder的餘數,要轉換一下。
char end[SIZE]={0};
void tenToN(int a, int base)
{
int c=SIZE-1;
int Remainder; //簡化code,Quotient省略
while(a > 0)
{
Remainder = a % base;
a = a / base;
if(Remainder >= 10)
Remainder = (Remainder-10)+65; //'A' = 65
else
Remainder = Remainder+48; //'0' = 48
end[c--] = Remainder;
}
}
我們在將一個十進位的數P轉換成2進位時,通常會用除法和餘數組合
令一個int Quotient = P/2
在令一個int Remainder = P%2
Remainder 是我們要個別的結果,我們可以用一個東西把它裝起來
EX : char sum[i] = Remainder ;
而P = P/2 後,進行下一輪計算
依此類推,一直做到 Quotient <=0 在表示上我們用一個容器把它裝起來,陣列是最簡單的。因為列印時會從左而右,所以不失一般性我們從陣列的最後面開始存資料,這樣一來從頭列印的時後就可以顯示成一般人都能讀取的結果。 把這種想法轉成code: int end[SIZE]={0}; void tenToN(int a, int base) { int c=SIZE-1; int Remainder; //簡化code,Quotient省略 while(a > 0)
{
Remainder = a % base;
a = a / base;
end[c--] = Remainder;
}
}
但這code會遇到一個問題,如果要計算某個數的16進位表示法,結果可能有ABCDEFG...,int陣列就不能使用
陣列內容也不能單純的取Remainder的餘數,要轉換一下。
char end[SIZE]={0};
void tenToN(int a, int base)
{
int c=SIZE-1;
int Remainder; //簡化code,Quotient省略
while(a > 0)
{
Remainder = a % base;
a = a / base;
if(Remainder >= 10)
Remainder = (Remainder-10)+65; //'A' = 65
else
Remainder = Remainder+48; //'0' = 48
end[c--] = Remainder;
}
}
訂閱:
文章 (Atom)