Range-based for loop in C++ - c++

I was trying to solve this problem on LeetCode. My solution involves keeping a hashmap with a key based on Godel's number from the counts of each letter, and if I have conflicts, I just iterate over an array and compare the counts. However I don't know why this code does not work:
class Solution {
typedef vector<string> vs;
const int MAX_ALPHABET = 26;
const int MOD = 10007;
vector<int> primes;
void gen_primes() {
primes.push_back(2);
for (int i=3; primes.size() < 26; i+=2) {
bool isPrime = true;
for (int x : primes)
if (i % x == 0) {
isPrime = false;
break;
}
if (isPrime)
primes.push_back(i);
}
}
int compute(vector<int>& v) {
int ret = 1;
for (int i=0; i<MAX_ALPHABET; i++) {
for (int j=0; j<v[i]; j++)
ret = (ret * primes[i]) % MOD;
}
return ret;
}
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
gen_primes();
unordered_map<int, vector<
pair< vector<int>, vector<string> >
>> hash;
for (string s : strs) {
vector<int> count(MAX_ALPHABET, 0);
for (char c : s)
count[c - 'a']++;
int key = compute(count);
bool inHash = false;
// Here is the problem
for (auto x : hash[key])
if (x.first == count) {
x.second.push_back(s);
inHash = true;
break;
}
// Here ends the problem
if (!inHash) {
hash[key].push_back({count, {s}});
}
}
vector<vs> ret;
for (auto hashGroup : hash) {
// hashGroup = {key, vector< pair<vector<int>, vector<string>> >}
cout << hashGroup.second[0].second.size() << endl;
for (auto anagramGroup: hashGroup.second) {
// anagramGroup = pair<vector<int>, vector<string>>
sort(anagramGroup.second.begin(), anagramGroup.second.end());
ret.push_back(anagramGroup.second);
}
}
return ret;
}
};
But if I replace the for range loop with a normal for loop, it works:
for (int i=0; i<hash[key].size(); i++)
if (hash[key][i].first == count) {
hash[key][i].second.push_back(s);
inHash = true;
break;
}
Is this behavior normal?

The problem is here:
auto x : hash[key]
Here auto x infers to a value, not to a reference. so x is a copy of the element inside vector<pair<vector<int>,vector<string>>>, not a reference to it. Try with:
auto& x : hash[key]
The problem is not the ranged-based loop itself, you can expose the same "faulty" behavior also with normal loop:
for (int i=0; i< hash[key].size(); i++) {
auto value = hash[key][i];
if (value.first == count) {
value.second.push_back(s);
inHash = true;
break;
}
}

Related

Codeforces 519B Using Vectors vs Some Other Container

To solve 519B I created three vectors that each hold different numbers and occurrences of those numbers for each line. These vectors are also sorted.
eg if the line was 1 1 3 2, the vector would store <1, 2>, <2, 1>, <3, 1>
From there, I would compare one pair from one vector with the pair from the next vector to find the missing number.
This passes most test cases until there are a large number of numbers in each line. I actually saw the answer for this question, but it uses a different method to find the answer. However, I would like to know if there is a way to solve the question with "my way." I read online that using maps and other containers could yield a faster result, but I'm skeptical that using another container would really make that big of a difference. Any thoughts?
#include <iostream>
#include <vector>
#include <algorithm>
int has(std::vector<std::pair<int, int>> &error, int i) {
for (int j = 0; j < error.size(); j++) {
if (error[j].first == i) {
return j;
}
}
return -1;
}
std::vector<std::pair<int, int>> generate(int n) {
int temp;
std::vector<std::pair<int, int>> tempVec;
for (int i = 0; i < n; i++) {
std::cin >> temp;
int pos = has(tempVec, temp);
if (pos != -1) {
tempVec[pos].second++;
} else {
tempVec.push_back(std::make_pair(temp, 1));
}
}
return tempVec;
}
bool sortPair(const std::pair<int, int> &a, const std::pair<int, int> &b) {
return a.first < b.first;
}
int main() {
int n, temp;
std::cin >> n;
std::vector<std::pair<int, int>> a = generate(n), b = generate(n - 1), c = generate(n - 2);
std::sort(a.begin(), a.end(), sortPair);
std::sort(b.begin(), b.end(), sortPair);
std::sort(c.begin(), c.end(), sortPair);
bool found = false;
for (int i = 0; i < n - 1; i++) {
if (a[i] != b[i]) {
found = true;
std::cout << a[i].first << std::endl;
break;
}
}
if (!found) {
std::cout << a[n - 1].first << std::endl;
}
bool found2 = false;
for (int i = 0; i < n - 2; i++) {
if (b[i] != c[i]) {
found2 = true;
std::cout << b[i].first << std::endl;
break;
}
}
if (!found2) {
std::cout << b[n - 2].first << std::endl;
}
}

