Is there a test case where this code can break? - c++

This is the problem I am trying to solve.
Given two arrays a and b, check whether they are similar.
Two arrays are called similar if one can be obtained from another by swapping at most one pair of elements in one of the arrays.
I wrote the following code to solve the problem. I tried to make some optimizations but it fails on a hidden test. Can anyone help me find where the code could break?
bool is_similar(vector<int> a, vector<int> b, int start){
return memcmp(a.data() + start, b.data() + start, (a.size() - start) * sizeof(int)) == 0;
}
bool solution(vector<int> a, vector<int> b) {
int sizea = a.size(), sizeb = b.size();
if(sizea != sizeb) return false;
for(int i = 0; i < sizea; i++){
if(a[i] != b[i]){
auto it = find(b.begin() + i + 1, b.end(), a[i]);
if(it != b.end()){
swap(b[i], *it);
return is_similar(a, b, i + 1);
}
return false;
}
}
return true;
}

I started from scratch again and came up with a much better solution. Thank you all for your input. I'm loving this platform
The main problem was assuming the inputs were unique. This is the general flow of the initial code. A good test case to demonstrate the fault is when a = [0,1,1,3,4], b = [0,4,1,3,1]
Loop for the length of one of the arrays (they are of equal length)
Do nothing if the values are equal at the same index
If the values are not equal (now we are at index 1), search for 1 in array b and swap it with the current index. b becomes [0,1,4,3,1]
Now if we go on and call is_similar(a,b), it returns false.
Clearly if we swapped the contents at index 1 and 4, in array b, the arrays would be similar. That is why it fails.
A better approach is to collect the values at the indices where the values are different and determine if one swap is enough to make the two arrays similar. This is the code snippet.
bool solution(vector<int> a, vector<int> b) {
int sizea = a.size(), sizeb = b.size();
if(sizea != sizeb) return false;
int i= 0;
vector<int> a1;
vector<int> b1;
for(i = 0; i < sizea; i++){
if(a[i] != b[i]){
a1.emplace_back(a[i]);
b1.emplace_back(b[i]);
}
}
if(a1.size() == 0) return true;
if(a1.size() == 2) return a1[0] == b1[1] && a1[1] == b1[0];
return false;
}

Related

Finding closest triplet in a set of three vectors?

Given three vectors of double, I want to pair every element in each vector such that the difference between the largest and smallest element in each triple is minimized, and every element of every vector is part of a triple. Right now, I'm using std::lower_bound():
double closest(vector<double> const& vec, double value){ auto const ret = std::lower_bound(vec.begin(), vec.end(), value); return(*ret); }
int main(){
vector<double> a, b, c; vector<vector<double>> triples;
for(auto x : a){
triples.push_back({x, closest(b, x), closest(c, x)});
}
}
Pretend a, b, and c here are populated with some values. The problem is, lower_bound() returns the nearest element not less than the argument. I would also like to consider elements less than the argument. Is there a nice way to to this?
My solution was to implement a binary search terminating in a comparison of neighboring elements. Another possible solution is to iterate over the elements of each vector/array, adjusting the index as necessary to minimize the difference (which may compare to binary search with an ideal complexity of $O(\log{n})$?):
int solve(int A[], int B[], int C[], int i, int j, int k)
{
int min_diff, current_diff, max_term;
min_diff = Integer.MAX_VALUE;
while (i != -1 && j != -1 && k != -1)
{
current_diff = abs(max(A[i], max(B[j], C[k]))
- min(A[i], min(B[j], C[k])));
if (current_diff < min_diff)
min_diff = current_diff;
max_term = max(A[i], max(B[j], C[k]));
if (A[i] == max_term)
i -= 1;
else if (B[j] == max_term)
j -= 1;
else
k -= 1;
}
return min_diff;
}

Problems with vectors, how to remove the arrays in my vectors?

