關於Karel倍增beeper問題的討論

問題描述: 如下圖所示,Karel將從(1,1)出發尋找地圖中一處放置有若干beeper的位置,將該處beeper數量double並返回原點。


補充描述: Karel只能在到達某處後獲知該處有或者沒有beeper,無法獲知具體數量。Karel只能理解前進,轉向的命令。Karel在自己所在位置取出(如果有)beeper或者放下(如果有)beeper,一次只能操作一個beeper。
 該程序分爲三個部分,首先尋找beeper的放置位置,其次將該處的beeper數量增倍,最後返回原處
這裏重點討論第二部分。這裏的程序有兩種寫法:
code 1:
通常做法,利用堆棧的方式,在旁邊空白位置處堆放2倍的beeper,再放回原處,程序如下
  1. private void doubleBeepers() {
  2. //pick up beepers at the corner where they were put
  3. //double them at the place behind this corner
  4. while (beepersPresent()) {
  5. pickBeeper();
  6. turnAround();
  7. move();
  8. putBeeper();
  9. putBeeper();
  10. turnAround();
  11. move();
  12. }
  13. //Pick up all the beepers generated at the new place
  14. //return them back to their original place
  15. turnAround();
  16. move();
  17. turnAround();
  18. while (beepersPresent()) {
  19. pickBeeper();
  20. move();
  21. putBeeper();
  22. turnAround();
  23. move();
  24. turnAround();
  25. }
  26. }
code 2:利用遞歸的思想將問題解構,從而避免在其餘空白處堆棧。原問題可以描述爲取出一個beeper,將剩下的beeper加倍,再放入兩個beeper。那麼中間一個步驟又變爲與原問題一致的問題,也即將該處的beeper數量加倍。那麼設計一個方法(method),讓其反覆調用自身,直至最後一步只剩下一個beeper,取出後beeper不再存在,遞歸終止,繼而層層遞進依次兩兩放入beeper,從而實現了對於beeper數目的加倍。
代碼如下:
  1. private void recursionDoubleBeeper(){
  2. if (beepersPresent()) {
  3. pickBeeper();
  4. recursionDoubleBeeper();
  5. putBeeper();
  6. putBeeper();
  7. }
  8. }
討論: 顯然方法2要遠優於方法1,其過程更加凝練,更具思想性,但相應不是十分直觀。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章