3

I am new to C++ but thought that working on some project Euler problems would familiarize me with the language.

When attempting Project Euler Problem 14: Longest Collatz sequence

I could not manage to get my C++ solution to work, but had no problem with my python solution...

import time 
start = time.time()
memo = {1:1,2:2}
longest_chain, longest_starting_key = 2, 2

def rec(a):
    global longest_chain, longest_starting_key

    if a in memo.keys():
        return memo[a]    
    if a % 2 == 0:
        memo[a] = rec(a // 2) + 1
    else:
        memo[a] = rec(3 * a + 1) + 1
    if memo[a] > longest_chain:
        longest_chain = memo[a]
        longest_starting_key = a
    return memo[a]    

for i in range(1000000,3,-1): rec(i)

print("starting key", longest_starting_key , ": has length", longest_chain)
print((time.time() - start), "seconds")

and got

starting key 837799 has length 525
1.399820327758789 seconds

My C++ attempt... (that I thought was equivalent...)

#include <iostream>
#include <unordered_map>
std::unordered_map<int, int> mem = { {1,1},{2,2} };
int longest_chain{ 2 }, best_starting_num{ 2 };

bool is_in(const int& i){
    auto search = mem.find(i);
    if(search == mem.end())
        return false;
    else
        return true;
}

int f(int n){
    if(is_in(n))
        return mem[n];
    if(n % 2)
        mem[n] = f(3 * n + 1) + 1;
    else
        mem[n] = f(n / 2) + 1;
    if(mem[n] > longest_chain)
        longest_chain = mem[n];
    return mem[n];
}

int main(){
    for(int i = 3; i < 1000000; i++){
        f(i);
    }
    std::cout << longest_chain << std::endl;
}

When running this in Visual Studio in debug mode I get the following error

Unhandled exception at 0x00007FF75A64EB70 in
0014_longest)collatz_sequence_cpp.exe: 0xC00000FD: Stack overflow
(parameters: 0x0000000000000001, 0x000000DC81493FE0).

Someone told me that I should allocate on the heap using pointers, but have very limited experience with working with pointers...

The other thing I don't understand is... when I run it with 100'000 instead of 1'000'000 in the main body loop, it works but is very slow.

4
  • running it through vc++ debugger would help a lot. I think mem allocates new elements in the heap already. Commented Sep 12, 2016 at 19:36
  • 1
    When I run your C++ code on my system I get a result of 489 (not 525). The Python and C++ versions are clearly not equivalent... Commented Sep 12, 2016 at 19:41
  • 1
    @Barry below provides a very good algorithmical answer, but there is also a coding error in your C++ version - you are doing map lookup twice whenever value is present, first to detect it's availability, second to actually get it. Not good. Commented Sep 12, 2016 at 19:49
  • It is worth doing a search of SO with the word Collatz for inspiration. Commented Sep 12, 2016 at 19:54

1 Answer 1

5

Hint: What is the invariant on the range of n that the Collatz sequence provides (mathematically), which your Python code satisfies but your C++ code doesn't? Hint to the hint: what are the last few values of n before your stack overflow actually occurs?

Sign up to request clarification or add additional context in comments.

3 Comments

Ah, just what I was about to say, but the hint format is more in keeping with educational theme of the question's context. :)
I have been staring at it, but to no avail. I changed the main loop in python version to look like the C++ version (instead of counting down of goes from 1 to 999'999). changed the names so that they look more like each other... But I still cannot spot it.
@Quantifeye Start at 113383. What are all the values of n that you call f with?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.