Reputation: 173
This is not a problem with programming contest but with the language C++.
There is an old programming problem on codeforces. The solution is with C++. I already solved in Python but I don't understand this behavior of C++. In my computer and on onlinegdb's C++ compiler, I get expected output but on codeforces judge, I get a different output.
If interested in the problem : http://codeforces.com/contest/8/problem/A It's very simple and a small read. Though Reading it is not required for the question.
Task in Short:
Print("forward") if string a
is found in string s
and string b
is also found in s
Print("backward") if string a
is found in reverse of string s
and string b
is also found in reverse of s
Print("both") if both of above are true
Print("fantasy") if both of above are false
#include<bits/stdc++.h>
using namespace std;
#define int long long
//initializing all vars because blogs said uninitialized vars sometimes give unexpected result
string s="", a="", b="";
bool fw = false;
bool bw = false;
string now="";
string won="";
int pa=-1, pb=-1, ra=-1, rb=-1;
signed main()
{
//following 2 lines can be ignored
ios_base::sync_with_stdio(false);
cin.tie(NULL);
//taking main input string s and then two strings we need to find in s are a & b
cin >> s >> a >> b;
//need reverse string of s to solve the problem
string r = s;
reverse(r.begin(), r.end());
//pa is index of a if a is found in s else pa = -1 if not found
pa = s.find(a);
//if a was a substring of s
if (pa != -1) {
//now is substring of s from the next letter where string a was found i.e. we remove the prefix of string till last letter of a
now = s.substr(pa + a.size(), s.size() - (pa + a.size()));
//pb stores index of b in remaining part s i.e. now
pb = now.find(b);
//if b is also in now then fw is true
if (pb != -1) {
fw = true;
}
}
//same thing done for the reverse of string s i.e. finding if a and b exist in reverse of s
ra = r.find(a);
if (ra != -1) {
won = r.substr(ra + a.size(), r.size() - (ra + a.size()));
rb = won.find(b);
if (rb != -1) {
bw = true;
}
}
if (fw && bw) {
cout << "both" << endl;
}
else if (fw && !bw) {
cout << "forward" << endl;
}
else if (!fw && bw) {
cout << "backward" << endl;
}
else {
cout << "fantasy" << endl;
}
return 0;
}
For input
atob
a
b
s="atob", a="a", b="b"
Here reverse of atob
is bota
.
a
is in atob
.
So, string now
= tob
.
b
is in tob
so fw
is true
.
Now a
is in bota
.
So, string won
= ""
(empty because nothing after a
). So, b
is not in won
.
So, rw
is false
.
Here answer is to print forward
and in C++14 on my PC and onlinegdb, the output is forward
but on codeforces judge, it's both
.
I did many variations of the code but no result.
Finally I observed that if I run my program on PC and don't give any input and terminate the program in terminal with Ctrl-C, it prints both
which is strange as both should only be printed when both fw
and rw
are true.
What is this behavior of C++?
Upvotes: 0
Views: 183
Reputation: 92
The above answer and comments are way more enough information for your question. I cannot comment yet so I would like to add a simplified answer here, as I'm also learning myself.
From the different outputs on different compilers you can trackback the logic and found the flow of code is differ in this line:
if (rb != -1) {
Simply adding a log before that line, or using a debugger:
cout << "rb:" << rb << endl;
You can see that on your PC: rb:-1
But on codeforces: rb:4294967295
won.find(b) return npos, which mean you have an assignment: rb = npos;
This is my speculation, but a possible scenario is:
On your PC, rb is compiled as int (keyword), which cannot hold 4294967295, and assigned to -1.
But on codeforces, rb is compiled as long long, follow the definition, and 4294967295 was assigned instead.
Because you redefine the keyword int, which is advised again by standard of C++ programming language, different compiler will treat this line of code differently.
Upvotes: 1
Reputation: 67733
Let's dissect this code and see what problems we can find. It kind of tips over into a code review, but there are multiple problems in addition to the proximate cause of failure.
#include<bits/stdc++.h>
Never do this. If you see it in an example, you know it's a bad example to follow.
using namespace std;
Fine, we're not in a header and brevity in sample code is a reasonable goal.
#define int long long
Oh no, why would anyone ever do this? The first issue is that preprocessor replacement is anyway prohibited from replacing keywords (like int
).
Even without that prohibition, this later line
int pa=-1, pb=-1, ra=-1, rb=-1;
is now a deliberate lie, as if you're obfuscating the code. It would have cost nothing to just write long long pa ...
if that's what you meant, and it wouldn't be deceptive.
//initializing all vars because blogs said uninitialized vars sometimes give unexpected result
string s="", a="", b="";
But std::string
is a class type with a default constructor, so it can't be uninitialized (it will be default-initialized, which is fine, and writing =""
is just extra noise).
The blogs are warning you about default initialization of non-class types (which leaves them with indeterminate values), so
bool fw = false;
is still sensible.
NB. these are globals, which are anyway zero-initialized (cf).
signed main()
Here are the acceptable faces of main
- you should never type anything else, on pain of Undefined Behaviour
int main() { ... }
int main(int argc, char *argv[]) { ... }
Next, these string positions are both (potentially) the wrong type, and compared to the wrong value:
ra = r.find(a);
if (ra != -1) {
could just be
auto ra = r.find(a);
if (ra != std::string::npos) {
(you could write std::string::size_type
instead of auto
, but I don't see much benefit here - either way, the interface, return type and return values of std::string::find
are well-documented).
The only remaining objection is that none of now
, won
or the trailing substring searches correspond to anything in your problem statement.
Upvotes: 4