MayI know why this code is not giving any output?

Please help me to solve the query that this code runs infinitely at a particular line.
It does not give any output as at the end of the code I write the code to print the vector. Even after I assign any value to vector "result" manually still it is not giving any output. why is it so?
#include<bits/stdc++.h>
using namespace std;
bool authorize(int strValue, int value, int M)
{
long int newValue = (strValue - (value * 131) % M);
if (newValue >= 48 && newValue <= 57)
return true;
if (newValue > 65 && newValue <= 90)
return true;
if (newValue >= 97 && newValue <= 122)
return true;
return false;
}
int hashingfunct(string str, int M)
{
long int P, F, sum = 0;
int len = str.length();
for (int i = 0; i < len; i++)
{
P = pow(131, len - i - 1);
F = (int)str[i];
sum += (F * P) % M;
}
sum = sum % M;
return sum;
}
int main()
{
int n = 5;
string str1, str2;
vector<vector<string> > events;
for (int i = 0; i < n; i++) {
cin >> str1 >> str2;
vector<string > temp;
temp.push_back(str1);
temp.push_back(str2);
events.push_back(temp);
}
for (int i = 0; i < n; i++) {
cout << events[i][0] << events[i][1];
}
/*
INPUT FORMAT:
setpassword 1
setpassword 2
setpassword 3
authorize 49
authorize 50
*/
vector<int> result;
int j = 0;
long int m = pow(10, 9);
long int M = m + 7;
long int value, strValue;
for (int i = 0; i < events.size(); i++)
{
strValue = stoi(events[i][1]);
if (events[i][0] == "setPassword") {
value = hashingfunct(events[i][1], M);
}
else if (strValue == value)
result[j++] = 1;
else if (authorize(strValue, value, M))
result[j++] = 1;
else
result[j++] = 0;
}
for (int i = 0; i < result.size(); i++) {
cout << result[i];
}
}
Your program has complete Undefined Behaviour.
Let's get started with the first problem. In the following check code
long int value, strValue; // not initialised
for (int i = 0; i < events.size(); i++)
{
// ...
// here it should have been "setpassword" (i.e. all are small letters)
if (events[i][0] == "setPassword")
{
// if the check fails the `value` never get initialised!
value = hashingfunct(events[i][1], M);
}
// If the `value` not been initialised, check happens with any garbage value here!
else if (strValue == value)
// ...other code
}
You are checking whether the string is "setPassword" instead of "setpassword" (i.e. see in the events vector, all the strings are small letters).
If that goes wrong, the value will never get initialized, meaning it holds any garbage value and hence conducting this check else if (strValue == value) can cause any behaviour to your program (aka Undefined Behaviour).
Secondly, the vector<int> result; is empty at the beginning. Therefore accessing elements via std::vector::operator[] later
result[j++] = 1;
// ...
result[j++] = 1;
// ...
result[j++] = 0;
triggers the access out of bounds (UB). There you need just result.emplace_back(/*value*/); or result.push_back(/*value*/);, and no need of redutant variable j.
In short, you need
#include <iostream>
#include <vector>
#include <string>
// ..other functions
int main()
{
std::vector<std::vector<std::string> > events {
{"setpassword", "1"}, // can be also user input, like in your example
{"setpassword", "2"},
{"setpassword", "3"},
{"authorize", "49" },
{"authorize", "50" }
};
std::vector<int> result;
const long int M = pow(10, 9) + 7;
long int value{ 0 }, strValue{ 0 }; // default initialization
for (const std::vector<std::string> row: events) // better use range-based loop
{
strValue = std::stoi(row[1]);
if (row[0] == "setpassword") {
value = hashingfunct(row[1], M);
if (strValue == value)
result.emplace_back(1);
else if (authorize(strValue, value, M))
result.emplace_back(1);
}
else
result.emplace_back(0);
}
}
As a side note,
Please do not use using namespacestd;
Why should I not #include <bits/stdc++.h>?
Corrected code
#include<bits/stdc++.h>
using namespace std;
bool authorize(long int strValue,long int value,int M){
long int value1=value*131;
long int newValue=(strValue-(value1%M))%M;
if(newValue>=48 && newValue<=57)
return true;
if(newValue>=65 && newValue<=90)
return true;
if(newValue>=97 && newValue<=122)
return true;
return false;
}
int hashingfunct(string str,int M){
long int P,F,sum=0;
int len=str.length();
for(int i=0;i<len;i++){
P=pow(131,len-i-1);
F=(int)str[i];
sum+=(F*P)%M;
}
sum=sum%M;
return sum;
}
int main(){
int n=5;
string str1,str2;
vector<vector<string> > events;
for (int i=0;i<n;i++){
cin>>str1>>str2;
vector<string > temp;
temp.push_back(str1);
temp.push_back(str2);
events.push_back(temp);
}
/*
setPassword cAr1
authorize 223691457
authorize 303580761
setPassword d
authorize 100
*/
vector<int> result;
int j=0;
long int m=pow(10,9);
long int M=m+7;
long int value,strValue;
for(int i=0;i<events.size();i++){
if(events[i][0]=="setPassword"){
value=hashingfunct(events[i][1],M);
continue;
}
strValue=stoi(events[i][1]);
if(strValue==value)
result.push_back(1);
else if(authorize(strValue,value,M))
result.push_back(1);
else
result.push_back(0);
}
for(int i=0;i<result.size();i++){
cout<<result[i];
}
}

