cin is not taking in the last input in a while loop - c++

In the following code segment, the cin inside the while loop, which is nested inside the while loop in the main function, is somehow not working during the last input (i.e, when h == n-1) and reporting a segmentation fault instead.
I figured this out by using the print statements (which are commented in the code below), one at the start of the inner while loop, one after the cin statement (to find the read values of v and x decremented by 1) and one outside the while loop. The third cout statement doesn't execute, from which I concluded that the segmentation fault is inside the while loop.
Moreover, in the last iteration of the inner while loop, the cout statement after the cin statement (to print the values of v and x) also didn't execute. And so, I think that the cin inside the inner while loop isn't working in the last iteration.
I tried searching a lot and put in the cin.clear() and cin.ignore(numeric_limits<streamsize>::max(), '\n'); statements but still no use!
Why is there such an issue?
#include <bits/stdc++.h>
using namespace std;
vector <vector<int>> adj;
vector<unordered_set <int>> leaf;
int process(int node, int *pans, int k){
*pans = *pans + (leaf[node].size() / k) * k;
int temp = (leaf[node].size() / k) * k;
if(temp == 0) return 0;
for(auto it : leaf[node]){
if(temp == 0) break;
leaf[node].erase(it);
auto j = find(adj[node].begin(), adj[node].end(), it);
adj[node].erase(j);
temp --;
}
if(adj[node].size() == 1){
leaf[adj[node][0]].insert(node);
process(adj[node][0], pans, k);
}
return 0;
}
int main(){
int t, v, x, n, k;
cin>>t;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
while(t--){
int ans = 0;
cin>>n>>k;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
adj.resize(n);
int h = 1;
while(h < n){
// cout<<"r";
cin>>v>>x;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
v --; x --;
cout<<v<<" "<<x<<"\n";
adj[v].push_back(x);
adj[x].push_back(v);
h++;
}
// cout<<"out";
leaf.resize(n);
for(int i = 0; i < n; i ++){
if(adj[i].size() == 1) leaf[adj[i][0]].insert(i);
}
for(int i = 0; i < n; i ++){
if(leaf[i].size() >= k) process(i, &ans, k);
}
cout<<ans<<"\n";
adj.clear();
leaf.clear();
}
}
Following is an example of the input:
1
8 3
1 2
1 5
7 6
6 8
3 1
6 4
6 1

The error is here
for(auto it : leaf[node]){
if(temp == 0) break;
leaf[node].erase(it);
auto j = find(adj[node].begin(), adj[node].end(), it);
adj[node].erase(j);
temp --;
}
By modifying the unordered_set leaf[node].erase(it); you are invalidating the implicit iterator used by the range based for loop. Rewrite your loop with an explciit iterator so you can account for the iterator invalidation. Like this
for (auto i = leaf[node].begin(); i != leaf[node].end(); ) {
if(temp == 0) break;
auto it = *i;
i = leaf[node].erase(i);
auto j = find(adj[node].begin(), adj[node].end(), it);
adj[node].erase(j);
temp --;
}
With this loop your code runs to completion (at least for me). I've no idea if the output is correct or not.

Related

Unıque Random Number Check form Array c++