I have created a function that creates all the possible solutions for a game that I am creating... Maybe some of you know the bullcow game.
First I created a function that creates a combination of numbers of max four integers and the combination can't have any repeating number in it... like...
'1234' is a solution but not '1223' because the '2' is repeating in the number. In total there is 5040 numbers between '0123' and '9999' that haven't repeating numbers.
Here is my function:
std::vector <std::array<unsigned, 4>> HittaAllaLosningar(){
std::vector <std::array<unsigned, 4>> Losningar;
for (unsigned i = 0; i < 10; i++) {
for (unsigned j = 0; j < 10; j++) {
for (unsigned k = 0; k < 10; k++) {
for (unsigned l = 0; l < 10; l++) {
if (i != j && i != k && i != l && j != k && j != l && k != l) {
Losningar.push_back({i,j,k,l});
}
}
}
}
}
return Losningar;
}
Now let's say I have the number '1234' and that is not the solution I am trying to find, I want to remove the solution '1234' from the array since that isn't a solution... how do I do that? have been trying to find for hours and can't find it. I have tried vector.erase but I get errors about unsigned and stuff... also its worth to mention the guesses are in strings.
What I am trying to do is, to take a string that I get from my program and if it isn't a solution I want to remove it from the vector if it exists in the vector.
Here is the code that creates the guess:
std::string Gissning(){
int random = RandomGen();
int a = 0;
int b = 0;
int c = 0;
int d = 0;
for (unsigned i = random-1; i < random; i++) {
for (unsigned j = 0; j < 4; j++) {
if (j == 0) {
a = v[i][j];
}
if (j == 1) {
b = v[i][j];
}
if (j == 2) {
c = v[i][j];
}
if (j == 3) {
d = v[i][j];
}
}
std::cout << std::endl;
AntalTry++;
}
std::ostringstream test;
test << a << b << c << d;
funka = test.str();
return funka;
}
The randomgen function is just a function so I can get a random number and then I go in the loop so I can take the element of the vector and then I get the integers of the array.
Thank you very much for taking your time to help me, I am very grateful!
You need to find the position of the element to erase.
std::array<unsigned, 4> needle{1, 2, 3, 4};
auto it = std::find(Losningar.begin(), Losningar.end(), needle);
if (it != Losningar.end()) { Losningar.erase(it); }
If you want to remove all the values that match, or you don't like checking against end, you can use std::remove and the two iterator overload of erase. This is known as the "erase-remove" idiom.
std::array<unsigned, 4> needle{1, 2, 3, 4};
Losningar.erase(std::remove(Losningar.begin(), Losningar.end(), needle), Losningar.end());
To erase from a vector you just need to use erase and give it an iterator, like so:
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
auto it = vec.begin(); //Get an iterator to first elements
it++; //Increment iterator, it now points at second element
it = vec.erase(it); // This erases the {4,3,2,1} array
After you erase the element, it is invalid because the element it was pointing to has been deleted. Ti continue to use the iterator you can take the return value from the erase function, a valid iterator to the next element after the one erased, in this the case end iterator.
It is however not very efficient to remove elements in the middle of a vector, due to how it works internally. If it's not important in what order the different solution are stored, a small trick can simplify and make your code faster. Let's say we have this.
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
vec.push_back({3,2,1,4});
To remove the middle one we then do
vec[1] = vec.back(); // Replace the value we want to delete
// with the value in the last element of the vector.
vec.pop_back(); //Remove the last element
This is quite simple if you have ready other functions:
using TestNumber = std::array<unsigned, 4>;
struct TestResult {
int bulls;
int cows;
}
// function which is used to calculate bulls and cows for given secred and guess
TestResult TestSecretGuess(const TestNumber& secret,
const TestNumber& guess)
{
// do it your self
… … …
return result;
}
void RemoveNotMatchingSolutions(const TestNumber& guess, TestResult result)
{
auto iter =
std::remove_if(possibleSolutions.begin(),
possibleSolutions.end(),
[&guess, result](const TestNumber& possibility)
{
return result == TestSecretGuess(possibility, guess);
});
possibleSolutions.erase(iter, possibleSolutions.end());
}
Disclaimer: it is possible to improve performance (you do not care about order of elements).

what is the recursive form of this code?

I was trying to locate vector a in vector b. So it's like if vector a is in vector b then return true else false. And vector a should be like {1,2,3} and b should like {4,1,2,3,5,5,7}. The output of this code is coming like true 1 and false 0. So my problem is I don't want 1 and 0 to show up in the output.
Also I want to write this code in recursive form so could anyone help me with this problem?
bool x(vector<int>& a, vector<int> b)
{
vector<int> index ( b.size(),0 );
int counter = 0;
if ( a.size() <= b.size() ) {
for ( int i = 0; i < a.size(); i++ ) {
for ( int j = 0; j < b.size(); j++ ) {
if ( a[i]== b[j]) {
index[j] = 1;
}
}
}
for ( int i = 0; i < index.size(); i++ ) {
if ( index[i] == 1 ) {
for ( int j = i; j < index.size(); j++ ) {
if ( index[j] == 1 ) {
counter++;
}
}
if(counter == a.size()){
cout<<"true"<<endl;
return true;
break;
}
else{
counter = 0;
cout<<"false"<<endl;
return false;
// continue;
}
}
}
}
return 0;
}
if you just don't like the output: true 1 and false 0. the simplest way to solve it is:
if(x(a, b)){
cout<<"true"<<endl;
} else {
cout<<"false"<<endl;
}
BUT, before you try to convert you algorithm to a recursive one, I afraid that your algorithm is wrong. try this:
vector<int> a;
vector<int> b;
a.push_back(1);
a.push_back(2);
a.push_back(3);
b.push_back(1);
b.push_back(1);
b.push_back(1);
cout<<x(a,b)<<endl;
you will get true ,and the correct answer is false.
check your algorithm !
The reason you're seeing "true 1" and "false 0" is probably because while you print "true" and "false" as strings in your function, you return a bool, which if you print outside the function will be default print as "1" and "0". To overcome that, you can use std::boolalpha as discussed here: Converting bool to text in C++
As for converting your algorithm to a recursive one, I'm afraid that's off topic for Stack Overflow until you try it yourself.
Like John said, you're printing the cout (standard out) Strings, not integers (1/0). Also agree with the off-topic, you need to suggest a solution and ask for help/recommendations/feedback. There's a heap of tutorials on the net about how to it.
But if you want to recurse, you should create an array3 whose length is the same size array1, whereas you'll recurse over array2 to check if any elements of array2 exist (either as objects or as values) in array1. You'll need a function that produces an array and takes in arrays (why are you using vectors?) and then iterates over the 2nd array, passing array1, array3 and current index value as arguments.
Fibonacci recursive problem is taught in just about every programming course in Uni (or at least it should be), so it's a good starting point to look at.
Recursion function of this :
// it will return true if vector is present
// i is pointer for a
// j is pointer for b
bool subVector(vector<int>& a, vector<int> b,i,j)
{
if( i<a.size() && j<b.size()
{
if(a[i]==b[i])
{
return subVector(a,b,i+1,j+1)
}
else
{
return subVector(a,b,0,j+1)
}
}
else
{
if(i>a.size())
{
return true;
}
else{
return false;
}
}
}
// Calling
subVector(a,b,0,0);
Note : Not Compiled.

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>())