Count distinct pairs of strings that contain at least one common character at the same position - c++

Is there a more efficient way to count distinct pairs of strings in an array that have at least one common character at the same position. The strings will always have the same length of 3. For example,
"abc", acb": counts
"bun", "fun": counts
"xyz", "yzx": doesn't count
"one", "two": doesn't count
I've tried writing a function that checks if they match and then count them using for loops, but it doesn't seem to be so efficient, especially when the array is huge.
bool match(std::string a, std::string b) {
for (int i = 0; i < 3; i++) {
if (a.at(i) == b.at(i)) {
return true;
}
}
return false;
}
int main() {
const int count = 100000;
std::string strings[count] = {...};
long long int matches = 0;
for (int i = 0; i < count; i++) {
for (int j = i + 1; j < count; j++) {
if (match(strings[i], strings[j])) {
matches++;
}
}
}
}
So, is there a more efficient way to achieve this?

Heres the list (assuming the strings has 3 chars):
is actual the only one that might not be already done by your compiler: pass the std::string by const&, so that you don't need to copy them every time you call the function
bool match(const std::string& a, const std::string& b){...}
avoid useless branches in your code (can be optimized already by some branch prediction algorithm):
// from
if (match(strings[i], strings[j])) {
matches++;
}
// to
matches = matches + match(strings[i], strings[j];
loop unrolling (which can been done already by your compiler):
bool match(std::string a, std::string b) {
return a.at(0) == b.at(0) || a.at(1) == b.at(1) || a.at(2) == b.at(2);
}
You can also try to parallelize those conditions (depends on architecture, can be done already by the compiler) using | and so all the conditions can be done in parallel by ALU, instead using | must be performed step by step (short circuit evaluation):
bool match(std::string a, std::string b) {
return a.at(0) == b.at(0) | a.at(1) == b.at(1) | a.at(2) == b.at(2);
}
Compile using the highest optimization (can increase the compilation time), using -O3
use pre-increment instead of post-increment (post increment will generate a second variable to return every time you use it, pre-increment no):
for (int i = 0; i < count; ++i) {
for (int j = i + 1; j < count; ++j) {
}
}
by this line std::string strings[count] = {...}; I suppose you are using initializarer list, and so the computation can actually be performed at compile time if you use std::string_view and so at runtime there is no compilation to perform (this works only if the strings are known at compile time)
decrease cache misses, but this depends 100% on architecture
inline the function (so that your program don't have to do a jump every time to call match):
// from:
bool match(const std::string& a, const std::string& b){...}
//to:
inline bool match(const std::string& a, const std::string& b){...}
use operator[] instead of .at() because it does not make any kind of bounds checking
bool match(std::string a, std::string b) {
return a[0] == b[0] | a[1] == b[1] | a[2] == b[2];
}

Related

How can I iterate through the last element of the vector without going out of bounds?

The expected output is 1a1b1c but I only get 1a1b If I try putting '-1' next to input.size() in the for loop but that will just ignore the bug. What I'm looking for is that I want to be able to iterate through the last member of the string without going out of bounds.
std::string input = "abc";
for (unsigned int i = 0; i < input.size(); i++){
int counter = 1;
while(input.at(i) == input.at(i+1) && i < input.size()-1){
counter++;
i++;
}
number.push_back(counter);
character.push_back(input.at(i));
}
Few points for you to consdier:
1: for (unsigned int i = 0; i < input.size(); i++) specifically i++. This is a postfix operation meaning it returns i then increments the value of i. Not as big a deal here with integers but with iterators this can get very expensive as you create a copy of the iterator each time. Prefer to say what you mean / what you actually want, which is to increment i, not get a copy of i and increment i afterwards. So prefer ++i which only increments i and does not make a copy.
2: unsigned int i = 0 Firstly its better than using an int which has a signed -> unsigned conversaion every comparison with input.size() which returns a size_t. Secondly unsigned int is not guaranteed to be big enough to hold the size of the string and requires a promotion from (probably) 32 bit -> 64 bit unsigned to compare with size_t
3: cognitive complexity, nested loops which both mutate the same invariant (in this case i) makes the code more difficult to reason about and will ultimately lead to more bugs as code evolves over time. where possible only have one place where a loop invariant is mutated.
4: As pointed out by others the while loop while(input.at(i) == input.at(i+1) && i < input.size()-1) can exceed the size of the string and using the .at member function of string will throw for an out of bounds access. This can be simply resolved with point 3 by refactoring ther nested loop into a single loop.
5: Avoid so many calls to .at, we are in complete control of the index we use to index the string so you can use operator[] safely as long as we can guarantee i will always be a valid index which in this case i think you can.
6: i < input.size() using < when its not the check you want and its much more expensive than the check you actually want which is i != input.size(). Check out this trivial comparison in compiler explorer
Thankfully the fix from shadowranger Fixes your problem completely ie: while(i < s.size()-1 && s.at(i) == s.at(i+1)) However i would like to offer an alternitive with no nested loops to show you how to avoid my points 3,4, 5 and 6 :
void do_the_thing(std::string const& s) {
std::cout << "Considering: \"" + s + "\"\n";
if(s.empty()) {
return;
}
size_t const length = s.length(); // avoiding repeated calls to length which never changes in this case
if(length == 1) {
std::cout << "1" << s[0] << "\n";
return;
}
std::vector<unsigned> number;
std::vector<char> character;
// do the stuff your example did
char last = s[0];
unsigned same_count = 1;
for(size_t ii = 1; ii != length; ++ii) {
char const cur = s[ii];
if(cur == last) {
++same_count;
} else {
number.push_back(same_count);
character.push_back(last);
last = cur;
same_count = 1;
}
}
if(*s.rbegin() == last) {
number.push_back(same_count);
character.push_back(last);
}
// print the things or use them in some way
assert(number.size() == character.size());
size_t const out_len = character.size();
for(size_t ii = 0; ii != out_len; ++ii) {
std::cout << number[ii] << character[ii];
}
std::cout << "\n";
}

What does "bool a_indexable = i < static_cast<int>(a.size())" mean in the following code?

The following is the code:
#include <vector>
#include <string>
std::vector<std::string> zip(
const std::vector<std::string> & a,
const std::vector<std::string> & b) {
std::vector<std::string> result;
for (int i = 0; ; ++i) {
bool a_indexable = i < static_cast<int>(a.size()); //I couldn't get what the following two lines mean as I asked in the title, I couldn't get what bool means here and I couldn't get what i < static_cast<int>(a.size()) means here
bool b_indexable = i < static_cast<int>(b.size());
if (!a_indexable && !b_indexable) {
break;
}
std::string element;
if (a_indexable) {
element += a[i];
}
if (b_indexable) {
element += b[i];
}
result.push_back(element);
}
return result;
}
I know what static_cast<int> means in the code but I feel confused about its combination especially like i < static_cast<int>(b.size()). Please explain it if you could help me.
a_indexable is a boolean that indicates if i is a valid index for the vector a.
A naive way of computing a_indexable would be:
bool a_indexable = i < a.size();
However a.size() is of type std::size_t which is an unsigned integer. Mixing signed with unsigned integers is troublesome so most compilers will emit a warning for i < a.size(). The solution is to explicitly cast a.size() to the type of i like in your example:
bool a_indexable = i < static_cast<int>(a.size());
a.size() and b.size() here refers to std::vector::size(). std::vector::size() returns a size_t (usually an unsigned int), not an int.
As you can see in this question, comparing an int to an size_t will give a warning. By static_casting to an int, whoever wrote this code is getting rid of a warning from the compiler.
It's actually a way of deciding whether a given index is valid for the vector and therefore ensuring you don't try to read beyond the end of a vector. If the index is less than the size, then it's valid. The cast avoids warnings form mixing signed and unsigned values in the comparison.
However, I probably would have just made i a size_t type so that such casting was unnecessary, especially since i is very limited in scope.
In fact, I would have written it differently so as to avoid that sort of logic altogether, by getting the common length up front (the minimum of both lengths) and then processing it in sections, something like (with some type aliasing goodness to make the code a little mode readable, and as a complete program showing a minimal test harness):
#include <vector>
#include <string>
using vecString = std::vector<std::string>;
vecString zip(const vecString &a, const vecString &b) {
vecString result;
auto asz = a.size();
auto bsz = b.size();
auto common_sz = std::min(asz, bsz);
// Handle common size, both vectors are guaranteed
// to have elements at these indices.
for (size_t i = 0; i < common_sz; ++i)
result.push_back(a[i] + b[i]);
// Handle where sizes differ, only ONE of these loop
// bodies will be executed, depending on which is
// larger. Of course, if sizes were identical,
// neither loop body will execute.
for (size_t i = common_sz; i < asz; ++i)
result.push_back(a[i]);
for (size_t i = common_sz; i < bsz; ++i)
result.push_back(b[i]);
return result;
}
#include <iostream>
int main() {
std::vector<std::string> vec1, vec2;
vec1.push_back("pax");
vec1.push_back("is");
vec1.push_back("clever");
vec2.push_back("diablo");
auto zipVec = zip(vec1, vec2);
for (const auto &zipString: zipVec)
std::cout << zipString << '\n';
}

C++: Fastest method to check if all array elements are equal

What is the fastest method to check if all elements of an array(preferable integer array) are equal. Till now I have been using the following code:
bool check(int array[], int n)
{
bool flag = 0;
for(int i = 0; i < n - 1; i++)
{
if(array[i] != array[i + 1])
flag = 1;
}
return flag;
}
int check(const int a[], int n)
{
while(--n>0 && a[n]==a[0]);
return n!=0;
}
Here is a solid solution which is valid C++11.
The advantages is that you do not need to manually play with the indexes or iterators. It is a best practice to
prefer algorithm calls to handwritten loops [Herb Sutter - C++ Coding Standards]
I think this will equally efficient as Paul R's solution.
bool check(const int a[], int n)
{
return !std::all_of(a, a+n, [a](int x){ return x==a[0]; });
}
Once you have found a mismatching element you can break out of the loop:
bool check(const int array[], int n)
{
for (int i = 0; i < n - 1; i++)
{
if (array[i] != array[i + 1])
return true;
}
return false;
}
If this is performance-critical then it can be further optimised slightly as:
bool check(const int array[], int n)
{
const int a0 = array[0];
for (int i = 1; i < n; i++)
{
if (array[i] != a0)
return true;
}
return false;
}
Recast the array to a larger data type. Eg, operate on 64bit ints, or use SSE or AVX intrinsics for 128 or 256 bit operation. For example, the SSE2 intrinsic is _mm_cmpeq_epi32, whose result you'll use with _mm_or_si128. Check the result with repeated application of _mm_srli_si128 and _mm_cvtsi128_si32. Check the result every few hundred iterations for early exit.
Make sure to operate on aligned memory, check the unaligned start and end as ints, and check the first packed element with itself.
For programmer efficiency you may try the following all in one line.
vector<int> v{1, 1, 1, 1};
all_of(v.cbegin(), v.cend(), [&r=v[0]](int value){ return value == r; }->bool);
I did not test run this code, let me know if there is syntax error.
Find a library that's available on your platform that supports threading or parallel-for loops, and split the computation out such that different cores test different ranges of the array.
Some available libraries are listed here:
http://parallel-for.sourceforge.net/parallelfor.html
Or possibly, you can make use of the parallism that many GPU's offer.
bool check(int array[],int n)
{
// here 1st element is checked with others. This decreases the number of iteration by 1.
// also it returns immediately.
// The requirement is to check if all the elements are equal.
// So if 1st element is equal to others then all elements are equal.
// Otherwise the elements are not equal.
for(int i=1;i<n;i++)
{
if(array[0]!=array[i])
return false;
}
return true;
}
We'll it's basically an O(n) operation so you can't do much better than what you have, other than dispensing with the flag and just return false; on the first failure and return true; after the iteration.
In theory, I would propose this:
bool check_single(const int a[], int n)
{
for (int i = 1; i < n; ++i) {
if (a[0] != a[n]) { return false; }
}
return true;
}
Compared to other (already proposed) versions:
a[0] will be hoisted outside the loop by the compiler, meaning a single array access within the loop
we loop from 0 to n, which is better (access-wise) than loading a[0] and then looping from a[n]
Obviously, it still checks N elements and thus is O(N).
fast hash mapping technique:
bool areSame(int a[],int n)
{
unordered_map<int,int> m; //hash map to store the frequency od every
for(int i=0;i<n;i++)
m[a[i]]++;
if(m.size()==1)
return true;
else
return false;
}
I think the following is more readable than the highest rated answer and I would wager more efficient too (but havent benchmarked)
bool check(int a[], int n)
{
if (n)
{
auto first = a[0];
for(int i = 1; i < n; i++)
{
if(array[i] != first) return false;
}
return true;
}
return true; //change to false for the OPs logic. I prefer logical true here
}
bool check_identity (int a[], int b[], const int size)
{
int i;
i = 0;
while ((i < size-1) && (a[i] == b[i])) i++;
return (a[i] == b[i]);
}

conditionally testing for equality of vector's elements

Although it seems pretty simple, I'm not sure of the most efficient way of doing this.
I have two vectors:
std::vector<bool> a;
std::vector<int> b;
a.size() necessarily equals b.size().
each bool in a corresponds to an int in b. I want to create a function:
bool test(std::vector<bool> a, std::vector<int> b);
This function returns true if the values in a are equal. However, it only considers values in a that correspond to true values in b.
I could do this:
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned int i;
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
x = a.at(i);
break;
}
}
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
if(a.at(i) != x){
return false;
}
}
}
return true;
}
But then I have to create two loops. Although the first loop will stop at the first true value, is there a better way?
Your solution looks good enough to me:
Each loop does a different thing anyway (so you shouldn't worry about duplication)
You don't use extranious variables or flags that complicate the code.
The only problems I see are:
You start the second loop at 0 instead of where you left off.
Doing if(condition == true) is very ugly. Just do if(condition) instead.
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned i;
for(i = 0; i < a.size(); i++){
if(b.at(i)){
x = a.at(i);
break;
}
}
for(i++; i < a.size(); i++){
if(b.at(i)){
if(a.at(i) != x){
return false;
}
}
return true;
}
You can do it in one loop if you remember if you have seen the first true element in b or not. Also, you should take the a and b parameters by reference to avoid unnecessary copying. And finally, if you know that the indices into a vector are always within valid range (i.e. between 0 and vector.size() - 1, inclusive), you can use operator[] instead of at, and achieve better peformance (at does a range check, while operator[] does not). Heres a modified version of your test function considering all the above points:
bool test(std::vector<int> const& a, std::vector<bool> const& b){
int x;
bool first = true;
for(unsigned i = 0, n = a.size(); i != n; ++i){
if( b[i] ){
if( first ) {
x = a[i];
first = false;
}
else if( x != a[i] ) {
return false;
}
}
}
return true;
}
Provided you know a.size() == b.size() just create a single loop that compares an 'a' element to a 'b' element at the same time at each iteration. Once you see that a[i] != b[i] then you know the containers don't match and you can break out.
I am not 100% certain I know what you want to do but a straight compare once you know you have equal size
std::equal(a.begin(), a.end(), b.begin(), std::equal_to<bool>())

Difference between code generated using a template function and a normal function

I have a vector containing large number of elements. Now I want to write a small function which counts the number of even or odd elements in the vector. Since performance is a major concern I don't want to put an if statement inside the loop. So I wrote two small functions like:
long long countOdd(const std::vector<int>& v)
{
long long count = 0;
const int size = v.size();
for(int i = 0; i < size; ++i)
{
if(v[i] & 1)
{
++count;
}
}
return count;
}
long long countEven(const std::vector<int>& v)
{
long long count = 0;
const int size = v.size();
for(int i = 0; i < size; ++i)
{
if(0 == (v[i] & 1))
{
++count;
}
}
return count;
}
My question is can I get the same result by writing a single template function like this:
template <bool countEven>
long long countTemplate(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
if(countEven)
{
if(v1[i] & 1)
{
++count;
}
}
else if(0 == (v1[i] & 1))
{
++count;
}
}
return count;
}
And using it like this:
int main()
{
if(somecondition)
{
countTemplate<true>(vec); //Count even
}
else
{
countTemplate<false>(vec); //Count odd
}
}
Will the code generated for the template and non-template version be the same ? or will there be some additional instructions emitted?
Note that the counting of numbers is just for illustration hence please don't suggest other methods for counting.
EDIT:
Ok. I agree that it may not make much sense from performance point of view. But atleast from maintainability point of view I would like to have only one function to maintain instead of two.
The templated version may and, very probably, will be optimized by the compiler when it sees a certain branch in the code is never reached. The countTemplate code for instance, will have the countEven template argument set to true, so the odd branch will be cut away.
(sorry, I can't help suggesting another counting method)
In this particular case, you could use count_if on your vector:
struct odd { bool operator()( int i )const { return i&1; } };
size_t nbOdd = std::count_if( vec.begin(), vec.end(), odd() );
This can also be optimized, and writes way shorter :) The standard library developers have given possible optimization much thought, so better use it when you can, instead of writing your own counting for-loop.
Your template version will generate code like this:
template <>
long long countTemplate<true>(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
if(true)
{
if(v1[i] & 1)
{
++count;
}
}
else if(0 == (v1[i] & 1))
{
++count;
}
}
return count;
}
template <>
long long countTemplate<false>(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
if(false)
{
if(v1[i] & 1)
{
++count;
}
}
else if(0 == (v1[i] & 1))
{
++count;
}
}
return count;
}
So if all optimizations are disabled, the if will in theory still be there. But even a very naive compiler will determine that you're testing a constant, and simply remove the if.
So in practice, no, there should be no difference in the generated code. So you can use the template version and don't worry about this.
I guess that good compiler will cut redundant code in your template as countEven is compile time constant and it is very simple to implement such optimization during template instantiation.
Anyway it seems pretty strange. You wrote a template but do "dynamic switching" inside.
May be try something like that:
struct CountEven {}
struct CountOdd {}
inline void CountNum(int & num, long long & count, const CountEven &)
{
if(num & 1)
{
++count;
}
}
inline void CountNum(int & num, long long & count, const CountOdd &)
{
if(0 == (num & 1))
{
++count;
}
}
template <class T>
long long countTemplate(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for(int i = 0; i < size; ++i)
{
CountNum(v1[i], count, T());
}
return count;
}
It will select necessary CountNum() function version on compilation stage:
int main()
{
if(somecondition)
{
countTemplate<CountEven>(vec); //Count even
}
else
{
countTemplate<CountOdd>(vec); //Count odd
}
}
Code is messy, but I think you got the idea.
This will depend on how smart the compiler optimizer is. The compiler might be able to see that really the if-statement is redundant and only one branch of it is executed and optimize the whole thing.
The best way to check is to try and look at the assembly - this code will not produce too much of machine code.
The first thing that comes to my mind are the two optimization "rules":
Don't optmized prematurely.
Don't do it yet.
The point is that sometimes we bother about a performance bottleneck which will never happen in practice. There are studies that say that 20 percent of the code is responsible for 80 percent of the software execution time. Of course this doesn't mean you pessimize prematurely, but I don't think that's your case.
In general, you should do this kind of optmization only after you have actually run a profiler on your program and identified the real bottlenecks.
Regarding your function versions, as other have said this depends on your compiler. Just remember that with the template approach you won't be able to switch calls at runtime (template is a compile-time tool).
A final note: long long is not standard C++ (yet).
If you care about optimization issues try to make it like the following:
template <bool countEven>
long long countTemplate(const std::vector<int>& v1)
{
long long count = 0;
const int size = v1.size();
for ( int i = 0; i < size; ++i ) {
// According to C++ Standard 4.5/4:
// An rvalue of type bool can be converted to an rvalue of type int,
// with false becoming zero and true becoming one.
if ( v1[i] & 1 == countEven ) ++count;
}
return count;
}
I believe that the code above will be compiled in the same code as without templates.
Use STL, Luke :-) It's even as example in reference
bool isOdd(int i)
{
return i%2==1;
}
bool isEven(int i)
{
return i%2==0;
}
std::vector<int>::size_type count = 0;
if(somecondition)
{
count = std::count_if(vec.begin(), vec.end(), isEven);
}
else
{
count = std::count_if(vec.begin(), vec.end(), isOdd);
}
In general, the outcome will be much the same. You are describing an O(n) iteration over the linear memory of the vector.
If you had a vector of pointers, suddenly the performance would be way worse because the memory locality of reference would be lost.
However, the more general thing is that even netbook CPUs can do gazallions of operations per second. Looping over your array is most unlikely to be performance-critical code.
You should write for readability, then profile your code, and consider doing more involved hand-tweaked things when the profiling highlights the root cause of any performance issue you have.
And performance gains typically come from algorithmic changes; if you kept count of the number of odds as you added and removed elements from the vector, for example, it would be O(1) to retrieve...
I see that you're using long long for counter, and that probably means that you expect huge number of elements in vector. In that case, I would definitely go for template implementation (because of code readability) and just move that if condition outside for loop.
If we assume that compiler makes no optimization whatsoever, you would have 1 condition and possibly more than 2 billion iterations through vector. Also, since the condition would be if (true) or if (false) the branch prediction would work perfectly and execution would be less than 1 CPU instruction.
I'm pretty sure that all compilers on the market have this optimization, but I would quote my favorite when it comes to performance: "Premature optimization is the root of all evil" and "There're only 3 rules of optimization: Measure, measure and measure".
If you absolutely absurdly care about fast looking code:
(a clever compiler, or one otherwise hinted at using directives or intrinsics, could do this in parallel using SIMD; CUDA and OpenCL would of course eat this for breakfast!)
int count_odd(const int* array,size_t len) {
int count = 0;
const int* const sentinal = array+len;
while(array<sentinal)
count += (*array++ & 1);
return count;
}
int count_even(const int* array,size_t len) {
return len-count_odd(array,len);
}