Why sublime text and VSCode not showing runtime error? - c++

In the below code snippet, for example, take n as 9 and the array a's elements as {5,5,4,5,5,5,4,5,6}.
Sublime text and visual studio code are showing the correct output as 3 but Leetcode online ide is showing "runtime error: index 8 out of bounds for type 'int [k]' ". I want to know why sublime text and visual studio code are not showing the runtime error, and if there is an ide/text editor which shows runtime error, please recommend it to me.
int k = n - 1;
int temp[k];
for (int i = 0 ; i < k ; i++)
{
temp[i] = (a[i] - a[i + 1]);
}
int res = INT_MIN;
for (int i = 0 ; i < k ; )
{
int x = temp[i];
int c = 0;
while (x == temp[i])
{
i++;
c++;
}
res = max(res, c + 1);
}
cout<<res;

int k = n - 1;
int temp[k]; // variable length array, must be either #define k <constant num>
// or 'const int k'
The variable-length arrays (VLAs) aren't supported in C++ standard. The Sublime Text & VS Code doesn't matters at all, but the compiler.
You might've not enabled your compiler warnings, thus, you're unable to see any error. You can do it by appending -pedantic flag in your compilation option to see all warnings.

Related

Why is 1 for-loop slower than 2 for-loops in problem related to prefix sum matrix?

I'm recently doing this problem, taken directly and translated from day 1 task 3 of IOI 2010, "Quality of life", and I encountered a weird phenomenon.
I was setting up a 0-1 matrix and using that to calculate a prefix sum matrix in 1 loop:
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (a[i][j] < x) {lower[i][j] = 0;} else {lower[i][j] = 1;}
b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + lower[i][j];
}
}
and I got TLE (time limit exceeded) on 4 tests (the time limit is 2.0s). While using 2 for loop seperately:
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (a[i][j] < x) {lower[i][j] = 0;} else {lower[i][j] = 1;}
}
}
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + lower[i][j];
}
}
got me full AC (accepted).
As we can see from the 4 pictures here:
TLE result, picture 1 : https://i.stack.imgur.com/9o5C2.png
TLE result, picture 2 : https://i.stack.imgur.com/TJwX5.png
AC result, picture 1 : https://i.stack.imgur.com/1fo2H.png
AC result, picture 2 : https://i.stack.imgur.com/CSsZ2.png
the 2 for-loops code generally ran a bit faster (even in accepted test cases), contrasting my logic that the single for-loop should be quicker. Why does this happened?
Full code (AC) : https://pastebin.com/c7at11Ha (Please ignore all the nonsense bit and stuff like using namespace std;, as this is a competitive programming contest).
Note : The judge server, lqdoj.edu.vn is built on dmoj.ca, a global competitive programming contest platform.
If you look at assembly you'll see the source of the difference:
Single loop:
{
if (a[i][j] < x)
{
lower[i][j] = 0;
}
else
{
lower[i][j] = 1;
}
b[i][j] = b[i-1][j]
+ b[i][j-1]
- b[i-1][j-1]
+ lower[i][j];
}
In this case, there's a data dependency. The assignment to b depends on the value from the assignment to lower. So the operations go sequentially in the loop - first assignment to lower, then to b. The compiler can't optimize this code significantly because of the dependency.
Separation of assignments into 2 loops:
The assignment to lower is now independent and the compiler can use SIMD instructions that leads to a performance boost in the first loop. The second loop stays more or less similar to the original assembly.

C++ functions, arrays, and pointers

