A Message to everyone regarding debugging the code yourself

Hey there. I hope that everyone reads it in good health.

I want to convey a message regarding the posts that I have been seeing on discuss lately. I find that most of them are generally tagged with help and have doubts regarding a question or simply contains a link which redirects to their solution. It’s not bad to ask questions or doubts but at the same time if that doubt can be solved by oneself then it should be done.

There are hell lot of solutions in the topics that contains a simple mistake which cause them a WA or any other verdict. It is easy to find it at a glance. Well, it may not be the same for others or the one who has asked for help, but this behaviour will simply make them more ignorant to debugging their code and searching for errors.

Debugging a code is an art which everyone should know about. It not only makes us more capable in producing a strong code but also develops a habit to foresee the potential bugs without even causing them. Sometimes, a code might fail on some edge case, debugging, will make us think out of the box for those edge cases.

Some may argue that it is not productive to spend a lot of time in debugging when we can solve some problem or read another concept in that time… It is true that these alternatives will surely help but debugging is equivalently important. Now, regarding the time constraints, one can read the editorial or google the same thing rather than posting here.

Let me tell you what happens when you don’t do the hard work yourself. Suppose you have a code, a simple one and it gives you a WA. Now you post it on discuss and ask for help. Someone replies with the correct solution, say the part that was causing you an error was a comparison with vector.size() and the suggestion was to use (int) vector.size() inplace. You change it and voila! you get AC. It’s more a case that you will simply ignore the reason why that happened or forget it in the future. Now suppose you are asked the same in an interview. It is always necessary to have in depth knowledge of anything and you should know the if buts consequences. In debugging you would have come across the point of comparison and figured it out yourself which would be more benefitial. It may not be the best example but I hope you get the point.

Also, Iknow there are many coders out there on discuss who just come here to debug the codes because they like it. No offense is intended to them.

The whole point is spend more time in debigging and finding a solution yourself through editorial and google, it will be more valuable and you will learn more things. And only if you are not able to progress on your own then show up to discuss. People here are always happy to help.

P.s. I don’t like reading unformatted and poorly written code. It gives me a headache so that’s one more reason why I have made a topic of it.

13 Likes

Word.

2 Likes

+1000000000 :+1: :slight_smile:

I’d add:

  • always debugging locally with debug flags - at minimum, -fsanitize=undefined -fno-sanitize-recover and _GLIBCXX_DEBUG.
  • get in the habit of writing a simple brute-force solution (which nearly everyone does, at some point), and a random testcase generator, and do it in such a way that you can compare the results of your brute-force and optimised approach - here is an example. It is such an absurdly, ludicrously effective technique that I cannot fathom why it’s not absolutely ubiquitous - it almost feels like cheating :slight_smile:
    Using this simple technique (plus a few others), I only got just one (IIRC) WA submission in OCT19A, and that’s because I misread the question XD

Seriously, debugging is a hugely important skill in the real world, and there may not be anyone around to keep doing it for you (or even to give you failing testcases), so get practicing! Stick print statements everywhere (but remember to disable them when you submit!) - verify all your assumptions! Are you even reading in input correctly? Is this simple helper function actually correct? assert aggressively!

6 Likes

Perhaps not as technical as ssjgz, but I also know a few things that helped me get really fast at debugging.

Proper Indentation is a MUST. It is very uncomfortable to read badly indented code, and difficult to spot errors in.

One of the main techniques is to minimise the number of if conditions in your code, and try to keep them simple and easy to read, instead of writing conditions as they come to you.

Wrapping some structures in structs instead of pair or something else also helps, as you can use sensible names for the data, making it much easier to read through the code. Also a data structure wrapped in a struct as you can stress test a different instance without having to rework your struct.

Using vector<int> seq(n) instead of a global array. Not having global arrays allow you to not worry about what the state of the array is, and work each test case seperately. Also vectors and #define _GLIBCXX_DEBUG makes finding errors easier.

Using for(int x : arr) instead of for(int i=0;i<n;i++). Sometimes, when your code gets too nested, the former for loops can be very helpful. Case in point :

Look at your own risk
   for(int i=0;i<n;i++){
       if(ans[i]==-1){
           bool end=0;
           queue<pair<int,int>> tochk;
           vector<int> path[n];
           tochk.push(mp(i,0));
           bool found[n]={0};
           found[i]=1;
           while(!tochk.empty() && !end){
               for(int j=0;j<edgeforward[tochk.front().first].size();j++){
                  if(ansback[edgeforward[tochk.front().first][j]]!=-1 && !found[ansback[edgeforward[tochk.front().first][j]]]){
                    found[ansback[edgeforward[tochk.front().first][j]]]=1; 
                    path[ansback[edgeforward[tochk.front().first][j]]]=path[tochk.front().first];
                    path[ansback[edgeforward[tochk.front().first][j]]].pb(tochk.front().first);
                    path[ansback[edgeforward[tochk.front().first][j]]].pb(edgeforward[tochk.front().first][j]);
                    tochk.push(mp(ansback[edgeforward[tochk.front().first][j]],tochk.front().second + 1));
                 }
                 else if(ansback[edgeforward[tochk.front().first][j]]==-1){
                     ans[tochk.front().first]=edgeforward[tochk.front().first][j];
                     ansback[edgeforward[tochk.front().first][j]]=tochk.front().first;
                     for(int k=0;k<path[tochk.front().first].size();k+=2){  
                      ans[path[tochk.front().first][k]]=path[tochk.front().first][k+1];
                      ansback[path[tochk.front().first][k+1]]=path[tochk.front().first][k];
                     }
                     end=1;
                     break;
                 }
               }

               tochk.pop();
           }
       }
   }

When preparing a helper function, make sure to assert the necessary conditions.
Just today it saved me because a previous function had a bug, and it would be difficult to notice without the assertion.

Function
auto getmin = [&](const vector<int> &seq1, const vector<int> &seq2){
        assert(seq1.size() == seq2.size());
        int n = seq1.size();
        for(int i=0;i<n;i++){
            if(seq1[i]==seq2[i]){
                continue;
            }
            if(seq1[i]<seq2[i]){
                return seq1;
            }
            return seq2;
        }
        return seq1;
    };

Just keep asking yourself yourself what if while writing each part of your code. It will help you find edge cases, without getting a WA on them.

Also, it will be much, much harder to debug a code during a contest if you aren’t sure of your logic’s correctness due to psychological reasons. You should always prove that your solution is correct if necessary.

Also debugging other’s code on codechef is somehow actually good practice, even though 90% of people who ask help write sphagetti code.

3 Likes

:+1:

:+1:

As an addendum to this - if your vector will contain n elements, make its size exactly n, not n + 3 or whatever - the latter is just sloppy, and prevents _GLIBCXX_DEBUG from triggering a runtime error in the case that you make the serious mistake of reading/ writing past the nth element.

Also, another easy and minor tip - get an Editor that supports auto-formatting of code (automatically indenting and stuff) - it’s a small thing, but having an eye-glazing mass of un-indented code just increases the cognitive load and makes it much-less-likely that an error will “leap out at you”.

3 Likes

To be honest, could not possibly agree more. The first thing I do before debugging someone else’s code is to indent it sensibly. Somehow proper indentation is really underrated, especially among beginners for some reason.

Also the time I spend debugging has decreased drastically since I started indenting correctly.

3 Likes