Dynamic Programming solution doesn't work in Hackerrank enviroment - c++

My code runs perfectly on my machine but it fails even in the sample testcases on Hackerrank. How can the same code yield different results on two different environment?
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
int maxum(int arr[], int n)
{
int t[100][100];
for(int i=0;i<n+1; i++)
for(int j=0; j<n+1;j++)
{
if(i==0)
t[i][j]=0;
else
t[i][j]=max(t[i-1][j]+arr[i-1], t[i-1][j] );
}
int maximum=0;
for(int i=0;i<n+1;i++)
for(int j=0; j<n+1;j++)
{
if(t[i][j]>maximum)
maximum=t[i][j];
}
return maximum;
}
int main()
{
int arr[100],i,n;
cin>>n;
for(i=0;i<n;i++)
cin>>arr[i];
cout<<maxum(arr,n);
return 0;
}

The algorithm is just wrong. For instance given the input from the first test case
5
3 7 4 6 5
The correct answer is 13 (7+6) but your code outputs 25 (3+7+4+6+5).
It seems haven't implemented the requirement that the members of the maximal subset be non-adjacent.

Your code exhibits undefined behaviour at least for larger inputs. Example:
g++ -O3 -Wall -Wextra -pedantic -std=c++17 -fno-exceptions -fsanitize=address a.cpp
yes 100 | ./a.out
Triggers asan to complain, although the input is valid according to the constraints specified in the link your provide.
==298664==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffce142a650 at pc 0x55697440f74d bp 0x7ffce14209c0 sp 0x7ffce14209b8
WRITE of size 4 at 0x7ffce142a650 thread T0
#0 0x55697440f74c in maxum(int*, int) (/tmp/a.out+0x174c)
#1 0x55697440f26c in main (/tmp/a.out+0x126c)
#2 0x7fc97926acc9 in __libc_start_main ../csu/libc-start.c:308
#3 0x55697440f3a9 in _start (/tmp/a.out+0x13a9)
[rest of asan output omitted]

Related

Why does the program still work when there is malloc (NULL)?

I wrote a merge sort. When I changed the 35 lines of code to malloc(NULL), I found that the program could still sort the results without reporting an error. Why is this happening?
There is a warning at malloc(NULL) but no error.
int sort(int*a,int n){
int *p=(int *)malloc(NULL);
g_sort(a,0,n-1,p);
return 1;
}
The code can be run to sort the correct result:
#include<bits/stdc++.h>
using namespace std;
void m_qsort(int *a,int left,int mid,int right,int*temp){
int m=mid;int r=right;
int k=0,j=mid+1;;
int l=left;
while(l<=m && j<=r){
if(a[l]<=a[j])
temp[k++]=a[l++];
else
temp[k++]=a[j++];
}
while(l<=mid){
temp[k++]=a[l++];
}
while(j<=r){
temp[k++]=a[j++];
}
for(int i=0;i<k;i++){
a[left+i]=temp[i];
}
}
void g_sort(int *a,int left,int right,int*temp){
if(left<right){
int mid=(left+right)>>1;
g_sort(a,left,mid,temp);
g_sort(a,mid+1,right,temp);
m_qsort(a,left,mid,right,temp);
}
}
int sort(int*a,int n){
int *p=(int *)malloc(NULL);
g_sort(a,0,n-1,p);
return 1;
}
int main()
{
int a[22]={8,4,7,5,6,2,1,7,10,25,0,1,75,52,14,56,33,24,852,20,26,41};
sort(a,22);
for(int i=0;i<22;i++){
cout<<a[i]<<' '<<endl;
}
}
Result:
$g++ -o main *.cpp
main.cpp: In function ‘int sort(int*, int)’:
main.cpp:46:27: warning: passing NULL to non-pointer argument 1 of ‘void* malloc(size_t)’ [-Wconversion-null]
int *p=(int *)malloc(NULL);
^
$main
0
1
1
2
4
5
6
7
7
8
10
14
20
24
25
26
33
41
52
56
75
852
According to this documentation, requesting a 0 size as you did is implementation-defined. Your system's implementation probably returns a non-null pointer, because a null pointer would segfault on most systems (see Scheff's Cat's comment below for why I say "most"). The documentation says not to use this pointer, so you're violating malloc's contract. I take it that your question is for your curiosity.
Maybe it's returning an address within the heap, and your program is buffer-overrunning into adjacent virtual memory addresses that were allocated to your process. You may be able to use heap analysis tools to confirm this. This StackOverflow question has answers with some heap analysis tools.

OpenMP GPU offload; Map scalar