There is already a lot about this but none solved my problem or maybe I just didn't understand the answers. I'm just simply trying to return an array from a function
Also, I am having to put all of my functions above the main function that also seems weird to me.
And here is what happens when I try to use pointers:
int * RookMoves(int startingPosition, bool isWhite, int theBoard[64]){
int startingPositionXY[2] = { startingPosition % 8, (startingPosition - (startingPosition % 8)) / 8 };
int possibleRookPositions[14];
int possiblePosXY[2];
int counter = 0;
for (int h = 0; h < 2; h++)
{
int counter2 = 1;
for (int j = 0; j < 2; j++)
{
counter2 *= -1;
for (int i = 1; i < 8; i++)
{
int other = startingPositionXY[h] + (i * counter2);
int hInverted = (h + abs(h - 1)) * abs(h - 1); // 0 + 1 * 1 = 1 but 1 + 0 * 0 = 0
if (other < 8 && other > -1)
{
possiblePosXY[h] = other;
possiblePosXY[hInverted] = startingPositionXY[hInverted];
int movesOneDim = possiblePosXY[0] + (possiblePosXY[1] * 8);
if (CalculateSameColor(isWhite, theBoard[movesOneDim])) {
possibleRookPositions[counter] = movesOneDim;
counter++;
if (CalculateEnemy(isWhite, theBoard[movesOneDim]))
{
break;
}
}
else
{
break;
}
}
else
{
break;
}
}
}
}
for (int i = counter; i < 14; i++) //simply changing any unused elements to -1 for later recognition
{
possibleRookPositions[i] = -1;
}
cout << sizeof(possibleRookPositions) / sizeof(possibleRookPositions[0]) << ' '; // returns 14 just as it should
return possibleRookPositions;
}
int main()
{
int testBoard[64];
for (int i = 0; i < 64; i++) {
testBoard[i] = 0;
}
int* arr = RookMoves(21, true, testBoard);
cout << sizeof(arr) / sizeof(arr[0]); //ouputs: 1, should be 14
}
by all things the web says the pointer one should work but it doesn't, it returns an array with a size of 1.
An array in C++, in “simple” code, is either std::vector or std::array. Those can be returned without any problem. I’d say your issue is that you are writing mostly C and calling it C++. C is IMHO much harder to get right for beginners - so use the fact that you got C++ available for your use!
The C-style arrays is something any professional C++ programmer of course fully understands, but whenever I’m forced to write code like that (due to what amounts to customer requirements), it almost never passes the tests on the first try. So don’t be too worried: even people who can write a compiler that could take this array code and produce assembly output still have trouble with getting it right to some extent. It’s unwieldy and it has almost no place in C++ of today.
I was trying to get sizeof from a pointer because I don't really understand how those work yet but all I needed to do was to use pointers but just initialize the array I was returning as "static." Thanks to MikeCAT

Trying to avoid if-else statement inside for-loop but the code seems to have some errors

This snippet works just fine.
for (int i = 0; i < 1; i++) // for some other purpose
{
// some other code
double** angle = new double* [10]; // for a 2D matrix
for (int j = 0; j < 10; j++)
{
angle[j] = new double [3];
if (j == 0)
angle[j][0] = 2; // focused on the first column for now
else
angle[j][0] = angle[j-1][0]+3;
std::cout << angle[j][0] << std::endl;
}
for (int i = 0; i < 10; i++)
delete[] angle[i];
delete[] angle;
}
I am trying to not use conditional statement inside the loop. If I replace that with the following line, the code stops working. Please help me understand it.
angle[j][0] = (j == 0) * 2 + (j != 0) * (angle[j-1][0] + 3);
Using g++ -std=c++11 -o out main.cpp; ./out on Ubuntu 16.04 LTS
You're trying to use the ternary operator, but the syntax is wrong.
Do this:
angle[j][0] = (j == 0) ? 2 : (angle[j-1][0] + 3);
The line
angle[j][0] = (j == 0) * 2 + (j != 0) * (angle[j-1][0] + 3);
does not work since you access angle[-1] when j is 0. That is a reason for undefined behavior.
Looking at your comment to the other answer, you are apparently looking for using the conditional operator.
angle[j][0] = (j == 0) ? 2 : (angle[j-1][0] + 3);
As Sahu said, the problem with your combined line is that you take angle[j-1][0] with j==0, which is undefined behavior. This means that combining both if and else parts into a single non-branching statement is not really possible.
Secondly, these two code snippets look different (with the ternary/conditional operator producing fewer lines of C++ code):
if (x == 1)
A = 7;
else
A = 13;
versus
A = (x == 1) ? 7 : 13;
But they compile to exactly the same machine code.
So, how do we fix your problem of not wanting to branch in every single loop iteration?
Since the test/branch variable (j) is also the loop variable and the test is for j == 0, which is also the starting condition, you can do something like this:
double** angle = new double* [10]; // for a 2D matrix
angle[0] = new double[3]; // Prepare the first element
angle[0][0] = 2;
for (int j = 1; j < 10; j++) // Fill out the rest
{
angle[j] = new double[3];
angle[j][0] = angle[j - 1][0] + 3;
std::cout << angle[j][0] << std::endl;
}
Where the setup for the first element is moved out of the loop, after which the loop can be started at j=1 and only have the else branch in the loop body (with no test, of course).
However, given that branch predictors in modern CPUs are pretty awesome, and your loop hits the if-branch exactly once; on the first loop-iteration, and the else-branch on every following one, I doubt that you will see much difference in the execution times for the two versions. So, I would simply recommend that you pick the version that you find most easy to read and understand.

The knapsack problem, visual studio issues

