There is not much code to review here, but some titbits can be mentioned
Style
- The modern way is to use
cache
over lru_cache
unless you need a cache of a very specific size. For one-off imports I always include the package, however I've seen different opinions on this. Especially for standard libraries
- Include typing hints
- Include a docstring explaining what your code does.
- Include a
if __name__ == "__main__"
guard if you want to run more examples.
- Better name. It took me far to long to understand that
kuan = Knuth's up arrow notation
. You are not paid by the number of characters you write; feel free to be a bit verbose.
Implementation
I have no idea what implementation you are using? Looking at Wikipedia it gives me this
$$
a\uparrow^n b=
\begin{cases}
a^b, & \text{if }n=1; \\
1, & \text{if }n>1\text{ and }b=0; \\
a\uparrow^{n-1}(a\uparrow^{n}(b-1)), & \text{otherwise }
\end{cases}
$$
Which, when implemented correctly runs in milliseconds.
import functools
@functools.cache
def arrow(a: int, b: int, arrows: int) -> int:
"""Evaluates numbers using Knuth's up-arrow notation
Source: http://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation)
arrow(2, 3, 1)
= 2 * 2 * 2
= 8
arrow(2, 3, 2)
= arrow(2, arrow(2, 2, 1), 1)
= arrow(2, 4, 1)
= 2 * 2 * 2 * 2
= 2 ^ 4
= 16
arrow(2, 3, 3)
= arrow(2, arrow(2, 2, 2), 2)
= arrow(2, arrow(2, arrow(2, 1, 1), 1), 2)
= arrow(2, arrow(2, 2, 1), 2)
= arrow(2, 2 * 2, 2)
= arrow(2, 4, 2)
= arrow(2, arrow(2, arrow(2, 2, 1), 1), 1)
= arrow(2, arrow(2, 4, 1), 1)
= arrow(2, 2 * 2 * 2 * 2, 1)
= arrow(2, 16, 1)
= 2 * ... * 2 (16 times)
= 2 ^ 16
= 65536
Example:
>>> arrow_notation(2, 3, 1)
8
>>> arrow_notation(2, 3, 2)
16
>>> arrow_notation(2, 3, 3)
65536
>>> arrow_notation(3, 2, 3)
7625597484987
"""
if arrows == 1 or b == 0:
return a ** b
return arrow(
a=a,
b=arrow(a, b - 1, arrows),
arrows=arrows - 1,
)
if __name__ == "__main__":
import doctest
doctest.testmod()
# print(arrow_notation(3, 2, 3))
kuan(100, 100, 100)
. The problem is, it is very slow for (relatively) small inputs likekuan(3, 3, 2)
\$\endgroup\$kuan(a,b,1)
uses a completely different method than higherarrows
, so saying you can calculate that pretty quickly doens't help. Have you checked your validity elsewhere? By my math, yourkuan(3,3,2)
has about 3.3e12 digits. I wouldn't call that relatively small. You seem to be ending up with an extra exponentiation. \$\endgroup\$for i in range(b):
tofor _ in range(1, b):
fixes the code. Feel free to leave this as an answer =) \$\endgroup\$