Recursion 方案:河内塔楼(递归)

Recursion 方案:河内塔楼(递归),recursion,scheme,racket,towers-of-hanoi,Recursion,Scheme,Racket,Towers Of Hanoi,首先,我想说这是家庭作业;所以我不是在寻求解决方案,只是一些建议。我已经沉思了大约一个星期了。我提出的每一个解决方案都不是递归的,因为我无法将列表作为唯一的参数来递归。我的教授说他们可以用大约6个助手函数来完成 如前所述,我必须以列表作为唯一参数来解决这个问题。这是我最近一次尝试的一个例子 (define (sumSublists lst) (if (= (length lst) 0) 0 (+ (length (car lst)) (sumSublists (cdr

首先,我想说这是家庭作业;所以我不是在寻求解决方案,只是一些建议。我已经沉思了大约一个星期了。我提出的每一个解决方案都不是递归的,因为我无法将列表作为唯一的参数来递归。我的教授说他们可以用大约6个助手函数来完成

如前所述,我必须以列表作为唯一参数来解决这个问题。这是我最近一次尝试的一个例子

(define (sumSublists lst)
  (if (= (length lst) 0)
      0
      (+ (length (car lst)) (sumSublists (cdr lst)))
  )
)

(define (hanoi towersNum)
  (sub1 (sumSublists towersNum))

    (if (= (sumSublists towersNum) 1)
        (print towersNum)
        (begin (if (= (sumSublists towersNum) 1)
                   (print towersNum)
                   (hanoi '((car towersNum) (cddr towersNum) (cadr towersNum)))
               )
               (if (= (sub1 (sumSublists towersNum)) 1)
                   (print towersNum)
                   (hanoi '((car towersNum) (cadr towersNum) (cddr towersNum)))
               )
               (if (= (sub1 (sumSublists towersNum)) 1)
                   (print towersNum)
                   (hanoi '((cddr towersNum) (cadr towersNum) (car towersNum))) 
               )
        )
    )
)
sumSublists返回游戏中有多少磁盘。我得到了一个无限循环,因为每次使用它时,它都会取相同的值,因此不会减少值。我的问题是,我太习惯于命令式和面向对象的变量使用,所以我不知道当Hanoi只取一个参数时我怎么能做到这一点

<河内代码是我尝试将我的项目从C++变成方案。


感谢您的帮助。顺便说一句,我正在使用Dr.Racket作为我的IDE。

河内塔是一个固有的递归问题,它有一个优雅的递归解决方案。我不会直接给出解决方案,但我会解释解决方案背后的直觉。考虑:

+--+||
| 1 |                     |                       |
+-----------+                 |                       |
|     2     |                 |                       |
+-------------------+             |                       |
|         3         |             |                       |
+-------------------+   +-------------------+   +-------------------+
A、B、C
给定
n
光盘,最小的光盘标记为
1
,最大的光盘标记为
n
。我们的工作是将所有光盘从堆栈
A
移动到堆栈
C
,同时保持不变,即较大的光盘可能永远不会放在较小的光盘上。如果没有这个不变量,解决方案将是微不足道的

现在,我们可以将光盘
n
A
移动到
C
的唯一方法是首先将其上方的所有光盘从
A
移动到
B

|||
|                       |                       |
|                     +---+                     |
|                     | 1 |                     |
+-------------------+       +-----------+                 |
|         3         |       |     2     |                 |
+-------------------+   +-------------------+   +-------------------+
A、B、C
我们的解决方案现在很简单。我们可以用三个简单的步骤来解决问题。首先,我们将光盘
n
上方的所有光盘从
A
移动到
B
。接下来,我们将光盘
n
A
移动到
C
。最后,我们将剩余的光盘从
B
移动到
C

将所有光盘从
A
移动到
C
的问题现在分为两个子问题:

  • 将小于光盘
    n
    的所有光盘从
    A
    移动到
    B
  • 将小于光盘
    n
    的所有光盘从
    B
    移动到
    C
  • 我们如何解决这些子问题?我们不必。根据递归原理,我们已经解决了这些子问题

    现在,我们有三个堆栈,分别标记为
    A
    B
    C
    。但是,我们想从源堆栈、目标堆栈和辅助堆栈的角度来讨论这些堆栈。在解决将光盘
    n
    A
    移动到
    C
    的问题时,我们将
    A
    称为源,将
    C
    称为目标。此外,我们需要使用
    B
    ,我们称之为辅助堆栈

    需要注意的一件重要事情是源、目标和辅助堆栈不断变化。对于“将光盘
    n
    A
    移动到
    C
    ”问题,源是
    A
    ,目标是
    C
    。但是,对于“将光盘
    n-1
    A
    移动到
    B
    ”问题,源是
    A
    ,目标是
    B
    。第三个堆栈(不是源或目标)始终是辅助堆栈


    这将给你足够的洞察力来解决河内塔的问题。当你解决这个问题时,你会惊讶地发现,与命令式代码相比,这个解决方案是多么简单、优雅和直截了当。

    河内塔是一个固有的递归问题,它有一个优雅的递归解决方案。我不会直接给出解决方案,但我会解释解决方案背后的直觉。考虑:

    +--+||
    | 1 |                     |                       |
    +-----------+                 |                       |
    |     2     |                 |                       |
    +-------------------+             |                       |
    |         3         |             |                       |
    +-------------------+   +-------------------+   +-------------------+
    A、B、C
    
    给定
    n
    光盘,最小的光盘标记为
    1
    ,最大的光盘标记为
    n
    。我们的工作是将所有光盘从堆栈
    A
    移动到堆栈
    C
    ,同时保持不变,即较大的光盘可能永远不会放在较小的光盘上。如果没有这个不变量,解决方案将是微不足道的

    现在,我们将光盘
    n
    A
    移动到
    C
    的唯一方法是首先将其上方的所有光盘从
    A
    移动到