NOTICE

 任何跟文章無關的閒聊,請愛用 留言板(Guestbook)

 想要快速瀏覽主題,請點選單 目錄 標籤。

 停止更新ing,請見諒。 <(_ _)>


6月 21, 2008

【演算】河內塔 - Tower of Hanoi

@
  河內塔問題(Tower of Hanoi)是由法國數學家盧卡斯(Édouard Lucas)引進的數學謎題:在 3 根桿子中,有 1 桿上有 N 個從下數起由大而小的穿孔圓盤。在每次只能移動一個圓盤,且大盤不能疊在小盤之上的規則之下,你需要以最少的次數將這 N 個圓盤全部移到另一根桿子上。




  這個遊戲乍看起來有點複雜,其實解法相當簡單(為了方便起見,我們分別將三根桿子標記成 A, B, C,且都是將圓盤由 A 桿移向 C 桿)。

  假設現在 A 桿上有 1 個圓盤,則直接將之移到 C 桿上。若是有 A 桿上有兩個圓盤,則先將第 1 個(最小的)圓盤移到 B 桿上,再將 A 桿剩下的第 2 個圓盤移到 C 桿上,最後將剛剛移到 B 桿上的第 1 個圓盤移到 C 桿第 2 個圓盤之上即可。


  若是 3 個圓盤的情況呢?這時我們需要先忽略第 3 個圓盤,先把前 2 個圓盤以上述的方式移到 B 桿,再將第 3 個圓桿移到 C 桿之後,最後將 B 桿上的 2 個圓盤循同樣的方式移到 C 桿第 3 個圓盤之上即可。

  所以同樣的,若是 4 個圓盤,就將前 3 層以一樣的方式移到 B 桿,再將第 4 個圓盤移到 C 桿上,最後再把 B 桿上的圓盤全部移到 C 桿上。

  至於更多圓盤的情況,其實也都是運用這種規律解開。以下是 3 層與 4 層河內塔的最少移動解法圖例:






  而這種河內塔解法,其實就類似程式的遞迴(recursion)

  怎麼說呢?假設現在你需要將一個 N 層河內塔由 A 桿移到 C 桿。依照上面的解法,我們需要先將前 N - 1 層的圓盤先移到 B 桿,再將第 N 層的圓盤移到 C 桿,最後將 B 桿上的圓盤全部移到 C 桿。

  而要怎麼將前 N - 1 層的圓盤由 A 桿移到 B 桿呢?也是運用同樣的方式:將前 N - 2 層的圓盤先移到 A 桿,再將第 N 層的圓盤移到 B 桿,最後將 A 桿上的圓盤全部移到 B 桿。

  就這樣下去,直到變成最簡易的移動 1 層圓盤為止。也就是說,遞迴的終止條件為移動的圓盤數 n = 1。


  以下是解河內塔謎題的虛擬碼:

void Hanoi(Index n, char A, char B, char C)
{
    if (n = 1)
    {
        print "將第" n "個圓盤由" A "移到" C;
    }
    else
    {
        Hanoi(n - 1, A, C, B);
        print "將第" n "個圓盤由" A "移到" C;
        Hanoi(n - 1, B, A, C);
    }
}


  最後,附上 C 語言的程式實作:

#include <stdio.h>
#include <stdlib.h>

void hanoi(int, char, char, char);

int time = 0;

int main(void)
{
    int n;

    printf("請輸入河內塔的高度:");
    scanf("%d", &n);

    hanoi(n, 'A', 'B', 'C');

    printf("移動 %d 層河內塔共需移動 %d 次\n", n, time);

    system("pause");
}

void hanoi(int n, char A, char B, char C)
{
    if (n == 1)
    {
        printf("%d: 將第 %d 個圓盤由 %c 移到 %c\n", ++time, n, A, C);
    }
    else
    {
        hanoi(n - 1, A, C, B);
        printf("%d: 將第 %d 個圓盤由 %c 移到 %c\n", ++time, n, A, C);
        hanoi(n - 1, B, A, C);
    }
}


  小小的補充一下,假如用以上的程式去試看看,可以發現 N 層河內塔的最小移動次數恰好是 2n - 1。

6月 01, 2008

【轉貼】程設師遇到BUG的回應

@
程式為什麼不會動?程式設計師告訴你為什麼!


20. "That's weird..."
  這很奇怪喔。

19. "It's never done that before."
  以前從來不會這樣啊!

18. "It worked yesterday."
  昨天明明會動的啊!

17. "How is that possible?"
  怎麼可能!?

16. "It must be a hardware problem."
  這一定是硬體的問題。

15. "What did you type in wrong to get it to crash?"
  你到底是打了什麼才讓程式當掉的?

14. "There is something funky in your data."
  一定是你的資料有問題。

13. "I haven't touched that module in weeks!"
  我已經好幾個禮拜沒碰那一段程式了。

12. "You must have the wrong version."
  你一定是用到舊版了。

11. "It's just some unlucky coincidence."
  一定是巧合!為什麼這種壞運氣只讓你碰上。

10. "I can't test everything!"
  我不可能什麼功能都測試到吧,有 bug 是正常的!

 9. "THIS can't be the source of THAT."
  這個不可能是那個的原始碼!

 8. "It works, but it hasn't been tested."
  這程式應該是會動的,只是我寫好後還沒做測試。

 7. "Somebody must have changed my code."
  可惡!一定有人改了我的程式。

 6. "Did you check for a virus on your system?"
  你有檢查過你的電腦有沒有病毒嗎?

 5. "Even though it doesn't work, how does it feel?"
  儘管這功能還不能動啦,你覺得他如何?

 4. "You can't use that version on your system."
  在你的系統不能用那一個版本的程式啦!

 3. "Why do you want to do it that way?"
  你幹嘛要那樣操作,都是你的問題。

 2. "Where were you when the program blew up?"
  程式發生問題時你在哪裡?


 1. "It works on my machine."
  在我的機器明明就可以動啊!



原文:Top 20 replies by Programmers to Testers when their programs don't work
中譯:程式為什麼不會動?程式設計師告訴你為什麼!