#include <set>
#include <utility>
#include <iostream>
#include <algorithm>
using std:: make_pair ;
template < typename X, typename Y, typename Xless = std:: less < X> , typename Yless = std:: less < Y>>
class bimap
{
typedef std:: pair < X, Y> key_type;
typedef std:: pair < X, Y> value_type;
typedef typename std:: set < key_type> :: iterator iterator;
typedef typename std:: set < key_type> :: const_iterator const_iterator;
struct Xcomp
{
bool operator( ) ( X const & x1, X const & x2)
{
return ! Xless( ) ( x1, x2) && ! Xless( ) ( x2, x1) ;
}
} ;
struct Ycomp
{
bool operator( ) ( Y const & y1, Y const & y2)
{
return ! Yless( ) ( y1, y2) && ! Yless( ) ( y2, y1) ;
}
} ;
struct Fless
{ // prevents lexicographical comparison for std::pair, so that
// every .first value is unique as if it was in its own map
bool operator( ) ( key_type const & lhs, key_type const & rhs)
{
return Xless( ) ( lhs.first , rhs.first ) ;
}
} ;
/// key and value type are interchangeable
std:: set < std:: pair < X, Y> , Fless> _data;
public :
std:: pair < iterator, bool > insert( X const & x, Y const & y)
{
auto it = find_right( y) ;
if ( it == end( ) ) { // every .second value is unique
return _data.insert ( make_pair( x, y) ) ;
}
return make_pair( it, false ) ;
}
iterator find_left( X const & val)
{
return _data.find ( make_pair( val,Y( ) ) ) ;
}
iterator find_right( Y const & val)
{
return std:: find_if ( _data.begin ( ) , _data.end ( ) ,
[ & val] ( key_type const & kt)
{
return Ycomp( ) ( kt.second , val) ;
} ) ;
}
iterator end( ) { return _data.end ( ) ; }
iterator begin( ) { return _data.begin ( ) ; }
} ;
template < typename X, typename Y, typename In>
void PrintBimapInsertion( X const & x, Y const & y, In const & in)
{
if ( in.second ) {
std:: cout << "Inserted element ("
<< in.first - > first << ", " << in.first - > second << ")\n " ;
}
else {
std:: cout << "Could not insert (" << x << ", " << y << ") because (" <<
in.first - > first << ", " << in.first - > second << ") already exists\n " ;
}
}
int main( )
{
bimap< std:: string , int > mb;
PrintBimapInsertion( "A" , 1 , mb.insert ( "A" , 1 ) ) ;
PrintBimapInsertion( "A" , 2 , mb.insert ( "A" , 2 ) ) ;
PrintBimapInsertion( "b" , 2 , mb.insert ( "b" , 2 ) ) ;
PrintBimapInsertion( "z" , 2 , mb.insert ( "z" , 2 ) ) ;
auto it1 = mb.find_left ( "A" ) ;
if ( it1 ! = mb.end ( ) ) {
std:: cout << std:: endl << it1- > first << ", " << it1- > second << std:: endl ;
}
auto it2 = mb.find_right ( 2 ) ;
if ( it2 ! = mb.end ( ) ) {
std:: cout << std:: endl << it2- > first << ", " << it2- > second << std:: endl ;
}
return 0 ;
}
I2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGFsZ29yaXRobT4KCnVzaW5nIHN0ZDo6bWFrZV9wYWlyOwoKdGVtcGxhdGU8dHlwZW5hbWUgWCwgdHlwZW5hbWUgWSwgdHlwZW5hbWUgWGxlc3MgPSBzdGQ6Omxlc3M8WD4sIHR5cGVuYW1lIFlsZXNzID0gc3RkOjpsZXNzPFk+PgpjbGFzcyBiaW1hcAp7CiAgICB0eXBlZGVmIHN0ZDo6cGFpcjxYLCBZPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5X3R5cGU7CiAgICB0eXBlZGVmIHN0ZDo6cGFpcjxYLCBZPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVfdHlwZTsKICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjpzZXQ8a2V5X3R5cGU+OjppdGVyYXRvciAgICAgICBpdGVyYXRvcjsKICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjpzZXQ8a2V5X3R5cGU+Ojpjb25zdF9pdGVyYXRvciBjb25zdF9pdGVyYXRvcjsKCiAgICBzdHJ1Y3QgWGNvbXAKICAgIHsKICAgICAgICBib29sIG9wZXJhdG9yKCkoWCBjb25zdCAmeDEsIFggY29uc3QgJngyKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuICFYbGVzcygpKHgxLCB4MikgJiYgIVhsZXNzKCkoeDIsIHgxKTsKICAgICAgICB9CiAgICB9OwogICAgc3RydWN0IFljb21wCiAgICB7CiAgICAgICAgYm9vbCBvcGVyYXRvcigpKFkgY29uc3QgJnkxLCBZIGNvbnN0ICZ5MikKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAhWWxlc3MoKSh5MSwgeTIpICYmICFZbGVzcygpKHkyLCB5MSk7CiAgICAgICAgfQogICAgfTsKICAgIHN0cnVjdCBGbGVzcyAKICAgIHsgLy8gcHJldmVudHMgbGV4aWNvZ3JhcGhpY2FsIGNvbXBhcmlzb24gZm9yIHN0ZDo6cGFpciwgc28gdGhhdCAKICAgICAgICAvLyBldmVyeSAuZmlyc3QgdmFsdWUgaXMgdW5pcXVlIGFzIGlmIGl0IHdhcyBpbiBpdHMgb3duIG1hcAogICAgICAgIGJvb2wgb3BlcmF0b3IoKShrZXlfdHlwZSBjb25zdCAmbGhzLCBrZXlfdHlwZSBjb25zdCAmcmhzKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIFhsZXNzKCkobGhzLmZpcnN0LCByaHMuZmlyc3QpOwogICAgICAgIH0KICAgIH07CiAgICAvLy8ga2V5IGFuZCB2YWx1ZSB0eXBlIGFyZSBpbnRlcmNoYW5nZWFibGUKICAgIHN0ZDo6c2V0PHN0ZDo6cGFpcjxYLCBZPiwgRmxlc3M+IF9kYXRhOwoKcHVibGljOgogICAgc3RkOjpwYWlyPGl0ZXJhdG9yLCBib29sPiBpbnNlcnQoWCBjb25zdCAmeCwgWSBjb25zdCAmeSkKICAgIHsKICAgICAgICBhdXRvIGl0ID0gZmluZF9yaWdodCh5KTsKICAgICAgICBpZiAoaXQgPT0gZW5kKCkpIHsgLy8gZXZlcnkgLnNlY29uZCB2YWx1ZSBpcyB1bmlxdWUKICAgICAgICAgICAgcmV0dXJuIF9kYXRhLmluc2VydChtYWtlX3BhaXIoeCwgeSkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFrZV9wYWlyKGl0LCBmYWxzZSk7CiAgICB9CiAgICBpdGVyYXRvciBmaW5kX2xlZnQoWCBjb25zdCAmdmFsKQogICAgewogICAgICAgIHJldHVybiBfZGF0YS5maW5kKG1ha2VfcGFpcih2YWwsWSgpKSk7CiAgICB9CiAgICBpdGVyYXRvciBmaW5kX3JpZ2h0KFkgY29uc3QgJnZhbCkKICAgIHsKICAgICAgICByZXR1cm4gc3RkOjpmaW5kX2lmKF9kYXRhLmJlZ2luKCksIF9kYXRhLmVuZCgpLCAKICAgICAgICAgICAgWyZ2YWxdKGtleV90eXBlIGNvbnN0ICZrdCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBZY29tcCgpKGt0LnNlY29uZCwgdmFsKTsKICAgICAgICB9KTsKICAgIH0KICAgIGl0ZXJhdG9yIGVuZCgpICAgeyByZXR1cm4gX2RhdGEuZW5kKCk7ICAgfQogICAgaXRlcmF0b3IgYmVnaW4oKSB7IHJldHVybiBfZGF0YS5iZWdpbigpOyB9Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBYLCB0eXBlbmFtZSBZLCB0eXBlbmFtZSBJbj4Kdm9pZCBQcmludEJpbWFwSW5zZXJ0aW9uKFggY29uc3QgJngsIFkgY29uc3QgJnksIEluIGNvbnN0ICZpbikKewogICAgaWYgKGluLnNlY29uZCkgewogICAgICAgIHN0ZDo6Y291dCA8PCAiSW5zZXJ0ZWQgZWxlbWVudCAoIiAKICAgICAgICAgICAgPDwgaW4uZmlyc3QtPmZpcnN0IDw8ICIsICIgPDwgaW4uZmlyc3QtPnNlY29uZCA8PCAiKVxuIjsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHN0ZDo6Y291dCA8PCAiQ291bGQgbm90IGluc2VydCAoIiA8PCB4IDw8ICIsICIgPDwgeSA8PCAiKSBiZWNhdXNlICgiIDw8IAogICAgICAgICAgICBpbi5maXJzdC0+Zmlyc3QgPDwgIiwgIiA8PCBpbi5maXJzdC0+c2Vjb25kIDw8ICIpIGFscmVhZHkgZXhpc3RzXG4iOwogICAgfQp9CgoKaW50IG1haW4oKQp7CiAgICBiaW1hcDxzdGQ6OnN0cmluZywgaW50PiBtYjsKICAgIFByaW50QmltYXBJbnNlcnRpb24oIkEiLCAxLCBtYi5pbnNlcnQoIkEiLCAxKSApOwogICAgUHJpbnRCaW1hcEluc2VydGlvbigiQSIsIDIsIG1iLmluc2VydCgiQSIsIDIpICk7CiAgICBQcmludEJpbWFwSW5zZXJ0aW9uKCJiIiwgMiwgbWIuaW5zZXJ0KCJiIiwgMikpOwogICAgUHJpbnRCaW1hcEluc2VydGlvbigieiIsIDIsIG1iLmluc2VydCgieiIsIDIpKTsKCiAgICBhdXRvIGl0MSA9IG1iLmZpbmRfbGVmdCgiQSIpOwogICAgaWYgKGl0MSAhPSBtYi5lbmQoKSkgewogICAgICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGwgPDwgaXQxLT5maXJzdCA8PCAiLCAiIDw8IGl0MS0+c2Vjb25kIDw8IHN0ZDo6ZW5kbDsKICAgIH0KCiAgICBhdXRvIGl0MiA9IG1iLmZpbmRfcmlnaHQoMik7CiAgICBpZiAoaXQyICE9IG1iLmVuZCgpKSB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCBpdDItPmZpcnN0IDw8ICIsICIgPDwgaXQyLT5zZWNvbmQgPDwgc3RkOjplbmRsOwogICAgfQoKICAgIHJldHVybiAwOwp9