fork download
  1. # http://stackoverflow.com/questions/9831666/how-can-you-emulate-recursion-with-a-stack
  2.  
  3. def ack(m, n):
  4. assert m >= 0 and n >= 0
  5. if m == 0: return n + 1
  6. if n == 0: return ack(m - 1, 1)
  7. return ack(m - 1, ack(m, n - 1))
  8.  
  9. def ack_iter(m, n):
  10. stack = []
  11. push = stack.append
  12. pop = stack.pop
  13. RETURN_VALUE, CALL_FUNCTION, NESTED = -1, -2, -3
  14.  
  15. push(m) # push function arguments
  16. push(n)
  17. push(CALL_FUNCTION) # push address
  18. while stack: # not empty
  19. address = pop()
  20. if address is CALL_FUNCTION:
  21. n = pop() # pop function arguments
  22. m = pop()
  23. if m == 0: # return n + 1
  24. push(n+1) # push returned value
  25. push(RETURN_VALUE)
  26. elif n == 0: # return ack(m - 1, 1)
  27. push(m-1)
  28. push(1)
  29. push(CALL_FUNCTION)
  30. else: # begin: return ack(m - 1, ack(m, n - 1))
  31. push(m-1) # save local value
  32. push(NESTED) # save address to return
  33. push(m)
  34. push(n-1)
  35. push(CALL_FUNCTION)
  36. elif address is NESTED: # end: return ack(m - 1, ack(m, n - 1))
  37. # old (m - 1) is already on the stack
  38. push(value) # use returned value from the most recent call
  39. push(CALL_FUNCTION)
  40. elif address is RETURN_VALUE:
  41. value = pop() # pop returned value
  42. else:
  43. assert 0, (address, stack)
  44. return value
  45.  
  46. print(ack(2, 4))
  47. print(ack_iter(2, 4))
  48. assert all(ack(m, n) == ack_iter(m, n) for m in range(4) for n in range(6))
  49. print(ack_iter(3, 4))
  50.  
Success #stdin #stdout 0.19s 5852KB
stdin
Standard input is empty
stdout
11
11
125