Open10
Ackermann(*,*)の壁を突破したかった
import sys
sys.setrecursionlimit(10000)
def ackermann(m, n):
if m == 0:
return n + 1
elif n == 0:
return ackermann(m - 1, 1)
else:
return ackermann(m - 1, ackermann(m, n - 1))
print(ackermann(4, 1))
(4,1) を計算するには再帰深度10000でも足りない
Traceback (most recent call last):
File "/***/main.py", line 16, in <module>
print(ackermann(5, 0))
File "/***/main.py", line 11, in ackermann
return ackermann(m - 1, 1)
File "/***/main.py", line 13, in ackermann
return ackermann(m - 1, ackermann(m, n - 1))
File "/***/main.py", line 13, in ackermann
return ackermann(m - 1, ackermann(m, n - 1))
File "/***/main.py", line 13, in ackermann
return ackermann(m - 1, ackermann(m, n - 1))
[Previous line repeated 993 more times]
File "/***/main.py", line 11, in ackermann
return ackermann(m - 1, 1)
File "/***/main.py", line 8, in ackermann
if m == 0:
RecursionError: maximum recursion depth exceeded in comparison
Process finished with exit code 1
ちなみに sys.setrecursionlimit(100000)
だとこう
ショートカット戦法
import sys
sys.setrecursionlimit(10000)
def ackermann(m, n):
if m == 0:
return n + 1
# 1から3まではショートカットを作る
elif m == 1:
return n + 2
elif m == 2:
return 2 * n + 3
elif m == 3:
return pow(2, n + 3) - 3
# ショートカットここまで
elif n == 0:
return ackermann(m - 1, 1)
else:
return ackermann(m - 1, ackermann(m, n - 1))
print(ackermann(4, 1))
65533
Process finished with exit code 0
5x5の表が作れるかどうか
まあ無理なんですけどね
import sys
sys.setrecursionlimit(10000)
def ackermann(m, n):
if m == 0:
return n + 1
# 1から3まではショートカットを作る
elif m == 1:
return n + 2
elif m == 2:
return 2 * n + 3
elif m == 3:
return pow(2, n + 3) - 3
# ショートカットここまで
elif n == 0:
return ackermann(m - 1, 1)
else:
return ackermann(m - 1, ackermann(m, n - 1))
for i in range(1, 5 + 1):
for j in range(1, 5 + 1):
print("ack(%d, %d) = %d" % (i, j, ackermann(i, j)))
結果
(4,2)の計算を最後に応答がなくなりました
計算自体は間違ってなさそう
あとで読む
まず最初にここにたどり着くべきであった
比較用
import sys
sys.setrecursionlimit(100000)
count = 0
def ackermann(m, n):
global count
count += 1
print("count: %s" % count)
if m == 0:
return n + 1
elif n == 0:
return ackermann(m - 1, 1)
else:
return ackermann(m - 1, ackermann(m, n - 1))
memo = {}
def ackermann1(m, n):
global count
count += 1
print("count: %s" % count)
if tuple([m, n]) in memo:
return memo[tuple([m, n])]
if m == 0:
memo[tuple([m, n])] = n + 1
elif n == 0:
memo[tuple([m, n])] = ackermann1(m - 1, 1)
else:
memo[tuple([m, n])] = ackermann1(m - 1, ackermann1(m, n - 1))
return memo[tuple([m, n])]
print(ackermann(3, 5))
print(ackermann1(3, 5))
memo
import sys
sys.setrecursionlimit(100000)
memo = {}
def ackermann(m, n):
if tuple([m, n]) in memo:
return memo[tuple([m, n])]
if m == 0:
memo[tuple([m, n])] = n + 1
elif n == 0:
memo[tuple([m, n])] = ackermann(m - 1, 1)
else:
memo[tuple([m, n])] = ackermann(m - 1, ackermann(m, n - 1))
return memo[tuple([m, n])]
for i in range(6):
for j in range(6):
print("ack(%s, %s) = %s" % (i, j, ackermann(i, j)))
result
ack(0, 0) = 1
ack(0, 1) = 2
ack(0, 2) = 3
ack(0, 3) = 4
ack(0, 4) = 5
ack(0, 5) = 6
ack(1, 0) = 2
ack(1, 1) = 3
ack(1, 2) = 4
ack(1, 3) = 5
ack(1, 4) = 6
ack(1, 5) = 7
ack(2, 0) = 3
ack(2, 1) = 5
ack(2, 2) = 7
ack(2, 3) = 9
ack(2, 4) = 11
ack(2, 5) = 13
ack(3, 0) = 5
ack(3, 1) = 13
ack(3, 2) = 29
ack(3, 3) = 61
ack(3, 4) = 125
ack(3, 5) = 253
ack(4, 0) = 13
ack(4, 1) = 65533
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
おおー面白い
from collections import deque
def ackermann(m, n):
stack = deque([])
stack.extend([m, n])
while len(stack) > 1:
n, m = stack.pop(), stack.pop()
if m == 0:
stack.append(n + 1)
elif m == 1:
stack.append(n + 2)
elif m == 2:
stack.append(2 * n + 3)
elif m == 3:
stack.append(2 ** (n + 3) - 3)
elif n == 0:
stack.extend([m - 1, 1])
else:
stack.extend([m - 1, m, n - 1])
return stack[0]
print(ackermann(4, 3))
へんじがない
そりゃ