#include <iostream>
#include<ctime>
#include<cstdlib>
#include<string>
#include<cmath>
using namespace std;
int main()
{
bool cont = false;
string str;
int num, num2;
cin >> str >> num;
int arr[10];
int a = pow(10, num);
int b = pow(10, (num - 1));
srand(static_cast<int>(time(NULL)));
do {
num2 = rand() % (a - b) + b;
int r;
int i = 0;
int cpy = num2;
while (cpy != 0) {
r = cpy % 10;
arr[i] = r;
i++;
cpy = cpy / 10;
}
for (int m = 0; m < num; m++)
{
for (int j = 0; j < m; j++) {
if (m != j) {
if (arr[m] == arr[j]) {
break;
}
else {
cont = true;
}
}
}
}
cout << num2 << endl;
} while (!cont);
return 0;
}
I want to take a number from the user and produce such a random number.
For example, if the user entered 8, an 8-digit random number.This number must be unique, so each number must be different from each other,for example:
user enter 5
random number=11225(invalid so take new number)
random number =12345(valid so output)
To do this, I divided the number into its digits and threw it into the array and checked whether it was unique. The Program takes random numbers from the user and throws them into the array.It's all right until this part.But my function to check if this number is unique using the for loop does not work.
Because you need your digits to be unique, it's easier to guarantee the uniqueness up front and then mix it around. The problem-solving principle at play here is to start where you are the most constrained. For you, it's repeating digits, so we ensure that will never happen. It's a lot easier than verifying if we did or not.
This code example will print the unique number to the screen. If you need to actually store it in an int, then there's extra work to be done.
#include <algorithm>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>
int main() {
std::vector<int> digits(10);
std::iota(digits.begin(), digits.end(), 0);
std::shuffle(digits.begin(), digits.end(), std::mt19937(std::random_device{}()));
int x;
std::cout << "Number: ";
std::cin >> x;
for (auto it = digits.begin(); it != digits.begin() + x; ++it) {
std::cout << *it;
}
std::cout << '\n';
}
A few sample runs:
Number: 7
6253079
Number: 3
893
Number: 6
170352
The vector digits holds the digits 0-9, each only appearing once. I then shuffle them around. And based on the number that's input by the user, I then print the first x single digits.
The one downside to this code is that it's possible for 0 to be the first digit, and that may or may not fit in with your rules. If it doesn't, you'd be restricted to a 9-digit number, and the starting value in std::iota would be 1.
First I'm going to recommend you make better choices in naming your variables. You do this:
bool cont = false;
string str;
int num, num2;
cin >> str >> num;
What are num and num2? Give them better names. Why are you cin >> str? I can't even see how you're using it later. But I presume that num is the number of digits you want.
It's also not at all clear what you're using a and b for. Now, I presume this next bit of code is an attempt to create a number. If you're going to blindly try and then when done, see if it's okay, why are you making this so complicated. Instead of this:
num2 = rand() % (a - b) + b;
int r;
int i = 0;
int cpy = num2;
while (cpy != 0) {
r = cpy % 10;
arr[i] = r;
i++;
cpy = cpy / 10;
}
You can do this:
for(int index = 0; index < numberOfDesiredDigits; ++index) {
arr[index] = rand() % 10;
}
I'm not sure why you went for so much more complicated.
I think this is your code where you validate:
// So you iterate the entire array
for (int m = 0; m < num; m++)
{
// And then you check all the values less than the current spot.
for (int j = 0; j < m; j++) {
// This if not needed as j is always less than m.
if (m != j) {
// This if-else is flawed
if (arr[m] == arr[j]) {
break;
}
else {
cont = true;
}
}
}
}
You're trying to make sure you have no duplicates. You're setting cont == true if the first and second digit are different, and you're breaking as soon as you find a dup. I think you need to rethink that.
bool areAllUnique = true;
for (int m = 1; allAreUnique && m < num; m++) {
for (int j = 0; allAreUnique && j < m; ++j) {
allAreUnique = arr[m] != arr[j];
}
}
As soon as we encounter a duplicate, allAreUnique becomes false and we break out of both for-loops.
Then you can check it.
Note that I also start the first loop at 1 instead of 0. There's no reason to start the outer loop at 0, because then the inner loop becomes a no-op.
A better way is to keep a set of valid digits -- initialized with 1 to 10. Then grab a random number within the size of the set and grabbing the n'th digit from the set and remove it from the set. You'll get a valid result the first time.

Getting SIGSEGV (segmentation error) for the given problem. (Finding LCA of a generic tree)