Kurskal algorithm, Runtime Error in Kattis

I've been trying to solve the Minimum Spanning Tree on Kattis. (https://open.kattis.com/problems/minspantree) The first test runs fine, the second gives an unspecified runtime error. I've been struggling with this for over a week. It must be some logical error, but no matter how much effort i'm putting into it, I can't see what's wrong.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
class DisjointSet {
public:
vector<int> parent, rank;
DisjointSet(int _size) {
parent.resize(_size);
rank.resize(_size); // Maybe this?
// make the sets
for (int i = 0; i < _size; i++) { // fill set
parent[i] = i;
rank[i] = 0;
}
}
void make_set(int v) {
parent[v] = v;
rank[v] = 0;
}
int find_set(int v) {
if (v == parent[v])
return v;
return parent[v] = find_set(parent[v]);
}
void union_sets(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b) {
if (rank[a] < rank[b])
swap(a, b);
parent[b] = a;
if (rank[a] == rank[b])
rank[a]++;
}
}
};
bool sort_weight(const tuple<int, int, int> &one, const tuple<int, int, int> &two) {
return get<2>(one) < get<2>(two); // Weight
}
bool sort_node(const tuple<int, int, int> &one, const tuple<int, int, int> &two) {
if (get<0>(one) != get<0>(two)) {
return get<0>(one) < get<0>(two); // node one
}
return get<1>(one) < get<1>(two); // node two
}
int main()
{
int n_nodes = 0, n_arcs = 0;
int tmp_node1, tmp_node2, tmp_weight;
while (cin >> n_nodes >> n_arcs) { // Until the end
if (n_nodes == 0 && n_arcs == 0) { break; }
if (n_arcs < n_nodes - 1) { // If it is not possible to build a MST
cout << "Impossible\n";
}
else {
int cost = 0;
DisjointSet s(n_nodes); // make set
vector<tuple<int, int, int>> vArcs;
vector<tuple<int, int, int>> vResult;
vArcs.resize(n_arcs);
for (int i = 0; i < n_arcs; i++) {
cin >> tmp_node1 >> tmp_node2 >> tmp_weight;
vArcs[i] = make_tuple(tmp_node1, tmp_node2, tmp_weight);
}
sort(vArcs.begin(), vArcs.end(), sort_weight); // Sort by weight lowest to highest
for (int i = 0; i < n_arcs && vResult.size()<(n_nodes - 1); i++)
{
if (s.find_set(get<0>(vArcs[i])) != s.find_set(get<1>(vArcs[i]))) {
cost += get<2>(vArcs[i]);
vResult.push_back(vArcs[i]);
s.union_sets(get<0>(vArcs[i]), get<1>(vArcs[i]));
}
}
// We are done, order and print
sort(vResult.begin(), vResult.end(), sort_node);
cout << cost << "\n";
for (int i = 0; i < vResult.size(); i++)
{
cout << get<0>(vResult[i]) << " " << get<1>(vResult[i]) << "\n";
}
}
}
}
You need to read the whole input for each test case, even if the number of edges is below n - 1.

C++ vector reference works funny