I am trying to understand/test OpenMP with GPU offload. However, I am confused because some examples/info (1, 2, 3) in the internet are analogous or similar to mine but my example does not work as I think it should. I am using g++ 9.4 on Ubuntu 20.04 LTS and also installed gcc-9-offload-nvptx.
My example that does not work but is similar to this one:
#include <iostream>
#include <vector>
int main(int argc, char *argv[]) {
typedef double myfloat;
if (argc != 2) exit(1);
size_t size = atoi(argv[1]);
printf("Size: %zu\n", size);
std::vector<myfloat> data_1(size, 2);
myfloat *data1_ptr = data_1.data();
myfloat sum = -1;
#pragma omp target map(tofrom:sum) map(from: data1_ptr[0:size])
#pragma omp teams distribute parallel for simd reduction(+:sum) collapse(2)
for (size_t i = 0; i < size; ++i) {
for (size_t j = 0; j < size; ++j) {
myfloat term1 = data1_ptr[i] * i;
sum += term1 / (1 + term1 * term1 * term1);
}
}
printf("sum: %.2f\n", sum);
return 0;
}
When I compile it with: g++ main.cpp -o test -fopenmp -fcf-protection=none -fno-stack-protector I get the following
stack_example.cpp: In function ‘main._omp_fn.0.hsa.0’:
cc1plus: warning: could not emit HSAIL for the function [-Whsa]
cc1plus: note: support for HSA does not implement non-gridified OpenMP parallel constructs.
It does compile but when using it with
./test 10000
the printed sum is still -1. I think the sum value passed to the GPU was not returned properly but I explicitly map it, so shouldn't it be returned? Or what am I doing wrong?
EDIT 1
I was ask to modify my code because there was a historically grown redundant for loop and also sum was initialized with -1. I fixed that and also compiled it with gcc-11 which did not throw a warning or note as did gcc-9. However the behavior is similar:
Size: 100
Number of devices: 2
sum: 0.00
I checked with nvtop, the GPU is used. Because there are two GPUs I can even switch the device and can be seen by nvtop.
Solution:
The fix is very easy and stupid. Changing
map(from: data1_ptr[0:size])
to
map(tofrom: data1_ptr[0:size])
did the trick.
Even though I am not writing to the array this seemed to be the problem.

Segmentation fault while submitting code snippet in online compiler, even if it works in local machine

I was implemeting a graph theory question in Cpp using STL. While compiling the following code snippet in my local machine, I am not getting any compile time error, even with compiling using the following flags:
-Wall -Wextra -pedantic -std=c++11 -O2 -Wshadow -Wformat=2 -Wfloat-equal -Wconversion -Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fstack-protector
But when I am submitting the code to the following question: https://practice.geeksforgeeks.org/problems/count-the-paths/0 I am getting segmentation fault. Below is the code snippet, if you find any error, please point out.
#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define MAX 10e4
using namespace std;
vector<vector<int>> v(MAX);
vector<bool> check(MAX);
int path;
void dfs(int s, int d) {
for (int i: v[s]) {
if (i == d) {
path++;
continue;
}
if (!check[i]) {
dfs(i, d);
}
}
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--) {
int n, e;
cin >> n >> e;
int a, b;
for (int i=0; i<e; i++) {
cin >> a >> b;
v[a].push_back(b);
}
int source, destination;
cin >> source >> destination;
check[source] = true;
dfs(source, destination);
cout << path << endl;
}
return 0;
}
Your code has several errors, I've removed them all and run the code. It compiled fine and work properly on provided input. But there are some problems with your implementation style and also with problem. To understand what is wrong with your code(actually, its not only your code's fault, the problem is also wrong), let me explain first why the problem is wrong:
Statement:
Given a directed graph, a source vertex ‘s’ and a destination vertex ‘d’, print the count of all paths from given ‘s’ to ‘d’.
Input:
First line consists of T test cases. First line of every test case consists of V and E, denoting the vertices and edges. Second line of every test case consists of 2*E spaced integers denoting the edge between vertices. Third line of every test case consists of S and D.
Output:
Single line output, print the count of all paths from 's' to 'd'.
It seems ok at first, but see, there's not talk about cycle. If there's any cycle, then, this problem could have infinite answer.
Now, examine the input:
1
4 6
0 1
0 2 // note this
0 3
2 0 // note this
2 1
1 3
2 3
The above (note this) lines shows two edges, those create a cycle. but, your code still works, why? cause, your code makes check[source] = true. But what if the cycle does not include source but other vertices...then, this code will lead to stackoverflow and sometimes stackoverflow raises SIGSEGV (segmentation violation) signal.
This problem can still be solved with some work around, but it'll be solving a wrong problem with wrong rules and wrong understanding(this happens sometime in problem solving and competitive programming). So, I didn't try that.
[P.S.]: competitive programming or sport programming is not bad at all. its actually quite effective to learn ds and algo. but choose better sites like topcoder, codeforces, codechef, hackerrank, leetcode, atcoder, uva, lightoj and the list goes on...but those i've noted are actually quite good.

an error occur when running a c++ script in cygwin

