【发布时间】:2016-06-16 18:52:49
【问题描述】:
我们在 Uni 获得的任务之一是编写一个函数,该函数递归地打印出 河内塔谜题的动作:
public static void move(int number, char start, char help, char end) {
if (number == 1) {
print("Move the top disk from " + start + " to " + end);
} else {
move(number - 1, start, end, help);
print("Move the top disk from " + start + " to " + end);
move(number - 1, help, start, end);
}
}
现在我们必须想出一个函数来计算 n 元素的移动次数,并使用断言来检查我们使用此函数的代码的有效性。
显然,该函数由以下公式给出:f(n) = 2*f(n-1) + 1 为 n > 1 和 f(n) = 1 为 n = 1。我们可以求解这个递归方程并得到f(n) = 2^n - 1。
通过将static int count = 0;添加到类的顶部并在每个print语句之后递增它,我们可以获得移动的总数:
public static void move(int number, char start, char help, char end) {
if (number == 1) {
print("Move the top disk from " + start + " to " + end);
count++;
} else {
move(number - 1, start, end, help);
print("Move the top disk from " + start + " to " + end);
count++;
move(number - 1, help, start, end);
}
}
然后在函数调用之后添加一个断言,用递归方程的求解形式检查counter 的值:
move(n, 'A', 'B', 'C');
assert count == Math.pow(2,n) - 1 : "Number of movements isn't correct.";
这很好用。但是,我很想知道是否有一种方法可以在递归函数本身内部使用assert,并使用等式的递归形式检查移动的数量——比如assert count == 2*f(n-1) + 1。我们可能不得不更改 count 的使用方式,但我不知道如何(或者是否可能)。
注意:print() 仅代表标准 System.out.println()。
编辑:我更喜欢不需要更改 move 函数签名的解决方案(或者有人说如果没有这样的更改,这绝对是不可能的)
【问题讨论】:
标签: java recursion assert assertion