Allamo Olsson
Allamo Olsson

Reputation: 319

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!

Upvotes: 2

Views: 79

Answers (3)

Marek R
Marek R

Reputation: 37697

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

Upvotes: 1

super
super

Reputation: 12928

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

Upvotes: 1

Caleth
Caleth

Reputation: 62704

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

Upvotes: 4

Related Questions