Find if one map is subset of another - c++

I have two STL maps std::map<int, int> foo = {{1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}; and std::map<int, int> bar = {{2, 0}, {4, 0}, {5, 0}};
I want to find if bar is a subset of foo.
Since the elements are sorted in map, I would think
to find the first element from bar in foo, and then find consecutive elements
from bar in foo from that location.
The problem here is I'm not able to figure out a way to do that with STL maps in cpp.
Can I reduce the search range in map for every find from a location in map to the end of the map?
I hope I explained the problem.

Use std::includes algorithm with a custom comparator that compares only the keys:
#include <map>
#include <algorithm>
#include <iostream>
int main()
{
std::map<int, int> foo = {{1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}};
std::map<int, int> bar = {{2, 0}, {4, 0}, {5, 0}};
typedef std::pair<int,int> pair;
std::cout <<
std::includes(foo.begin(), foo.end(), bar.begin(), bar.end(),
[](const pair& p1, const pair& p2)
{
return p1.first < p2.first;
});
}

You could extract key sets (set1 and set2) of both maps (foo and bar), and as long as they are sorted, you can do the following:
if (std::includes(set1.begin(), set1.end(),
set2.begin(), set2.end())) {
// ...
}
See std::includes.

A simple way is to use Boost.Range in combination with boost::includes:
using namespace boost::adaptors;
bool result = includes(foo | map_keys, bar | map_keys);
Here is how a minimal, complete program could look like (mapped values are disregarded):
#include <map>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
int main()
{
std::map<int, int> foo = {{1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}};
std::map<int, int> bar = {{2, 0}, {4, 0}, {5, 0}};
using namespace boost::adaptors;
std::cout << includes(foo | map_keys, bar | map_keys);
}
Here is a live example.

Related

How can I make a bool array that saves the positions of numbers that are larger than 0 in a 2D array?

I'm creating an algorithm that solves the Sudoku puzzle, but one of the requirements is that I have to create a bool array that locks the initial positions of any assigned number (In this case, any number that isn't 0) so that when the algorithm runs, it doesn't change the numbers that are "locked"
basically, the array below is the "puzzle" itself, I need to create a 2D bool array that saves the positions of the initially provided numbers so that the algorithm cannot change them later on when it runs
here's the code for the puzzle itself and the data structure:
#define N 9
typedef struct Coordinates
{
int row;
int column;
};
int sudokuArray[N][N] = {
{0,0,0,6,0,0,4,0,0},
{7,0,0,0,0,3,6,0,0},
{0,0,0,0,9,1,0,8,0},
{0,0,0,0,0,0,0,0,0},
{0,5,0,1,8,0,0,0,3},
{0,0,0,3,0,6,0,4,5},
{0,4,0,2,0,0,0,6,0},
{9,0,3,0,0,0,0,0,0},
{0,2,0,0,0,0,1,0,0}
};
You can do something a little bit less memory efficient but faster:
Instead of having an array of values, store array of structures of values and bool that tells if given position is mutable.
#include <cstdint>
#include <array>
// Prefer constexpr to macros
constexpr uint32_t size = 9;
struct sudoku_field
{
uint8_t value;
bool is_mutable;
};
std::array<std::array<sudoku_field, size>, size> sudoku_board
{
{ {0, 0}, {0, 0}, {0, 0}, {6, 1}, {0, 0}, {0, 0}, {4, 1}, {0, 0}, {0, 0} },
{ {7, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {3, 1}, {6, 1}, {0, 0}, {0, 0} },
...
}
This approach will provide constant lookup time when you need to test if field should be mutable.
Your approach would require a vector of positions, where every entry in that vector is immutable.
#include <vector>
#include <algorithm>
struct coordinates
{
int8_t row;
int8_t column;
};
std::vector<coordinates> immutable_positions;
// And this would be a test funciton
bool is_immutable(int8_t row, int8_t column)
{
auto res = std::find(std::begin(immutable_positions),
std::end(immutable_positions),
coordinates{row, column});
return res == std::end(immutable_positions);
}
You can do the exact same thing that you did for the sudoko puzzle.
Another option is to programmatically find which numbers are non-zero.
for(int i = 0; i < ROW_SIZE; ++i)
{
for(int j = 0; j < ROW_SIZE; ++j)
{
boolArray[i][j] = (sudokuArray[i][j] > 0);
}
}

Search within a big vector in C++

I have following vectors:
std::vector<A*> vec;
std::vector<std::pair<A*, A*>> vec_pair;
vec_pair size is much more than vec size. I would like to find a pair within vec_pair which both members are inside vec.
contents of the vec_pair are constant. However after each iteration the contents of the vec will change and I would like to do the test again.
I know I can do a for loop and do the check. However considering size difference and recurrence of the job, I am looking for a smart and efficient way to do it.
If you are not going to change content of vec, create an std::unordered_set<A*> with the same content and search for occurrences there. Searching in an unordered_set is approximately O(1), so this would be a simple win.
The easiest and the most efficient way to construct an unordered_set from a vector is to use the constructor taking two iterators:
unordered_set<A*> us(vec.begin(), vec.end());
You can use an unordered_set (you don't really need a map) which allows O(1) search and insert.
1) From vec you build an unordered_set<A*> S;
2) For each pair in vec_pair you can check if both elements are present in S
Something like the following will do the job in average O(vec_pair.size())
std::vector<A*> vec;
std::vector<std::pair<A*, A*>> vec_pair;
unordered_set<A*> S;
for(auto a: vec)
S.insert(a);
for(auto p : vec_pair){
if(s.find(p.first)!=S.end() &&
s.find(p.second)!=S.end())
{
//PAIR GOOD
}else{
//THIS PAIR IS NOT GOOD
}
}
vec_pair size is much more than vec size.
This should act as a clue to you to use std::map.
Put all the elements of vector vec inside a map : myMap[vec[i]] = 1;
Then go through each pair in vec_pair, and do
if (myMap.find(vec_pair[i].first != myMap.end()) &&
myMap.find(vec_pair[i].second != myMap.end()) )
{
return FOUND;
}
else
return NOT_FOUND;`
As commented by Gates, use unordered_map for faster operations.
I don't know yours exactly requirements but, if the order of element in vec_pair isn't important, I suppose you can substitute it with a std::multimap or, I suppose better, a std::unordered_multimap.
I mean (using a type A equal to int as example) that instead
using A = int;
std::vector<std::pair<A, A>> const vec_pair
{ {1, 1}, {1, 2}, {1, 3}, {1, 4},
{2, 1}, {2, 2}, {2, 3}, {2, 4},
{3, 1}, {3, 2}, {3, 3}, {3, 4},
{4, 1}, {4, 2}, {4, 3}, {4, 4} };
you can use
std::unordered_multimap<A, A> const cM
{ {1, 1}, {1, 2}, {1, 3}, {1, 4},
{2, 1}, {2, 2}, {2, 3}, {2, 4},
{3, 1}, {3, 2}, {3, 3}, {3, 4},
{4, 1}, {4, 2}, {4, 3}, {4, 4} };
If you need that vec_pair is a vector of pairs, using the fact that vec_pair is constant (I understand correctly?) you can contruct a constant unordered multimap.
The advantage of this solution is that if you find that a key of the map isn't in vec, you can avoid the test for all the values with the same key.
More: if construct a set (or, better, an unordered_set) starting from vec (that is little, if I understand correctly, you can check the pairs as follows
for ( auto ci = cM.cbegin() ; ci != cM.cend() ; )
{
auto val = ci->first;
auto cnt = cM.count(val);
if ( s.end() == s.find(val) )
{
for ( auto i = 0U ; i < cnt ; ++i )
++ci;
}
else for ( auto i = 0U ; i < cnt ; ++i, ++ci )
if ( s.end() != s.find(ci->second) )
std::cout << "- good for <" << val << ", " << ci->second
<< '>' << std::endl;
}
I know: isn't an elegant solution.
Another way is to use a combination of map and set (unorderd, better) and instead of
std::vector<std::pair<A, A>> const vec_pair
{ {1, 1}, {1, 2}, {1, 3}, {1, 4},
{2, 1}, {2, 2}, {2, 3}, {2, 4},
{3, 1}, {3, 2}, {3, 3}, {3, 4},
{4, 1}, {4, 2}, {4, 3}, {4, 4} };
use (or construct)
std::unordered_map<A, std::unordered_set<A>> const cM
{ {1, {1, 2, 3, 4}}, {2, {1, 2, 3, 4}},
{3, {1, 2, 3, 4}}, {4, {1, 2, 3, 4}} };
In this case, the search part is more elegant (IMHO)
for ( auto const & p : cM2 )
if ( s.end() != s.find(p.first) )
for ( auto const & sec : p.second )
if ( s.end() != s.find(sec) )
std::cout << "- good for <" << p.first << ", " << sec
<< '>' << std::endl;
The following is a full compilable example for both solutions
#include <vector>
#include <utility>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
int main()
{
using A = int;
std::unordered_multimap<A, A> const cM
{ {1, 1}, {1, 2}, {1, 3}, {1, 4},
{2, 1}, {2, 2}, {2, 3}, {2, 4},
{3, 1}, {3, 2}, {3, 3}, {3, 4},
{4, 1}, {4, 2}, {4, 3}, {4, 4} };
std::unordered_set<A> s { 4, 3 };
for ( auto ci = cM.cbegin() ; ci != cM.cend() ; )
{
auto val = ci->first;
auto cnt = cM.count(val);
if ( s.end() == s.find(val) )
{
for ( auto i = 0U ; i < cnt ; ++i )
++ci;
}
else for ( auto i = 0U ; i < cnt ; ++i, ++ci )
if ( s.end() != s.find(ci->second) )
std::cout << "- good for <" << val << ", " << ci->second
<< '>' << std::endl;
}
std::unordered_map<A, std::unordered_set<A>> const cM2
{ {1, {1, 2, 3, 4}}, {2, {1, 2, 3, 4}},
{3, {1, 2, 3, 4}}, {4, {1, 2, 3, 4}} };
for ( auto const & p : cM2 )
if ( s.end() != s.find(p.first) )
for ( auto const & sec : p.second )
if ( s.end() != s.find(sec) )
std::cout << "- good for <" << p.first << ", " << sec
<< '>' << std::endl;
}
How much smaller is vec than vec_pair? Is the square of the size of vec still much smaller than the size of vec_pair? If so, you make an unordered_set out of vec_pair, and then search it for every possible pair generated from two things from vec.
Why can't you sort the two containers? Can you make a sorted copy of each? If so, take a pointer to the start of both lists, and increment both looking for matches. You would still be O(size of vec_pair) but your constant would be really small -- often just a single pointer comparison.

C++ How to print this map std::map<int, pair<vector<pair<int, int>>, int>> [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I want to print pairs in map like:
std::map<int, pair<vector<pair<int, int>>, int>> Mymap;
Example for data in this map:
Mymap[0] = (0, ({ { 1, 3 }, { 1, 5 } }, 4))
Mymap[1] = (1, ({ { 2, 3 }, { 3, 7 }, { 1, 3 } }, 8))
I want to print pairs like:
{ 1, 3 }, { 1, 5 }
{ 2, 3 }, { 3, 7 }, { 1, 3 }
So, a good first step is to actually write the example data such that it matches the type you've requested.
Perhaps something like:
Mymap[0] = {{{1, 3}, {1, 5}}, 4};
Mymap[1] = {{{2, 3}, {3, 7}, {1, 3}}, 8};
Then, we can pretty easily iterate over this...
#include <map>
#include <vector>
#include <iostream>
int main() {
std::map<int, std::pair<std::vector<std::pair<int, int>>, int>> Mymap;
Mymap[0] = {{{1, 3}, {1, 5}}, 4};
Mymap[1] = {{{2, 3}, {3, 7}, {1, 3}}, 8};
for (const auto & pair : Mymap) {
for (const auto & pair : pair.second.first) {
std::cout << "{" << pair.first << ", " << pair.second << "}, ";
}
std::cout << "\n";
}
}
Which outputs:
{1, 3}, {1, 5},
{2, 3}, {3, 7}, {1, 3},
I do not see any sense in your question, what exactly are you trying to do ?
Anyhow, this code should be able to do it:
std::map<int, pair<vector<pair<int, int>>, int>> Mymap;
Mymap[0] = {{{1, 3}, {1, 5}}, 4};
Mymap[1] = {{{2, 3}, {3, 7}, {1, 3}}, 8};
map<int, pair<vector<pair<int, int>>, int>>::iterator it;
for (it=Mymap.begin(); it!=Mymap.end(); it++){
pair<vector<pair<int, int>>, int> myPair=it->second;
vector<pair<int, int>> myVec=myPair.first;
for (int i=0; i<myVec.size(); i++){
cout<< "{ " << myVec[i].first << ","<<myVec[i].second<< " }, ";
}
cout<<endl;
}

concat std::vector and initializer list

In c++11 you can do this wonderful syntax:
vector<int> numbers = {1, 2, 3};
Is there a way to concatenate a further initializer list onto an existing vector?
numbers.??? ({4, 5, 6});
or
std::??? (numbers, {4, 5, 6});
You can use std::vector::insert for that:
#include <vector>
vector<int> numbers = {1, 2, 3};
numbers.insert( numbers.end(), {4, 5, 6} );
Use std::vector::insert:
numbers.insert(numbers.end(), {4, 5, 6});
You can use std::vector::insert. Link to example code
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> a = {1,2,3};
a.insert(a.end(), {4,5,6});
for(int &i : a) {
cout << i << " ";
}
cout << endl;
return 0;
}

The most neat way to remove all but the last element with the same key from a sorted std::vector?

I have a vector of structures {key; value}, sorted by key:
{ {0, 1}, {0, 2}, {1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2} }
I need to erase all but the last elements with the same key. The result should be:
{ {0, 2}, {1, 3}, {2, 2} }
What is the most neat way to do this? Which STL algorithms can I use? Apparently, this task doesn't fit remove-erase idiom.
A naive but efficient solution is to iterate over the vector, copying the relevant elements into a new vector.
An alternative is to use std::unique (with an appropriate predicate). As you want to preserve the last element in each group, you'd need to use a reverse iterator.
I words, the algorithm needed would be:
iterate the container backwards
if you encoutner a new key, leave the element,
if you encoutner a key you already had, remove the element.
in code:
#include <vector>
#include <iostream>
#include <algorithm>
struct S { int key; int value; };
int main() {
std::vector<S> vec{ {0, 1}, {0, 2}, {1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2} };
auto lastKey = std::numeric_limits<int>::max();
auto rLast = std::remove_if(vec.rbegin(), vec.rend(), [&lastKey](S const& s) -> bool {
if (s.key == lastKey) return true;
lastKey = s.key;
return false;
});
vec.erase(begin(vec),rLast.base());
for (auto& s : vec) {
std::cout << '{' << s.key << ',' << s.value << '}';
}
}
Or using std::unique as recommended in the other answer:
auto rLast = std::unique(vec.rbegin(), vec.rend() [](S const& s1, S const& s2) {
return s1.key == s2.key;
});
vec.erase(vec.begin(), rLast.base());
If you use an std::map the problem just disappears:
std::map<int, int> theMap;
// insert the elements of { {0, 1}, {0, 2}, {1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2} }
theMap[0] = 1;
theMap[0] = 2;
theMap[1] = 1;
theMap[1] = 2;
theMap[1] = 3;
theMap[2] = 1;
theMap[2] = 2;
// result: { {0, 2}, {1, 3}, {2, 2} }