Code issues regarding Ambiguous Permutations - c++

Consider this question: Ambiguous Permutation. My code is written in C++11 using G++ 4.7.2
#include<iostream>
#include<vector>
using std::cin;
using std::cout;
using std::vector;
int main()
{
int h;
while((cin >> h) && (h!=0))
{
int num;
bool c=true;
vector<int> arr;
while((cin >> num) && (h!=0))
{
arr.push_back(num);
--h;
}
const auto n = arr.size();
for(int i=0; i!=n; ++i)
{
if(arr[arr[i]-1] != (i+1))
{
c = false;
cout << "Not Ambiguous\n";
break;
}
}
if(c==true)
cout << "Ambiguous\n";
}
return 0;
}
This code works fine as long as I enter every number in a newline. If I start providing inputs separated by white space (for permutation) then the code behaves unexpectedly. It demands an invalid input for the condition while((cin >> num) and exits after one round of input. Any suggestions for removing this issue? I was also wondering if using STL Arrays would be good choice or not. Thanks!

You are taking input incorrectly, specifically here-
while((cin >> num) && (h!=0)) //WRONG!
{
arr.push_back(num);
--h;
}
A clearer (hence bug free) way to do it is-
for (int i = 0; i < h; i++)
{
cin >> num;
arr.push_back(num);
}
For your second question-
I was also wondering if using STL Arrays would be good choice or not.
I would suggest using std::vector here (and for most purposes).

You code has something wrong there.
1. You should use h!=1 when you get the numbers for each permutation, in your current implementation, it is weird, if h =4, you are going to ask for 5 numbers, which does not make sense
2. You can certainly read those numbers for each test case in one line separated by space as follows:
#include<iostream>
#include<vector>
using std::cin;
using std::cout;
using std::vector;
int main()
{
int h;
while((cin>> h) && (h!=0))
{
int num;
bool c=true;
vector<int> arr;
while((cin >> std::skipws >> num) && (h!=1))
{ //^^^^^^^^^^^^^(add this) ^^^^^^^here should be 1 not 0
arr.push_back(num);
--h;
}
const auto n = arr.size();
for(int i=0; i!=n; ++i)
{
if(arr[arr[i]-1] != (i+1))
{
c = false;
cout << "Not Ambiguous\n";
break;
}
}
if(c==true)
cout << "Ambiguous\n";
}
return 0;
}
However, in either cases, your results are not right, it outputs the following:
4
1 4 3 2
Not Ambiguous
5
2 3 4 5 1
Not Ambiguous
1
1
Ambiguous
While the first should be "Ambiguous", you may need to check the logic for checking ambiguity.

Related

The question is about printing digits of two digit number n, I'm encountering a runtime error

Given a two-digit number n, print both the digits of the number.
Input Format:
The first line indicating the number of test cases T.
Next T lines will each contain a single number ni.
Output Format:
T lines each containing two digits of the number ni separated by space.
Constraints
1 <= T <= 100000
10 <= ni <= 99
Error: Runtime Error (SIGSEGV)
I'm not able to pinpoint, where the problem is in the code as it is working fine for a two numbers while it gives the runtime error for 4 or more numbers.
Is there another way of doing this problem other than using for loop twice?
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
int arr[t];
cin>>t;
for(int i=0;i<t;i++)
{
cin>>arr[i];
}
int c;
int b;
for(int i=0;i<t;i++)
{
c=(arr[i]/10);
if(c!=0)
{
b=arr[i]%(c*10);
}
else
{
b=arr[i];
}
cout<<c<<" "<<b<<endl;
}
return 0;
}
Fist, you declare t, but do not initialize it, so it is uninitialized. Trying to use the value leads to undefined behavior.
Second, VLA is not valid C++, see here. You have to use std::vector instead.
Third, you don't need to use an int.
So, you should do:
#include <iostream>
#include <vector>
#include <string>
int main()
{
int t{};
std::cin >> t;
std::vector<std::string> arr(t);
for(int i = 0; i < t; i++)
{
std::cin >> arr[i];
}
for(const auto &i : arr)
{
std::cout << i[0] << ' ' << i[1] << '\n';
}
}

Why this C++ code is not counting properly?

I have written a code in c++ to count zeros. The input have to take as string. The input will be a digit with 1 and 0.
Example:
Input: 1000000001
Output: 8
The answer should be 8 but my code is showing 0. Where is the problem in the code.
Code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
string players;
cin >> players;
int count = 0;
for (int j = 0; j < players.length(); j++)
{
if (players[j] == 0)
{
count++;
}
}
cout << count;
return 0;
}
Please help me to find and solve it.
Thank you.
you need to compare with char not int:
if (players[j] == '0')
if condition for players[j] == 0 is wrong, your input is string type while you are trying to compare with the integer type 0. The correct if check is players[j] == '0'. Using bits/stdc++.h and using namespace std; is a big no in C++.
#include <iostream>
#include <string>
int main()
{
std:: string players;
std:: cin >> players;
int count = 0;
for(const char &player : players)
{
if (player == '0')
{
count += 1;
}
}
std:: cout << count;
return 0;
}
the condition is wrong.
write code like
players[j] == "0"
your condition means that
player[j] == NULL