I implemented a dynamic programming solution to the famous knapsack problem. Now the funny part of this is that visual studio will not allow my code to compile yet when I copy and paste my code in cpp.sh it runs fine with no errors.
At the moment this is what I am getting in visuial studio for errors:
Unhandled exception at 0x0FADED76 (ucrtbased.dll) in Practice.exe: An invalid
parameter was passed to a function that considers invalid parameters fatal.
This occurs at line 10, i.e. dp[i][j] = 0. I am not sure how to fix this issue, and in general I have noticed that visual studio can be particularly whiny.
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
int maxKnapSack(std::vector<int>& v, std::vector<int>& w, int capacity) {
std::vector<std::vector<int>> dp(capacity + 1, std::vector<int>(v.size() + 1));
for (int i = 0; i <= v.size(); i++) {
for (int j = 0; j <= capacity; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
}
else if (j - w[i - 1] >= 0) {
dp[i][j] = std::max(v[i-1] + dp[i - 1][j - w[i-1]], dp[i - 1][j]);
}
else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[v.size()][capacity];
}
int main() {
std::vector<int> v = { 10, 4, 7 };
std::vector<int> w = { 4, 2, 3 };
int capacity = 5;
std::cout << "The maximum I can get is " << maxKnapSack(v, w, capacity) << "\n";
std::cin.get();
}
Your vector dp contains 6 elements, each element being a vector of 4 elements. It's equivalent to the array definition int dp[6][4].
Your outer loop loop from 0 to 4 (inclusive) and the inner loop loops from 0 to 6 (inclusive). That means you will use index out of bounds in the nested (inner) vector.
Your loops should be the other way around with their limits. Or your vector dp should be defined with the sizes switched.
Your conditions inside the inner loop are also wrong. The condition i == 0 || j == 0 will be false if e.g. i == 0 and j != 0. That will then lead to you using negative indexes because of i - 1. That is also out of bounds and again lead to undefined behavior.
You need to make sure that the else if only happens when i > 0 and j - w[i-1] > 0 as well. And the else only when i > 0.

C++ memory: deleting an unused array of bool can change the result from right to wrong

I am trying to solve Project Euler Problem 88, and I did it without too much effort; however, I find that some seemingly irrelevant code in my program is affecting the result. Here's my complete code (it's not short, but I cannot locate the error. I believe it would be obvious to more experienced eyes, so please read my description first):
#include <iostream>
#include <set>
using namespace std;
bool m[24001][12001];
bool p[24001]; // <------------ deleting this line will cause error in result!
long long answer[12001];
int main() {
long long i;
long long j;
long long l;
set<long long> all;
long long s = 0;
for (i = 0; i <= 24000; i++) {
for (j = 0; j <= 12000; j++) {
m[i][j] = false;
}
}
m[1][1] = true;
for (i = 2; i <= 24000; i++) {
m[i][1] = true;
for (j = 2; (j <= i) && (i * j <=24000); j++) {
for (l = 1; l <= i; l++) {
if (m[i][l]) {
m[i * j][l + 1 + (i * j) - i - j] = true;
}
}
}
}
for (i = 0; i <= 24000; i++) {
for (j = 0; j <= 12000; j++) {
if (m[i][j] && (answer[j] == 0)) {
answer[j] = i;
}
}
}
for (i = 2; i <= 12000; i++) {
cout << answer[i] << endl;
all.insert(answer[i]);
}
cout << all.size() << endl;
for (set<long long>::iterator it = all.begin(); it != all.end(); it++) {
//cout << *it << endl;
s += *it;
}
cout << s << endl;
}
With the "useless" bool array, all the answers are right, between 0 and 24000; but without it, some answers in the middle got corrupted and become very large numbers.
I am completely confused now; why would that unused array affect the middle of the answer array?
Thanks and sorry for the long code! I will be grateful if someone could edit the code into a better example, I simply son't know what is with the code.
You do a silly thing in here:
m[i * j][l + 1 + (i * j) - i - j] = true;
Say, i=160, j=150, l=1... You will try to access m[24000][23692]... And you corrupt the stack, so behavior is undefined.
Next time try to use some profiler and/or debugger.
Add:
#include <cassert>
at the begining and
assert( (i * j) * 12001 + (l + 1 + (i * j) - i - j) <= 12001*24001 );
before the following line:
m[i * j][l + 1 + (i * j) - i - j] = true;
The assertion will fail, which means you write outside the bounds of the array m.
As requested, adding this to an answer.
You are definitely writing beyond the bounds of the array m somewhere, when the unused array p exists, m overwrites in to its contents which doesn't affect the answer array but once p is removed the overwriting happens in to answer array showing up the problems.
Overwriting beyond the bounds of the array is an Undefined Behavior and it causes your program to be ill-formed. With Undefined Behavior all safe bets are off and any behavior is possible. While your program may work sometimes or crash sometimes or give incorrect results.Practically, Anything is possible and the behavior may or even may not be explainable.
In one of your nested loops you use l as the index for the second dimension. This variable can run from 0 to i and i, in turn, can run from 0 to 24000. Since your second dimension of the array can only be index from 0 to 12000 this causes a classic out of range error. This also nicely explains why adding an extra array avoid the problem: the out of range accesses go to the "unused" array rather than overwriting the result.