So, I was trying to solve the below problem using the most basic method i.e. storing the paths and finding LCA.
My code is working fine on VSCode and giving the right output. But when submitting on SPOJ, it gives runtime error (SIGSEGV).
Problem Link: https://www.spoj.com/problems/LCA/
Problem Description:
A tree is an undirected graph in which any two vertices are connected by exactly one simple path. In other words, any connected graph without cycles is a tree. - Wikipedia
The lowest common ancestor (LCA) is a concept in graph theory and computer science. Let T be a rooted tree with N nodes. The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself). - Wikipedia
Your task in this problem is to find the LCA of any two given nodes v and w in a given tree T.
Sample Input:
1
7
3 2 3 4
0
3 5 6 7
0
0
0
0
2
5 7
2 7
Sample Output:
Case 1:
3
1
My Code:
#include <iostream>
#include <vector>
#include <cmath>
#include <cstring>
using namespace std;
vector<vector<int>> edges;
bool storepath(int s, int d, vector<int>& path, vector<bool>& visited) {
if(s == d)
{
path.push_back(d);
return true;
}
else if(edges[s].size() == 1) {
if(s != d)
{
for(int i = 0; i < path.size(); i++)
if(path[i] == s) {
path.erase(path.begin() + i);
}
}
return false;
}
visited[s] = true;
path.push_back(s);
for(auto e: edges[s])
{
if(visited[e] == false)
{
bool ans = storepath(e, d, path, visited);
if(ans)
break;
}
}
}
int LCA(int a, int b)
{
if(a == b)
return a;
vector<int> path1, path2;
vector<bool> visited(edges.size(), false);
storepath(1, a, path1, visited);
visited.assign(edges.size(), false);
storepath(1, b, path2, visited);
int n = path1.size();
int m = path2.size();
int i = 0,j = 0;
while(i < n && j < m && path1[i] == path2[j]) {
i++;
j++;
}
return path1[i-1];
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin >> t;
int Case = 1;
while(t--)
{
int n;
cin >> n;
edges.resize(n+1);
for(int i = 1; i <= n; i++)
{
int size, val;
cin >> size;
while(size--)
{
cin >> val;
edges[i].push_back(val);
edges[val].push_back(i);
}
}
int q;
cin >> q;
cout << "Case "<< Case << ":" << endl;
while(q--)
{
int a, b;
cin >> a >> b;
cout << LCA(a, b) << endl;
}
Case++;
edges.clear(); //added after igor's comment (forgot to add before but used while submitting)
}
return 0;
}
I think I'm not accessing any out of scope element so SIGSEGV should not occur.
Please tell me how can I fix and improve my code.
Some bugs are easy to find, when you know how to find them. The tools every programmer should know about are valgrind and -fsanitize. Remember to always compile with warnings enabled and fix them. Compiling your code with:
g++ -Wall -Wextra -fsanitize=undefined 1.cpp && ./a.out </tmp/2
results in a helpful warning:
1.cpp:38:1: warning: control reaches end of non-void function [-Wreturn-type]
38 | }
| ^
and a runtime error:
1.cpp:9:6: runtime error: execution reached the end of a value-returning function without returning a value
Your storepath doesn't return value.

Stuck in the following dp code