bad alloc exception when trying to resolve BFS challenge on HackerRank

So i was trying to make the challage: Breadth First Search: Shortest Reach on HackerRank, but i keep getting the bad alloc exception when the tests have great numbers of node/edges. The program works on the first test, so i don't think, it's something wrong with the implementation.
So here is the implementation:
(sorry for the indentation , my first question)
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <limits.h>
using namespace std;
int main() {
//test numbers
int t;
//the cost
int cost = 6;
cin >> t;
//for each test
for (int nt = 0; nt < t; ++nt) {
int n, e;
int snode;
queue <int> *que = new queue<int>();
//read the node/edges
cin >> n >> e;
//distance/visited/parents arrays/adjlist vector
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
vector< vector<int> > adjList(n + 1);
//read into the adjlist, unoriented graph, each edge has 6 weight
for (int ne = 0; ne < e; ++ne) {
int x, y;
cin >> x >> y;
adjList[x].push_back(y);
adjList[y].push_back(x);
}
//read the starting node
cin >> snode;
dist[snode] = 0;
//do actual bfs
que->push(snode);
visited[snode] = true;
while(!que->empty()) {
int c_node = que->front();
que->pop();
for (int i = 0; i < adjList[c_node].size(); ++i) {
if (visited[adjList[c_node].at(i)] == false) {
que->push(adjList[c_node].at(i));
parents[adjList[c_node].at(i)] = c_node;
dist[adjList[c_node].at(i)] = dist[parents[adjList[c_node].at(i)]] + cost;
visited[adjList[c_node].at(i)] == true;
}
}
}
//print at output the distance from the starting node to each other node
//if unreachable, print -1
for (int i = 1; i < n + 1; ++i) {
if (i == snode) {
} else if (dist[i] == 0 && i != snode) {
cout << "-1 ";
} else {
cout << dist[i] << " ";
}
}
cout << "\n";
}
return 0;
}
Am i doing something wrong, i haven't seen anyone else complain on this matter in the discussion section of the site.
How can i avoid the exception to be thrown and from where does it come?
Thank you!
I don't know, exactly, what is the cause of your exception; and I don't know ho to reproduce your problem because depends (I suppose) from the input values. A lot of input values, I suppose.
But I see some weak points (IMHO) of your code, so I try to point your attention to them.
1) you alloc a std::queue in your for cycle
queue <int> *que = new queue<int>();
but you never free it; it's a waste of memory
2) you're using C-style variable-length arrays
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
They aren't valid C++ standard code. I suggest you the use of standard containers (std::vector or std::queue).
3) you're initializing your C-style variable-length arrays with a initializers lists with only an element (-1 or false). I suppose your intention was initialize all n+1 elements with -1 and false. But this syntax initialize only the first element of the array with -1 and false.
If you want to initialize all n+1 element to -1 and false, the solution is (again) use standard containers; by example
std::vector<int> dist(n+1, -1);
std::vector<bool> visited(n+1, false);
std::vector<int> parents(n+1, -1);
4) you access arrays without bounds checking. By example:
cin >> snode;
dist[snode] = 0;
where snode is a int variable; if you insert a negative value, or a value over n, you write dist out of its bounds, devastating the memory. This, I suppose, can explain your "bad alloc exception".
Suggestion: use standard containers (again) instead of C-style array and use at() (that perform bounds checking) instead []; so
cin >> snode;
dist.at(snode) = 0;
5) sorry for my bad English (ok, I'm joking: this isn't one of your weak points; this is one of mine).

How can I improve this algorithm to prevent TLE is SPOJ submission?

