我已经在Python中实现了以下两个功能:
def c(m, n):
if m == 0:
return 0
elif m == 1 and n >= 0:
return n**2+n+1
elif m > 1 and n == 0:
return c(m-1, 1)
elif m > 1 and n > 0:
return c(m-1, c(m, n-1))
def d(n):
exp_num = n-1
result = 2
while exp_num != -1:
result = result**2
exp_num -= 1
final_result = 2**result
return final_result
其中输入m
和n
都是自然数。我被要求找到一个x
,这样对于所有数字y >= x
,c(y,y) > d(y)
。
一些输入和输出:
c(1, 1) = 3
c(2, 2) = 183
d(1) = 16
d(2) = 65536
d(3) = 115792089237316195423570985008687907853269984665640564039457584007913129639936
您可以看到d
的增长速度远远超过c
。我该如何解决这个问题?任何帮助将非常感激。
答案 0 :(得分:1)
函数c是Ackermann–Péter function的变体。
它之所以成名,是因为它不是Primitive Recursive,在这里,它的目的是意味着随着数量变得非常大,它很快就会用完堆栈空间。
问题是找到最小值x,使得y> = x时c(y,y)> d(y)。
我们认为这是c(3,3),但无法计算。我们确实计算了1和2:
d(1)= 16,d(2)= 65536,d(3)= 115792089237316195423570985008687907853269984665640564039457584007913129639936
c(1)= 3,c(2,2)= 183,c(3,3)=?
由于它不是原始递归的,因此c(3,3)难以计算(即耗尽堆栈空间)。但是,我们可以获取一个较低的 通过限制函数定义中的递归。
操作如下。
# Will use Memoization which eliminates repeated calculations in recursive functions
class Memoize:
def __init__(self, fn):
self.fn = fn
self.memo = {}
def __call__(self, *args):
if args not in self.memo:
self.memo[args] = self.fn(*args)
return self.memo[args]
@Memoize
def c(m, n, cnt = 0, MAX_RECURSION = 20):
" Refactor function c to have a max recursion depth "
if cnt > MAX_RECURSION:
return 0 # We know the return value is always >= 0, but normally
# much larger. By quitting early and returning zero we are
# ensuring our final computation will be smaller than it would
# otherwise if we had not limited the recurison depth
#
if m == 0:
return 0
elif m == 1 and n >= 0:
return n**2+n+1
elif m > 1 and n == 0:
return c(m-1, 1, cnt+1)
elif m > 1 and n > 0:
return c(m-1, c(m, n-1, cnt+1), cnt+1)
def d(n):
exp_num = n-1
result = 2
while exp_num != -1:
result = result**2
exp_num -= 1
final_result = 2**result
return final_result
value_d = d(3)
value_c = c(3, 3)
print('Number of digits in d(3) is {}'.format(len(str(value_d))))
#>>> Number of digits in d(3) is 78
print('Number of digits in c(3, 3) is {}'.format(len(str(value_c))))
#>>>Number of digits in c(3, 3) is 74176
因此,我们看到c(3,3)比d(3)多了约1K位数。自从我们在计算c(3,3)的早期就停止了递归以来,情况将会更加严重。