There is a simple feature I would like to add to one of the members of a class: I would like to quit the function in case all the values of some boolean (2d) array are true.
In the simpler case of a 1d array I can do it this way:
int SIZE = 10;
std::vector<bool> myArray(SIZE, true);
int i = 0;
while(myArray[i] and i < SIZE){
++i;
}
if(i == SIZE){
return;
}
// rest of the code for array not all true
There is probably no quicker way to do it (minus marginal optimizations) but I find it a bit ugly. Are there nicer ways to do it?
=========================================
In the end I decided to implement:
{
bool allTrue = true;
for(int i = 0; i < SIZE1 and allTrue; ++i)
for(int j = 0; j < SIZE2 and allTrue; ++j)
allTrue &= myArray[i][j];
if(allTrue)
return;
}
You may use std::all_of from <algorithm>:
if (std::all_of(myArray.begin(), myArray.end(), [](bool b) {return b;})) {
return;
}
One of the solutions:
int my2Da[][2] = {{true, true},{true, true},{true, true}};
int *pa = my2Da[0];
bool flag=true;
for (int i=0;flag && i<(sizeof my2Da)/(sizeof (int));flag &= pa[i++]);
//flag indicates about the result
For a 2d vector, you might want to break it down :
#include <vector>
#include <algorithm>
bool all_true(const std::vector<bool>& v)
{
return std::all_of(std::begin(v), std::end(v), [](const auto& b) { return b; });
}
bool all_true(const std::vector<std::vector<bool>>& vv)
{
return std::all_of(std::begin(vv), std::end(vv), [](const auto& v) {
return all_true(v);
});
}
void test()
{
std::vector< std::vector< bool > > d2 /* = initalise 2d vector */;
while(!all_true(d2))
{
// things you want to do
}
}
May be and-ing all values? This way:
bool r = true;
for (int i=0; i<myArray.size() && r; i++) r &= myArray[i];
return r;
Or std::all_of if your are familiar with iterators and lambdas.
Related
I am trying to see if an array contains multiple values at any given index in the array, and if it does I want it to return true and if not return false. I want it to return true when it finds the numbers 1-9 and false if it does not.
bool isSolved(int a[], int size) {
int count = 0;
for (int i = 1; i < 10; i++) {
if (hasNum(a,size,i)) {
count++;
}
}
if (count == 9) {
return true;
}
else {
return false;
}
}
bool hasNum(int a[], int size, int num) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (a[j] == num) {
return true;
}
else {
return false;
}
}
}
}
This is what I have so far and it just gets stuck and never ends.
Man, that's C++. So use a standard vector and the count_if function from the standard library:
#include <algorithm>
#include <vector>
std::vector<int> a { /* fill vector */ };
std::count_if(std::begin(a), std::end(a), [](auto const& x){ return x == 1;});
Return the number of elements with value 1.
Also good, to question whether there's any value of 1:
std::any_of(std::begin(a), std::end(a), [](auto const& x){ return x == 1;});
I know this is strictly not an answer ...
There's no need to have 2 for loops in your hasNum function. Also, you are returning false if any of the values in the array is not equal to the number passed. You need to return false after the for loop ends.
Rewrite your hasNum function as shown below:
bool hasNum(int a[], int size, int num) {
for (int i = 0; i < size; i++) {
if (a[i] == num) {
return true;
}
}
return false;
}
I am trying to see if an array contains multiple values at any given index in the array
An array always contains exactly one value in every index.
Basically, your code is far from any C++ guidelines.
First, you don't pass array in C++ as int a[]. Use std::vector<int> instead.
Second your algorithm is badly inefficient. Consider using histogram approach.
bool isSolved(const std::vector<int>& a)
{
std::array<bool,10> hist;
for(int i=0; i<10; i++)
{
hist[i]=false;
}
for(auto x : a)
{
if(x>=0 && x<10)
{
hist[x] = true;
}
}
for(int i=0; i<10; i++)
{
if(!hist[i]) return false;
}
return true;
}
Here is a hint to the solution to your problem:
class BinaryTreeSet : public BinarySearchTree {
...
operator==
...
};
You are best off using std algorithms like find_if:
#include <algorithm>
int a[42]; // or vector<int> a(42) or any other container of any size
std::find_if(std::begin(a),std::end(a),[](auto const& v){return (v>=1)&&(v<=9);});
I have the following problem :
Given a number N and N names, sort the names using a certain value (in ascending order). The names with the same value get sorted alphabetically.
The value of each name is determined by the number of pairs of vowels or consonants. Thus, each pair of vowels adds 1 to the value of the word, each pair of consonants subtracts 1 from the value, and a vowel-consonant or consonant-vowel pair doesn't change the value of the word.
What I did :
I created a vector using a struct. Each element has the name and its value. I calculated the value of each name and gave it to the .value field. After that, I sorted my vector using 2 for loops (I had no efficient idea for a value sort and an alphabetical sort all in one), and displayed the vector.
What happens:
I get no result, and I also think that there might be a segmentation fault. I'm still a newbie when it comes to finding out such errors.
Can you give me a few pointers ?
Thank you.
Attached the code below.
#include <vector>
#include <string>
#include <cstring>
using namespace std;
const char voc[] = "aeiouAEIOU";
struct stud
{
string name;
int value;
};
typedef vector<stud> vect;
void data(int& n, vect& v)
{
cin>>n;
for(int i = 0; i < n; ++i)
{
cin>>v[i].name;
}
}
int getValue(string name)
{
int value = 0;
int len = name.length();
for(int i = 0; i < len; ++i)
{
if(strchr(voc, name[i]) && strchr(voc, name[i+1]))
value++;
else if(!strchr(voc, name[i]) && !strchr(voc, name[i+1]))
value--;
}
return value;
}
void updateValues(vect& v)
{
vector<stud>::size_type v_size = v.size();
for(unsigned i = 0; i < v_size; ++i)
{
int value = getValue(v[i].name);
v[i].value = value;
}
}
void sortByValue(vect& v)
{
vector<stud>::size_type v_size = v.size();
for(unsigned i = 0; i < v_size; ++i)
for(unsigned j = i+1; j < v_size; ++j)
{
if(v[i].value > v[j].value)
swap(v[i], v[j]);
else if(v[i].value == v[j].value)
if(v[i].name.compare(v[j].name) > 0)
swap(v[i], v[j]);
}
}
void display(vect v)
{
vector<stud>::size_type sz = v.size();
for(unsigned i = 0; i < sz; ++i)
cout<<v[i].name<<'\n';
}
int main()
{
int n;
vect myvec;
data(n, myvec);
updateValues(myvec);
sortByValue(myvec);
display(myvec);
return 0;
}
better use overload operator> watch here
or use std::sort
std::vector<stud> vec;
//read
std::sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) -> bool
{
if (a.value == b.value)
return a.name > b.name;
else
return a.value > b.value
});
I am taking an introductory level C++ class. I have to write a boolean function that checks for duplicates along a vectors and returns true and false if no duplicates
#include<iostream>
#include<vector>
using namespace std;
bool has_duplicates(const vector <int> &v);
int main() {
vector<int> Vec(8);
Vec = { 20, 30, 40, 50, 10, 20, 5, 6 };
has_duplicates(Vec);
return 0;
}
bool has_duplicates(const vector<int>& v) {
bool duplicatefound = false;
for (int i = 0; i < 8; i++) { // Check each other number in the array
for (int j = i; j < 8; j++) { // Check the rest of the numbers
while (j != i) {// Makes sure don't check number against itself
if (v[i] == v[j]) {
cout << "duplicate found" << endl;
duplicatefound = true;
break;
}
}
}
}
return duplicatefound; // Reset the boolean after each number entered has been checked
}
There is a very simple solution to your problem:
Iterate through your array, using a loop:
for(int i=0; i < array_length; i++)
Within this loop, make use of another loop, to check whether any value prior to the one, to which i is pointing, is equal to your_array[i]. If this is the case you have found a duplicate and can return true, else the loops will just run until the end of the array is reached and then you can return false.
Thus your entire function would be something like:
bool contains_duplicates(int array[], int len) {
for(int i=0; i < len; i++) {
for(int j=0; j < i; j++) {
if(array[j]==array[i]) {
return true;
}
}
}
return false;
}
Hope I could help, cheers!
lindebear
You can use templates to extend the type contained on vector like this. This solution reduces the algorithm complexity to O(n log n) which is better than O(n^2) from your nested loop, it doesn't mean it will be faster always but it make a difference on large vectors.
template< typename T>
bool hasDuplicates(std::vector<T> vect) {
std::sort(vect.begin(), vect.end());
T last;
typename vector<T>::iterator it;
for(it = vect.begin(); it < vect.end(); it++) {
if (vect.begin() != it) {
if(last == *it) {
return true;
}
}
last = *it;
}
return false;
}
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;
}
}
I am working on a N dimensional grid.
I would like to generate nested loops depending on any dimension (2D, 3D, 4D, etc...).
How can I do that in an elegant and fast way ? Below a simple illustration of my problem.
I am writing in C++ but I think this kind of question can be useful for other languages.
I need to know the indices (i,j,k...) in my do stuff part.
Edit : lower_bound and upper_bound represents the indexes in the grid so they are always positive.
#include <vector>
int main()
{
// Dimension here is 3D
std::vector<size_t> lower_bound({4,2,1});
std::vector<size_t> upper_bound({16,47,9});
for (size_t i = lower_bound[0]; i < upper_bound[0]; i ++)
for (size_t j = lower_bound[1]; j < upper_bound[1]; j ++)
for (size_t k = lower_bound[2]; k < upper_bound[2]; k ++)
// for (size_t l = lower_bound[3]; l < upper_bound[3]; l ++)
// ...
{
// Do stuff such as
grid({i,j,k}) = 2 * i + 3 *j - 4 * k;
// where grid size is the total number of vertices
}
}
Following may help:
bool increment(
std::vector<int>& v,
const std::vector<int>& lower,
const std::vector<int>& upper)
{
assert(v.size() == lower.size());
assert(v.size() == upper.size());
for (auto i = v.size(); i-- != 0; ) {
++v[i];
if (v[i] != upper[i]) {
return true;
}
v[i] = lower[i];
}
return false;
}
And use it that way:
int main() {
const std::vector<int> lower_bound({4,2,1});
const std::vector<int> upper_bound({6,7,4});
std::vector<int> current = lower_bound;
do {
std::copy(current.begin(), current.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while (increment(current, lower_bound, upper_bound));
}
Live demo
An iterative approach could look like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> lower_bound({-4, -5, -6});
std::vector<int> upper_bound({ 6, 7, 4});
auto increase_counters = [&](std::vector<int> &c) {
for(std::size_t i = 0; i < c.size(); ++i) {
// This bit could be made to look prettier if the indices are counted the
// other way around. Not that it really matters.
int &ctr = c .rbegin()[i];
int top = upper_bound.rbegin()[i];
int bottom = lower_bound.rbegin()[i];
// count up the innermost counter
if(ctr + 1 < top) {
++ctr;
return;
}
// if it flows over the upper bound, wrap around and continue with
// the next.
ctr = bottom;
}
// end condition. If we end up here, loop's over.
c = upper_bound;
};
for(std::vector<int> counters = lower_bound; counters != upper_bound; increase_counters(counters)) {
for(int i : counters) {
std::cout << i << ", ";
}
std::cout << "\n";
}
}
...although whether this or a recursive approach is more elegant rather depends on the use case.
#include <iostream>
#include <vector>
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f)
{
std::vector<int> temp;
process(lower, upper, f, 0, temp);
}
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f,
int index, std::vector<int>& current)
{
if (index == lower.size())
{
f(current);
return;
}
for (int i = lower[index]; i < upper[index]; ++i)
{
current.push_back(i);
process(lower, upper, f, index + 1, current);
current.pop_back();
}
}
int main()
{
// Dimension here is 3D
std::vector<int> lower_bound({-4, -5, 6});
std::vector<int> upper_bound({6, 7, 4});
// Replace the lambda below with whatever code you want to process
// the resulting permutations.
process(lower_bound, upper_bound, [](const std::vector<int>& values)
{
for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
});
}
Probably some typos an whatnot, but I'd flatten the whole range.
This is based on the idea that the range can be described as
x_0 + d_0*(x_1+d_1*(x_2+d_2....)
So we can roll our own that way
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
//ranges
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
}
Edit: to be more generic:
template <typename D>
void multi_for(const std::vector<int>& lower_bound, const std::vector<int> upper_bound, D d) {
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
size_t numel = std::accumulate(ranges.begin(), ranges.end(), std::multiplies<int,int>{});
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
d(idx,indexes);
}
}
//main
size_t* grid;//initialize to whateer
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
auto do_stuff = [grid](size_t idx, const std::vector<int> indexes) {
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
};
multi_for(lower_bound,upper_bound,do_stuff);
A recursive function may help you achieve what you want.
void Recursive( int comp )
{
if(comp == dimension)
{
// Do stuff
}
else
{
for (int e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
Some additions may be necessary in the function signature if you need to know the current indices (i,j,k,...) in your "Do Stuff" section.
This is a clean way to have access to these indices
void Recursive( int comp, int dimension )
{
static std::vector<int> indices;
if( comp == 0 ) // initialize indices
{
indices.clear();
indices.resize(dimension, 0);
}
if(comp == dimension -1)
{
// Do stuff
}
else
{
int& e = indices[comp];
for (e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
This is however not usable along multiple threads, due to the shared static vector.