I have written a simple c++ algorithm to calculate permutations of a vector. The below code works fine if I change this 13. line
vector<int>& pp = p.front();
to this
vector<int> pp = p.front();
I cannot understand why. I don`t think it is caused by reallocation. Could someone explain?
#include <vector>
using namespace std;
class Solution {
public:
void f(vector<vector<int> >& p, vector<int>& num)
{
if (p.front().size() == num.size()) return;
int k = p.size();
while (k)
{
vector<int>& pp = p.front();
for (int toAdd : num)
{
bool found = false;
for (int i = 0; i < pp.size(); i++)
{
if (pp[i] == toAdd)
{
found = true;
break;
}
}
if (!found)
{
vector<int> newp;
for (int i = 0; i < pp.size(); i++)
{
newp.push_back(pp[i]);
}
newp.push_back(toAdd);
p.push_back(newp);
}
}
p.erase(p.begin());
k--;
}
f(p, num);
}
vector<vector<int> > permute(vector<int> &num)
{
vector<vector<int>> r;
r.reserve(2 << num.size());
for (int i = 0; i < num.size(); i++)
{
r.push_back(vector<int>());
r[i].push_back(num[i]);
}
f(r, num);
return r;
}
};
int main()
{
Solution s;
vector<int> num{ 6, 3, 2, 7, 4, -1 };
auto a = s.permute(num);
a.clear();
return 0;
}
It's because of this statement:
p.push_back(newp)
That invalidates all references to entries in the vector p, because it can reallocate the contents.

Querying for a value that's bigger than X, while having another condition

I have list of pair [x;y] where x is unique and y can be duplicate(integers).
Here lies a problem:
Given a pair [x;y], find new pair [k;m], such that:
k > x
m >= y
k - x is minimized.
Now, I've solved this problem with this logic; I sort pairs by x, and then start naive O(n^2) algorithm on it. It seems to work fine, except it's too slow.
Can I do better?
The actual problem im trying to solve, is here: http://www.spoj.com/problems/VBOSS/
and my current code:
#include <stdio.h>
#include <utility>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
struct employee
{
int id;
int salary;
int height;
int parent_index;
int sub_ordinates;
int cur;
bool important;
bool operator < (const employee& e) const
{
if(height == e.height)
return salary > e.salary;
return (height > e.height);
}
};
// problem states explictly that no two employees
// have same salary.
struct salary_predicate
{
inline bool operator() (const employee& struct1, const employee& struct2)
{
return (struct1.salary > struct2.salary);
}
};
const int MAX_EMPLOYEES = 30000;
const int MAX_QUERIES = 200;
employee employees[MAX_EMPLOYEES];
int queries[MAX_QUERIES];
int main()
{
int test_cases;
scanf("%d", &test_cases);
while(test_cases--)
{
int employeeCount, queryCount;
scanf("%d %d", &employeeCount, &queryCount);
int i = 0;
int j = 0;
while(i < employeeCount)
{
employees[i].parent_index = -1;
employees[i].sub_ordinates = 0;
employees[i].cur = i;
employees[i].important = false;
scanf("%d %d %d", &employees[i].id, &employees[i].salary, &employees[i].height);
i++;
}
map<int, int> mapper;
while(j < queryCount)
{
scanf("%d", &queries[j]);
mapper.insert(pair<int, int>(queries[j], -1));
j++;
}
// now step1; sort employees structure
// based on SALARY!!
sort(employees, employees + employeeCount, salary_predicate());
for(int k = 0; k < employeeCount; k++)
{
employees[k].cur = k;
if(mapper.find(employees[k].id) != mapper.end())
{
mapper[employees[k].id] = k;
employees[k].important = true;
}
}
int found = 0;
for(int l = employeeCount - 1; l >= 0; l--)
{
int gef = l - 1;
// check out information about previous worker,
// he might give us some valuable information!
// with his help, we know if we can skip some shit :)
if(l + 1 < employeeCount && employees[l + 1].parent_index != -1)
{
// if previous employee is smaller than our current employee
// then we can skip some people, becase we know that answer cant be
// smalle than that :)
if(employees[l + 1].height <= employees[l].height)
gef = employees[l + 1].parent_index - 1;
}
// find boss!
for(int b = gef; b >= 0; b--)
{
if(employees[b].height >= employees[l].height)
{
employees[l].parent_index = b;
employees[b].sub_ordinates += employees[l].sub_ordinates + 1;
break;
}
}
// this bit makes sure if we have processed all necessay things,
// then we can basically stop our work.
if(employees[l].important) found++;
if(found == mapper.size()) break;
}
// time to print it out.
for(int b = 0; b < queryCount; b++)
{
int id = queries[b];
int index = mapper[id];
int parent_index = employees[index].parent_index;
int parent = parent_index < 0 ? 0 : employees[parent_index].id;
printf("%d %d\r\n", parent, employees[index].sub_ordinates);
}
}
return 0;
}
salary=x, and height=y.
I would start by eliminating all records where m<y or k<=x. Then find the item with the smallest k value out of what's left. Both of these should be linear, so your overall complexity should also be linear.
struct p {
int k, m;
};
p find_item(p xy, std::vector<p> &values) {
auto end = std::partition(values.begin(), values.end(),
[xy](p const &v) { return xy.k < v.k || xy.m >= v.m; });
return *std::min_element(values.begin(), end,
[](p const &a, p const &b) { return a.k < b.k; });
}