I wrote the following dp code for finding the prime factors of a number.
#include <bits/stdc++.h>
#define max 1000001
using namespace std;
vector <int> prime;
vector<bool> isprime(max,true);
vector<bool> visited(max,false);
vector<int> data(max,-1);
void dp(int n,int last)
{
if(n >= max || visited[n])
return;
visited[n] = true;
for(int i = last;i<prime.size();i++)
{
if(n*prime[i] >= max || data[n*prime[i]] != -1)
return;
data[n*prime[i]] = prime[i];
dp(n*prime[i],i);
}
}
int main()
{
isprime[1] = false;
data[1] = 1;
for(int i = 4;i<max;i += 2)
isprime[i] = false;
for(int i = 3; i*i< max;i += 2)
{
for(int j = i*i; j < max;j += i)
isprime[j] = false;
}
prime.push_back(2);
data[2] = 2;
for(int i =3;i<max;i += 2)
if(isprime[i])
{
prime.push_back(i);
data[i] = i;
}
for(int i = 0;i<prime.size();i++)
{
dp(prime[i],i);
}
cout<<"...1\n";
for(int i = 2;i<=8000;i++)
{
cout<<i<<" :- ";
int temp = i;
while(temp!= 1)
{
cout<<data[temp]<<" ";
temp = temp/data[temp];
}
cout<<endl;
}
return 0;
}
Here, last is the last index of prime number n.
But I am getting segmentation fault for this, when I change max to 10001, it runs perfectly. I'm not getting why is this happening since the data-structures used are 1-d vectors which can hold values up to 10^6 easily.
I checked your program out using GDB. The segfault is taking place at this line:
if(n*prime[i] >= max || data[n*prime[i]] != -1)
In your first ever call to DP in your for loop, where you call dp(2,0), the recursive calls eventually generate this call: dp(92692,2585).
92692 * 2585 = 239608820
This number is larger than a 32 bit integer can hold, so the r-value generated by the integer multiplication of those two numbers overflows and becomes negative. nprime[i] becomes negative, so your first condition of the above loop fails, and the second is checked. data[n * prime[i]] is accessed, and since n*prime[i] is negative, your program accesses invalid memory and segfaults. To fix this, simply change n to a long long in your parameter list and you should be fine.
void dp(long long n, int last)

Finding Longest Increasing Sub Sequence in a round table of numbers