I am trying to solve the following problem:
http://www.spoj.pl/problems/TRIP/
I wrote a solution using DP (Dynamic Programming) in C++ (code posted below). But I get TLE (Time Limit Exceeded). How can I optimize my code?
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
string a,b;
vector<string> v;
int dp[85][85];
void filldp()
{
for(int i = 0; i <= a.length(); i++)
dp[i][0] = 0;
for(int i = 0; i <= b.length(); i++)
dp[0][i] = 0;
for(int i = 1; i <= a.length(); i++)
for(int j = 1; j<= b.length(); j++)
if(a[i-1] == b[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
vector<string> fillv(int i, int j)
{
vector<string> returnset;
if(i == 0 || j == 0)
{ returnset.push_back("");
return returnset;
}
if(a[i-1] == b[j-1])
{
vector<string> set1 = fillv(i-1,j-1);
for(int k = 0; k < set1.size(); k++)
{
returnset.push_back(set1[k] + a[i-1]);
}
return returnset;
}
else
{
if(dp[i][j-1] >= dp[i-1][j])
{
vector<string> set1 = fillv(i,j-1);
returnset.insert(returnset.end(), set1.begin(), set1.end());
}
if(dp[i-1][j] >= dp[i][j-1])
{
vector<string> set2 = fillv(i-1,j);
returnset.insert(returnset.end(), set2.begin(), set2.end());
}
return returnset;
}
}
void output()
{
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for(int i = 0; i < v.size(); i++)
cout << v[i] << endl;
cout << endl;
}
int main()
{
int T;
cin >> T;
while(T--)
{
memset(dp,-1,sizeof(dp));
v.clear();
cin >> a >> b;
filldp();
v = fillv(a.length(), b.length());
output();
}
return 0;
}
My guess here is that there is a lot of passing around of data structures which can be avoided but I cannot exactly figure out how.
The first wrong thing you're doing is using cin and cout, which are terribly slow. Never use cin and cout for contest programming! I've gone from TLE to AC just by changing cin/cout to scanf/printf.
You can greatly reduce the time of execution by taking input using fread() or fread_unlocked() (if your program is single-threaded). Locking/Unlocking the input stream just once takes negligible time, so ignore that.
Here is the code:
#include <iostream>
int maxio=1000000;
char buf[maxio], *s = buf + maxio;
inline char getc1(void)
{
if(s >= buf + maxio) { fread_unlocked(buf,sizeof(char),maxio,stdin); s = buf; }
return *(s++);
}
inline int input()
{
char t = getc1();
int n=1,res=0;
while(t!='-' && !isdigit(t)) t=getc1(); if(t=='-')
{
n=-1; t=getc1();
}
while(isdigit(t))
{
res = 10*res + (t&15);
t=getc1();
}
return res*n;
}
This is implemented in C++. In C, you won't need to include iostream, function isdigit() is implicitly available.
You can take input as a stream of chars by calling getc1() and take integer input by calling input().
The whole idea behind using fread() is to take large blocks of input at once. Calling scanf()/printf(), repeatedly takes up valuable time in locking and unlocking streams which is completely redundant in a single-threaded program.
Also make sure that the value of maxio is such that all input can be taken in a few "roundtrips" only (ideally one, in this case). Tweak it as necessary. This technique is highly effective in programming competitions, for gaining an edge over your opponent in terms of time of execution.
Hope this helps!
when you know the max size of the number of answers it's better to use array instead of vector
because it's a lot faster than vector.
("There is at least one such trip, but never more than 1000 different ones")
function fillv wastes a lot of time in the code . because it's get a lot of space in runtime and free it ( because of local space for fillv function) . it's better to use global answer for that.
for input and output to complete "Gandalf the Grey"'s answer , if you like to use cin and cout , it's better to use std::ios::sync_with_stdio(false); ( to speed up your io runtime ) however printf and scanf is much faster than this .

Error-correcting loop in C++, find specific chars in a string and flag as bad input

Here is v1.0 of the binary_to_decimal converter I wrote. I want to make several changes as I keep improving the spec. Classes and pointers will be added as well in the future. Just to keep me fresh and well practiced.
Well, I now want to implement an error-correcting loop that will flag any character that is not a 0 or a 1 and ask for input again.
I have been trying something along the line of this code block that worked with an array.
It might be way off but I think I can tweak it. I am still learning 0_0
I want to add something like this:
while ((cin >> strint).get())
{
cin.clear(); //reset the input
while (cin.get() != '\n') //clear all the way to the newline char
continue; //
cout << "Enter zeroes and/or ones only! \n";
}
Here is the final code without the error-correcting loop:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
const int MAX = 100;
int conv(int z[MAX], int l[MAX], int a);
int main()
{
int zelda[MAX];
int link[MAX];
string strint;
int am;
cout << "Enter a binary number: \n";
(cin >> strint).get(); //add error-correction to only read 0s and 1s.
am = strint.size();
cout << am << " digits entered." << endl;
int i = 0;
int p = 0;
while (i < am)
{
zelda[i] = strint[p] - '0'; //copies the string array elements into the int array; essentially STRING TO INT (the minus FORCES a conversion because it is arithmetic) <---- EXTREMELY CLEVER!
++i;
++p;
}
cout << conv(zelda, link, am);
cin.get();
return 0;
}
int conv(int zelda[MAX], int link[MAX], int length)
{
int sum = 0;
for (int t = 0; t < length; t++)
{
long int h, i;
for (int h = length - 1, i = 0; h >= 0; --h, ++i)
if (zelda[t] == 1)
link[h] = pow(2.0, i);
else
link[h] = 0;
sum += link[t];
}
return sum;
}
thanks guys.
I'm not completely sure of what you're trying to do, but I think what you're wanting is string::find_first_not_of. There's an example included in that link. You could have something like: myString.find_first_not_of("01");
If the return value is string::npos, then there are no characters in the string other than 1 or 0, therefore it's valid. If the return value is anything else, then prompt again for valid input and continue looping until the input's valid.