0

I have some code. I use Visual Studio to compile, and since it doesn't let you compile an already compiled program, I just remove and replace a semi-colon or something like that so it thinks it's different and lets me recompile.

The code is about Project Euler problem 11 (https://projecteuler.net/problem=11). I compile it and it gives a correct answer, then I recompile and it gives a wrong answer. The wrong answer appears to be like calling an integer in an array out of bounds. And it also only compiles into a broken state when I remove and put a semi-colon in a different place than the last time. I've noticed it only happens on some of the arrays (I pointed them out in code comments). I've tried some other things but they didn't break it.

long long ULEvenify(long long crntNum)
{
    if ((crntNum / 10) % 2 != 0) return +10;
    return crntNum;
}

template<size_t N>
long long GridGP(long long (&grid)[N]) //Stands for Grid Greatest Product; https://projecteuler.net/problem=11
{
    long long gridSize = sizeof(grid) / sizeof(*grid);
    long long digitProd = 1; //Digit Product
    long long potDigProd = 1; //Potential Digit Product
    for (long long numLocation = 0; numLocation < gridSize - 59; numLocation++) //-31 so that it doesn't continue onto the last 3 rows
    {
        cout << "NEW" << "\n";
        cout << numLocation << "\n";
        potDigProd = 1;
        if (numLocation >= (((numLocation / 10) * 10) + 3)) //Left Diagonal
        {
            for (long long i = 0; i <= 3; i++) //Times 4 not 3, so that it includes the first number in the series of 4 adjacent numbers
            {
                cout << numLocation + ((i * 10) - i) << "a" << "\n";
                cout << "GRID: " << grid[numLocation + ((i * 20L) - i)] << ", " << grid[numLocation] << "; ";
                potDigProd *= grid[numLocation + ((i * 20L) - i)]; //HERE
            }
            if (potDigProd > digitProd) digitProd = potDigProd;
            potDigProd = 1;
        }
        if (numLocation < ((ULEvenify(numLocation) / 10) * 10) + 7 && numLocation > 59) //Right Diagonal
        {
            for (long long i = 0; i <= 3; i++)
            {
                potDigProd *= grid[(numLocation - ((i * 20L)) + i)]; //HERE
            }
            if (potDigProd > digitProd) digitProd = potDigProd;
            potDigProd = 1;
        }
        for (long long i = 0; i <= 3; i++) //Down, doesn't requre an if statement to check if it's beyond the last 4th row because the for loop doesn't go beyond the last 4th row
        {
            potDigProd *= grid[numLocation + (i * 20L)]; //HERE
        }
        if (potDigProd > digitProd) digitProd = potDigProd;
        potDigProd = 1;
        if (numLocation > 59)
        {
            for (long long i = 0; i <= 3; i++)
            {
                potDigProd *= grid[numLocation - (i * 20L)]; //HERE
            }
            if (potDigProd > digitProd) digitProd = potDigProd;
            potDigProd = 1;
        }
    }
    return digitProd;
}  

The main() method just has the grid from Problem 11 as an int array and a cout << GridGP(grid20x2); statement.

I just don't understand how this makes any sense! I'm changing nothing of significance, and it only breaks when I "change nothing" in a different place from a set of places than the last time. Why does this happen? What is this? Schrodinger's code? Before compilation, both broken and working, and on compilation collapses to one state?

Note: Yes, I know the code is bad and there's a better way for Problem 11, but that's not the point. The point is, how can the answer be sometimes correct and sometimes wrong?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    are you sure that all array accesses are within bounds? – 463035818_is_not_an_ai Sep 29 '20 at 20:44
  • You still don't debug? If you do meanwhile, tell us your observations about how the variables change at each step please. I think we told you all the relevant information we can grasp from that incomplete example from your [last question](https://stackoverflow.com/questions/64120916/program-output-varies-for-unknown-reason) about that. – πάντα ῥεῖ Sep 29 '20 at 20:45
  • removing and adding a semicolon does not change the code. Are you also compiling and running this code in an environment under your control? Or your you only submitting it on project euler and hope for the best? – 463035818_is_not_an_ai Sep 29 '20 at 20:45
  • 1
    please dont post the same question twice. This is wasting yours and our time. If your question got closed then consider that it was closed for a reason and try to improve it. If you post a very similar question it will very likely be closed again (actually this one is less clear than the original) – 463035818_is_not_an_ai Sep 29 '20 at 20:47
  • btw do you know why you are using `template long long GridGP(long long (&grid)[N])` as signature for the function? The first line in the function should not be there – 463035818_is_not_an_ai Sep 29 '20 at 20:49
  • All of the Visual Studios, since at least 2008, have a "Rebuild" option. What version of Visual Studio are you using that doesn't have a "Rebuild" option or feature. You may need to dive into the display options and tell VS to display the "Rebuild" option. – Thomas Matthews Sep 29 '20 at 21:01
  • *I just don't understand how this makes any sense! I'm changing nothing of significance, and it only breaks when I "change nothing" in a different place from a set of places than the last time* -- It makes a lot of sense if you're accessing an element out-of-bounds. Doing so invokes undefined behavior. Also, if you have the test data, take the time to add that test data to `main`, and post the program. Right now, we have to go that link, copy the test data, create a `main` function with that data, add the headers, etc. This is the work you should have done before posting the question. – PaulMcKenzie Sep 29 '20 at 21:02
  • @PaulMcKenzie then how come sometimes the answer is correct? and other times it's completely random? and the random numbers are no where near in size as the correct one they are much bigger – Octodecillion Sep 29 '20 at 21:03
  • @Octodecillion -- Undefined behavior means just that -- the behavior is undefined. You've just explained it, but you didn't know it. – PaulMcKenzie Sep 29 '20 at 21:04
  • you already got the right pointers. Your code may have [undefined behavior](https://en.cppreference.com/w/cpp/language/ub). ub can manifest as changing the code such that output should be the same but output is not the same. You can find out if your code goes wrong (and maybe invokes UB) by using a debugger as exaplained [here](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems). Your indexing is confusing and making an attempt to make it more readable is surely worthwhile. Unclear why "this isn't the point" when this is the point – 463035818_is_not_an_ai Sep 29 '20 at 21:04
  • @idclev463035818 I don't submit and hope for the best. The wrong numbers are too huge to be anything close to the product of 4 2 digit numbers. And this question isn't the same as the last one, the last one i understood why that happened because i accessed element out of bound array giving the numbers, but in here it is sometimes correct, then i change nothing of significance and it is wrong – Octodecillion Sep 29 '20 at 21:05
  • Use temporary variables for common calculations. You may want to help the compiler by assigning repeated expressions to a temporary variable, such as `numLocation + ((i * 20L) - i)`. In higher optimization levels, the compiler may recognize the pattern and perform the operation. IMHO, there is no need to repeat a calculation. – Thomas Matthews Sep 29 '20 at 21:05
  • Then please provide a [mcve]. What tests are you using? What is the output, input, what is the expected output? – 463035818_is_not_an_ai Sep 29 '20 at 21:07
  • @Octodecillion -- And how do you know you're not going out-of-bounds with the current code? Don't say "I looked at my program a long time" -- that proves nothing. – PaulMcKenzie Sep 29 '20 at 21:07
  • You may want to separate a defined function from a templated function (place in different files). The template function is not instantiated, until it is recognized with a concrete type (or no type) when called. Some compilers will not compile it until then. Compiling the defined functions many times may violate ODR. – Thomas Matthews Sep 29 '20 at 21:08
  • @PaulMcKenzie Because when i submit the answer to project euler it's correct, but then when i do what i mentioned in the post i get the element out of bound outputs, and then i can change it again and get the correct answer again – Octodecillion Sep 29 '20 at 21:09
  • @Octodecillion -- You're not getting the point of what undefined behavior is. What you're describing is **exactly** what undefined behavior can do. – PaulMcKenzie Sep 29 '20 at 21:11
  • if this question is substantially different from your last one we can reopen it in a blink, I just dont see it yet – 463035818_is_not_an_ai Sep 29 '20 at 21:11
  • you cannot verify correctness of some c++ code by compiling it with one compiler, running it and getting the right result. "It compiles" is by far the lowest bar you can put and "I can pass one test" is just one step more, but from there it is a long way to "my code is correct". If your code is correct you get the expected output anywhere. If your code has UB it can appear to work here and fail elsewhere – 463035818_is_not_an_ai Sep 29 '20 at 21:15
  • But then why in a certain compilation it always gives an out of bounds number, then in another one the correct answer no matter how many times i ran it. Shouldn't UB always be random? – Octodecillion Sep 29 '20 at 21:19
  • @Octodecillion -- There are programs that have been running for years that contains bugs. Undefined behavior means just that -- again -- the behavior is undefined. Trying to place bets on when, how many times, etc. your program will fail is impossible. – PaulMcKenzie Sep 29 '20 at 21:20
  • Out of bounds you don't get from copmilation , its in your code. Did you actually change something on the code compared to your previous question? When it was wrong before, why are you now convinced that it is fine? – 463035818_is_not_an_ai Sep 29 '20 at 21:32
  • 1
    @Octodecillion -- Given the data, changing to `std::vector` and using `at()` to access the elements proves your code is going out of bounds. [Here is the code](https://ideone.com/4A5AkS). Scroll all the way to the bottom of that listing -- do you see the `std::out_of_range` exception being thrown? Now take that code, and run it on *any* C++ compiler -- you will see the error. – PaulMcKenzie Sep 29 '20 at 21:37
  • @PaulMcKenzie Weird, thing is sometimes on when i compile it in visual studio it doesn't give the exception. But why would it even go out of bounds? if you go to the problem 11 page and find a `04` next to `89` the `89` does have enough space to go left diagonal – Octodecillion Sep 30 '20 at 11:41
  • You see the calls to `at()`? One of those threw the exception -- instead of guessing, you see that the code stops at `340` in the output. Now take the 340 and do see if the line(s) with `at()` are within bounds of the vector. Even the message in the exception is telling you the error. – PaulMcKenzie Sep 30 '20 at 13:27

0 Answers0