I was recently working on the following problem.
http://www.codechef.com/problems/D2
The Chef is planning a buffet for the DirectiPlex inauguration party, and everyone is invited. On their way in, each guest picks up a sheet of paper containing a random number (this number may be repeated). The guests then sit down on a round table with their friends.
The Chef now decides that he would like to play a game. He asks you to pick a random person from your table and have them read their number out loud. Then, moving clockwise around the table, each person will read out their number. The goal is to find that set of numbers which forms an increasing subsequence. All people owning these numbers will be eligible for a lucky draw! One of the software developers is very excited about this prospect, and wants to maximize the number of people who are eligible for the lucky draw. So, he decides to write a program that decides who should read their number first so as to maximize the number of people that are eligible for the lucky draw. Can you beat him to it?
Input
The first line contains t, the number of test cases (about 15). Then t test cases follow. Each test case consists of two lines:
The first line contains a number N, the number of guests invited to the party.
The second line contains N numbers a1, a2, ..., an separated by spaces, which are the numbers written on the sheets of paper in clockwise order.
Output
For each test case, print a line containing a single number which is the maximum number of guests that can be eligible for participating the the lucky draw.
Constraints
1 ≤ N ≤ 10000
You may assume that each number number on the sheet of paper; ai is randomly generated, i.e. can be with equal probability any number from an interval [0,U], where U is some upper bound (1 ≤ U ≤ 106).
Example
Input:
3
2
0 0
3
3 2 1
6
4 8 6 1 5 2
Output:
1
2
4
On checking the solutions I found this code:
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
#define LIMIT 37
using namespace std;
struct node {
int val;
int index;
};
int N;
int binary(int number, vector<int>& ans) {
int start = 0;
int n = ans.size();
int end = n - 1;
int mid;
if (start == end)
return 0;
while (start != end) {
mid = (start + end) / 2;
if (ans[mid] == number)
break;
if (ans[mid] > number)
end = mid;
else
start = mid + 1;
}
mid = (start + end) / 2;
return mid;
}
void display(vector<int>& list) {
cout << endl;
for (int i = 0; i < list.size(); i++)
cout << list[i] << " ";
cout << endl;
}
int maxsubsequence(vector<int>& list) {
vector<int> ans;
int N = list.size();
ans.push_back(list[0]);
int i;
// display(list);
for (i = 1; i < N; i++) {
int index = binary(list[i], ans);
/*if(index+1<ans.size())
continue;*/
if (list[i] < ans[index])
ans[index] = list[i];
if (list[i] > ans[index])
ans.push_back(list[i]);
// display(ans);
}
return ans.size();
}
int compute(int index, int* g) {
vector<int> list;
list.push_back(g[index]);
int itr = (index + 1) % N;
while (itr != index) {
list.push_back(g[itr]);
itr = (itr + 1) % N;
}
return maxsubsequence(list);
}
int solve(int* g, vector<node> list) {
int i;
int ret = 1;
for (i = 0; i < min(LIMIT, (int)list.size()); i++) {
// cout<<list[i].index<<endl;
ret = max(ret, compute(list[i].index, g));
}
return ret;
}
bool cmp(const node& o1, const node& o2)
{ return (o1.val < o2.val); }
int g[10001];
int main() {
int t;
cin >> t;
while (t--) {
cin >> N;
vector<node> list;
int i;
for (i = 0; i < N; i++) {
node temp;
cin >> g[i];
temp.val = g[i];
temp.index = i;
list.push_back(temp);
}
sort(list.begin(), list.end(), cmp);
cout << solve(g, list) << endl;
}
return 0;
}
Can someone explain this to me. I am well aware of calculating LIS in nlog(n).
What I am not able to understand is this part:
int ret = 1;
for (i = 0; i < min(LIMIT, (int)list.size()); i++) {
// cout<<list[i].index<<endl;
ret = max(ret, compute(list[i].index, g));
}
and the reason behind sorting
sort(list.begin(),list.end(),cmp);
This algorithm is simply guessing at the starting point and computing the LIS for each of these guesses.
The first value in a LIS is likely to be a small number, so this algorithm simply tries the LIMIT smallest values as potential starting points.
The sort function is used to identify the smallest values.
The for loop is used to check each starting point in turn.
WARNING
Note that this algorithm may fail for certain inputs. For example, consider the sequence
0,1,2,..,49,9900,9901,...,99999,50,51,52,...,9899
The algorithm will try just the first 37 starting points and miss the best starting point at 50.
You can test this by changing the code to:
int main() {
int t;
t=1;
while (t--) {
N=10000;
vector<node> list;
int i;
for (i = 0; i < N; i++) {
node temp;
if (i<50)
g[i]=i;
else if (i<150)
g[i]=9999-150+i;
else
g[i]=i-100;
temp.val = g[i];
temp.index = i;
list.push_back(temp);
}
sort(list.begin(), list.end(), cmp);
cout << solve(g, list) << endl;
}
return 0;
}
This will generate different answers depending on whether LIMIT is 37 or 370.
In practice, for randomly generated sequences it will have a good chance of working (although I don't know how to compute the probability exactly).

Appending vectors. Result won't print

I'm trying to enter integers for a and b and then print those integers put together. For example, entering 1 2 3 4 for a and 4 3 2 1 for b would yield: 1 2 3 4 4 3 2 1. I don't understand why my program isn't printing this. Whenever I enter -1, nothing happens. Am I doing the process wrong while the program is running? Help is appreciated.
#include <iostream>
#include <vector>
using namespace std;
vector<int> append(vector<int> a, vector<int> b)
{
int n = a.size();
int m = b.size();
vector<int> c(n + m);
int i;
for (i = 0; i < n; i++)
c[i] = a[i];
for (i = 0; i < m; i++)
c[n + i] = b[i];
return c;
}
main()
{
vector<int>a, b, c;
int temp;
cin >> temp;
while (temp != -1) {
a.push_back(temp);
cin >> temp;
}
cin >> temp;
while (!cin.eof()) {
b.push_back(temp);
cin >> temp;
}
c = append(a, b);
for (int i = 0; i < c.size(); i++)
cout << c[i] << " ";
cout << endl;
}
You have two loops, one to input the vector a and another to input b.
Hitting -1 once would terminate only the first loop. The second one is terminated by an eof which you still haven't entered. So either enter an eof (specific to your system) or have the second loop terminate at -1 (in which case you'll need to enter -1 once more).
You say
Whenever I enter -1, nothing happens.
That's because you reach the second cin >> temp statement at that time (just before while.eof() loop). That's when you start inputting values for b vector. You end that loop by entering EOF character in the stream (CTRL+Z on windows, CTRL+D on linux).