Link to Question: https://projecteuler.net/problem=14
I began by defining the following functions below.
collatz := If[EvenQ[#], #/2, 3 # + 1] &
NotOneQ := collatz[#] != 1 &
collatzlength := Plus[NestWhileList[collatz, #, NotOneQ] // Length, 1] &
To find the actual answer, I inputted
Min[
Flatten[
Position[
Table[collatzlength[i], {i, 1, 999999}],
Max[Table[collatzlength[i], {i, 1, 999999}]]]]]
837799
Basically, it computes collatzlength
for i = 1
to i = 999999
, Tabled the results into a list, found the Position(s) of the maximum value in the list, and (in case there were multiple numbers with the same Collatz sequence length) took the minimum entry from a Flattened list.
Though this solution is simple and conceptually intuitive, it is fairly primitive and took a whopping 16 minutes for Mathematica to evaluate. How can I optimize this solution to make it compute faster? I saw other posts on StackExchange asking the same thing for Problem #14, but I was unable to understand any of the concepts discussed in those posts.
Thanks for reading,
-A
Edit: I tried the suggestion below about memorization. Here is the setup. Please let me know if it is incorrect and what needs to be changed. Please refer to the top of the post for the original function definitions.
f[x__] := collatz[x] = If[EvenQ[x], x/2, 3 x + 1]
g[x__] := f[x] != 1
h[x__] := collatzlength[x] = Plus[NestWhileList[f, x, g] // Length, 1]
The adjusted input was then
Min[Flatten[
Position[Table[h[i], {i, 1, 999999}],
Max[Table[h[i], {i, 1, 999999}]]]]]
I tested both methods using {i,1,10000}
and AbsoluteTiming
, and the computation time more than doubled after the memorizations were applied. Here are the results.
Original:
{21.303, 6171}
Memorizations applied:
{42.7376, 6171}
f[x_] := f[x] = rhs
The first time you call f[3], it will evaluate the rhs and assign that to f[3]. Next time you call f[3], it merely fetches the value from memory and skips evaluating the rhs a second time. If your program makes many redundant calls, this should save a lot of time. $\endgroup$collatz[x_] := collatz[x] = If[EvenQ[x], x/2, 3 x + 1]
, see what happens. Figure out if any other memoization might apply. And note belisarius's comment - there are smart ways to do this. $\endgroup$