uva 10035 Primary Arithmetic
這個問題其實很簡單,就是把兩個小於十位的非負整數相加,求相加的過程總共進位幾次
例如
123 + 456,完全沒有進位到,因為3+6<10, 2+5<10, 1+4<10
123+127,進位一次,因為3+7=10, 2+2+1<10, 1+1<10
問題簡單歸簡單,但我遞交UVa online 第11次才Accepted,前面得到wrong answer 9次、compilation error 1次,debug的全部時間加起來大約有兩、三小時吧,坦白說真的有點挫敗和無奈
起初我以為是輸出格式錯誤,有的問題是一次給完所有input,計算完一次把所有答案印出來;有的則是一筆一筆給,output也就一筆一筆印;有的會要求用一個空白行區隔、有的不會
但我確認這次是一筆一筆給、然後一筆一筆印
所以應該是邏輯錯誤沒錯?系統判斷出錯的機率極低,我這樣假設
於是我就試著丟一些input進去看能不能找到問題出在哪,但看不出來...,丟進去的資料給的結果都正確
我又想是不是不滿足input格式?小於10位的unsigned integer,在大部分情況下,用long long是足夠的,int也可以
我google找了別人的程式碼,丟進系統結果accepted,然後看它運作時的輸入、輸出格式,跟我的一樣
實在受不了,我就看了別人的程式碼跟我的到底有什麼不同,嗯...,判斷的過程比我的簡潔明瞭許多,然後我注意到第24行while loop那個判斷要不要繼續做下去的條件,他是打||,我打&&,我恍然大悟!突然想到我的程式會跑出錯誤結果的例子
977+23,7+3=10, 7+2+1=10, 9+1=10,總共進位3次
但我的程式對這個例子的判斷結果會是2次!因為最後9+1這次沒判斷到,我以為當兩個整數不同位的時候,判斷到小的數字的位數就足夠了,以這個例子而言較小的數字是23,我以為判斷完兩位的相加就好了...
這次經驗,老實說一樣是犯了之前常犯的問題:演算法不夠清楚或確認其正確性之前就開始寫程式,這個問題確實夠簡單,解法大部分人想一下大概就差不多,然後開始寫,大部分情況可能第一次或前幾次就Accepted,但這次剛好我想岔了一些,結果就是debug地獄
我一直很納悶,寫程式解決問題,想一個問題的解法、演算法到底要詳盡到什麼程度才足夠?
理論上一個良好的解決流程是這樣:
→想好演算法
→有明確且正確的演算法後、再把演算法「翻譯」成程式碼
→檢驗「翻譯」是否正確...
我用「翻譯」形容根據演算法來撰寫程式碼的過程,因為一些經驗,我覺得那真的很像翻譯;而演算法的詳盡程度有時會影響「翻譯」的難易,有時候演算法當中視為理所當然的基本運算,程式語言未必提供,例如演算法用到stack、而你使用C語言,那stack結構和相關函數就要自己寫,諸如此類的狀況,問題可能就在那些沒處理好的細節中產生
回到Primary Arithmetic這個問題,我大概知道從兩數最右邊的digit開始加、加到較小數字的最左digit,用一些判斷式,就可以得到carry operation的次數,不過是國小的加法,完全沒難度,這就是解法了
最左digit?我寫出來的程式碼真的在較小數的最左digit與大數對應的digit相加之後,有統計到那次的進位嗎?老實說,在我看到別人的程式碼寫的||之前,我心裡完全沒想過這問題,我很理所當然的認為:「程式正確執行了我想的解法、而且我想的解法在最左digit的任何情況都是正確的。」這講起來也許有點玄吧,就是因為我心裡堅持、抱持著錯誤的認知,而這認知導致我對某些部分輕易放過、看不見問題,我從沒想過我的程式會在處理最左digit的時候出差錯,而跟最左digit的後續處理有關的就是第24行while loop的條件,仔細想想我debug的過程大部分都是看著while loop的內部...
123 + 456,完全沒有進位到,因為3+6<10, 2+5<10, 1+4<10
123+127,進位一次,因為3+7=10, 2+2+1<10, 1+1<10
問題簡單歸簡單,但我遞交UVa online 第11次才Accepted,前面得到wrong answer 9次、compilation error 1次,debug的全部時間加起來大約有兩、三小時吧,坦白說真的有點挫敗和無奈
起初我以為是輸出格式錯誤,有的問題是一次給完所有input,計算完一次把所有答案印出來;有的則是一筆一筆給,output也就一筆一筆印;有的會要求用一個空白行區隔、有的不會
但我確認這次是一筆一筆給、然後一筆一筆印
所以應該是邏輯錯誤沒錯?系統判斷出錯的機率極低,我這樣假設
於是我就試著丟一些input進去看能不能找到問題出在哪,但看不出來...,丟進去的資料給的結果都正確
我又想是不是不滿足input格式?小於10位的unsigned integer,在大部分情況下,用long long是足夠的,int也可以
我google找了別人的程式碼,丟進系統結果accepted,然後看它運作時的輸入、輸出格式,跟我的一樣
實在受不了,我就看了別人的程式碼跟我的到底有什麼不同,嗯...,判斷的過程比我的簡潔明瞭許多,然後我注意到第24行while loop那個判斷要不要繼續做下去的條件,他是打||,我打&&,我恍然大悟!突然想到我的程式會跑出錯誤結果的例子
977+23,7+3=10, 7+2+1=10, 9+1=10,總共進位3次
但我的程式對這個例子的判斷結果會是2次!因為最後9+1這次沒判斷到,我以為當兩個整數不同位的時候,判斷到小的數字的位數就足夠了,以這個例子而言較小的數字是23,我以為判斷完兩位的相加就好了...
這次經驗,老實說一樣是犯了之前常犯的問題:演算法不夠清楚或確認其正確性之前就開始寫程式,這個問題確實夠簡單,解法大部分人想一下大概就差不多,然後開始寫,大部分情況可能第一次或前幾次就Accepted,但這次剛好我想岔了一些,結果就是debug地獄
我一直很納悶,寫程式解決問題,想一個問題的解法、演算法到底要詳盡到什麼程度才足夠?
理論上一個良好的解決流程是這樣:
→想好演算法
→有明確且正確的演算法後、再把演算法「翻譯」成程式碼
→檢驗「翻譯」是否正確...
我用「翻譯」形容根據演算法來撰寫程式碼的過程,因為一些經驗,我覺得那真的很像翻譯;而演算法的詳盡程度有時會影響「翻譯」的難易,有時候演算法當中視為理所當然的基本運算,程式語言未必提供,例如演算法用到stack、而你使用C語言,那stack結構和相關函數就要自己寫,諸如此類的狀況,問題可能就在那些沒處理好的細節中產生
回到Primary Arithmetic這個問題,我大概知道從兩數最右邊的digit開始加、加到較小數字的最左digit,用一些判斷式,就可以得到carry operation的次數,不過是國小的加法,完全沒難度,這就是解法了
最左digit?我寫出來的程式碼真的在較小數的最左digit與大數對應的digit相加之後,有統計到那次的進位嗎?老實說,在我看到別人的程式碼寫的||之前,我心裡完全沒想過這問題,我很理所當然的認為:「程式正確執行了我想的解法、而且我想的解法在最左digit的任何情況都是正確的。」這講起來也許有點玄吧,就是因為我心裡堅持、抱持著錯誤的認知,而這認知導致我對某些部分輕易放過、看不見問題,我從沒想過我的程式會在處理最左digit的時候出差錯,而跟最左digit的後續處理有關的就是第24行while loop的條件,仔細想想我debug的過程大部分都是看著while loop的內部...
留言
張貼留言