I tryed to run the following code in my cygwin
#include<iostream>
#include<cstdio>
using namespace std;
const int NR=2005;
int n,m;
bool arr[NR][NR];
int mx_jx(int x){
int up[NR][NR],lf[NR][NR],rt[NR][NR];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
up[i][j]=1,lf[i][j]=rt[i][j]=j;
for(int i=1;i<=n;i++)
for(int j=2;j<=m;j++)
if(arr[i][j-1]==x)lf[i][j]=lf[i][j-1];
for(int i=1;i<=n;i++)
for(int j=m-1;j>=1;j--)
if(arr[i][j+1]==x)rt[i][j]=rt[i][j+1];
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(arr[i][j]!=x)continue;
if(i>1 && arr[i-1][j]==x){
up[i][j]=arr[i][j-1]+1;
lf[i][j]=max(lf[i][j],lf[i-1][j]);
rt[i][j]=min(rt[i][j],rt[i-1][j]);
}
ans=max(ans,(rt[i][j]-lf[i][j]+1)*up[i][j]);
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int tmp;
scanf("%d",&tmp);
arr[i][j]=(int)tmp;
if((i+j)&1)arr[i][j]=!arr[i][j];
}
printf("%d",max(mx_jx(0),mx_jx(1)));
return 0;
}
It passed the compile(0 warning,0 error), but when I tried to run it with the following input
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
It says "Command terminated"
these code could run correctly on other platform, how can I solve this problem on cygwin? thanks a lot
While the answer from user3684240 is valid and it is definitely an issue with your code, more likely you have Stack Overflow due to allocating numerous huge arrays on stack and in global memory area.
You should use std::vector<std::vector<int> instead of plain C arrays.
std::vector<std::vector<int>> up(NR, std::vector<int>(NR, 0));
std::vector<std::vector<int>> lf(NR, std::vector<int>(NR, 0));
std::vector<std::vector<int>> rt(NR, std::vector<int>(NR, 0));
It is not very well optimized, but it's simplest solution I can provide.
For that bool array though, std::vector might behave... strange. I cannot give 100% guarantee that it will work if you simply substitute bool[][] with std::vector<std::vector<bool>> without testing it properly, because std::vector<bool> is optimized for memory and it has certain quirks that one should be aware of when using it.
You can try and see if that array of bools in global memory works (after changing arrays in mx_jx to vectors), maybe it does and you don't have to change it. If it doesn't, you can try to change to vector of vectors, then it should work.
The mistake is in that line:
scanf("%d", &arr[i][j]);
%d reads ints, but your array is of type bool. This leads to a memory error.
An easy way to fix it would be:
int read_value;
scanf("%d", &read_value);
arr[i][j] = read_value;
As an additional hint: If you enable compiler warnings (-Wall -Wextra -pedantic), the compiler will tell you about those kinds of mistakes.

my c++ random number is not random

I am running this
#include <boost/mpi.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <time.h>
namespace mpi = boost::mpi;
int main()
{
mpi::environment env;
mpi::communicator world;
srand (time(NULL));
std::srand(time(0) + world.rank());
int my_number = std::rand();
if (world.rank() == 0) {
std::vector<int> all_numbers;
gather(world, my_number, all_numbers, 0);
for (int proc = 0; proc < world.size(); ++proc)
std::cout << "Process #" << proc << " thought of "
<< all_numbers[proc] << std::endl;
} else {
gather(world, my_number, 0);
}
return 0;
}
to distributively generate random number, however, it gives me the number around the same magnitude everytime....
dhcp-18-189-66-216:ising2 myname$ make
mpic++ -I/usr/local/include/boost -L/usr/local/lib -lboost_mpi -lboost_serialization main.cpp -o main
mpirun -n 4 main
Process #0 thought of 238772362
Process #1 thought of 238789169
Process #2 thought of 238805976
Process #3 thought of 238822783
dhcp-18-189-66-216:ising2 myname$ make
mpic++ -I/usr/local/include/boost -L/usr/local/lib -lboost_mpi -lboost_serialization main.cpp -o main
mpirun -n 4 main
Process #0 thought of 238805976
Process #1 thought of 238822783
Process #2 thought of 238839590
Process #3 thought of 238856397
dhcp-18-189-66-216:ising2 myname$ make
mpic++ -I/usr/local/include/boost -L/usr/local/lib -lboost_mpi -lboost_serialization main.cpp -o main
mpirun -n 4 main
Process #0 thought of 238856397
Process #1 thought of 238873204
Process #2 thought of 238890011
Process #3 thought of 238906818
dhcp-18-189-66-216:ising2 myname$
In the website, http://www.boost.org/doc/libs/1_55_0/doc/html/mpi/tutorial.html , others said they get:
Process #0 thought of 332199874
Process #1 thought of 20145617
Process #2 thought of 1862420122
Process #3 thought of 480422940
Process #4 thought of 1253380219
Process #5 thought of 949458815
Process #6 thought of 650073868
I am very confused.... Any help? Thank you.
Your problem is the rand() function of the cstdlib. It is not a good random number generator. If you want to use proper random numbers in C++, use some from the header from C++11 or external random number generators (e.g. mersenne twister).
But nonetheless, using random numbers in for parallel programs is no easy task. You should use random number generators, which are specialised on that (e.g. r250_omp.h).
The problem is likely to be caused by your rand. See the discussion and answers for this question: First random number is always smaller than rest
It seems that the generated numbers for neighboring seeds (your case) can be quite heavily correlated. rand's implementations might vary, and for some implementations it seems to be a much more pronounced phenomena.
I think your random gen should be like this:
int max=100, min=0;
srand(time(NULL));
int random = (rand() % (max-min)) + min;