Dukales

http://stackoverflow.com/questions/18320566/

Aug 19th, 2013
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.89 KB | None | 0 0
  1. #!/usr/bin/env bash -vex
  2. # cls ; bash self.bash 2>&1 | tee self.log | less
  3. WARN="-W -Wall -Wextra -Werror"
  4. g++ -x c++ - -std=gnu++1y $WARN -Og -g -o a <<__EOF && ./a && echo -e "\e[1;32msucceeded\e[0m" || echo -e "\e[1;31mfailed\e[0m"
  5. #include <list>
  6. #include <tuple>
  7. #include <map>
  8. #include <functional>
  9.  
  10. #include <string>
  11.  
  12. #include <cstdlib>
  13. #include <cassert>
  14.  
  15. template< typename A, typename B >
  16. class bijection
  17. {
  18.  
  19.     using data_type = std::list< std::tuple< A const, B const > >;
  20.  
  21. public :
  22.  
  23.     using iterator = typename data_type::iterator;
  24.     using const_iterator = typename data_type::const_iterator;
  25.  
  26. private :
  27.  
  28.     using direct_mapping_type = std::map< std::reference_wrapper< A const >, iterator, std::less< A const & > > ;
  29.     using inverse_mapping_type = std::map< std::reference_wrapper< B const >, iterator, std::less< B const & > >;
  30.     using direct_iterator = typename direct_mapping_type::iterator;
  31.     using inverse_iterator = typename inverse_mapping_type::iterator;
  32.  
  33. public :
  34.  
  35.     auto size() const { return data_.size(); }
  36.    
  37.     auto begin() { return data_.begin(); }
  38.     auto cbegin() const { return data_.cbegin(); }
  39.     auto end() { return data_.end(); }
  40.     auto cend() const { return data_.cend(); }
  41.  
  42.     auto find(A const & a)
  43.     {
  44.         auto const direct = direct_mapping_.find(a);
  45.         if (direct == direct_mapping_.end()) {
  46.             return data_.end();
  47.         } else {
  48.             return direct->second;
  49.         }
  50.     }
  51.  
  52.     auto find(B const & b)
  53.     {
  54.         auto const inverse = inverse_mapping_.find(b);
  55.         if (inverse == inverse_mapping_.end()) {
  56.             return data_.end();
  57.         } else {
  58.             return inverse->second;
  59.         }
  60.     }
  61.  
  62.     auto erase(iterator pos)
  63.     {
  64.         auto const & element = *pos;
  65.         direct_mapping_.erase(std::get< 0 >(element));
  66.         inverse_mapping_.erase(std::get< 1 >(element));
  67.         return data_.erase(pos);
  68.     }
  69.  
  70.     template< typename X, typename Y >
  71.     std::tuple< iterator, bool, bool > insert(X && x, Y && y)
  72.     {
  73.         direct_iterator direct = direct_mapping_.find(x);
  74.         inverse_iterator inverse = inverse_mapping_.find(y);
  75.         bool const d = (direct != direct_mapping_.end());
  76.         bool const i = (inverse != inverse_mapping_.end());
  77.         if (d && i) {
  78.             iterator ix = inverse->second;
  79.             iterator iy = direct->second;
  80.             inverse_mapping_.erase(inverse);
  81.             direct_mapping_.erase(direct);
  82.             if (ix != iy) {
  83.                 inverse_mapping_.erase(std::get< 1 >(*iy));
  84.                 direct_mapping_.erase(std::get< 0 >(*ix));
  85.                 data_.erase(iy);
  86.                 data_.erase(ix);
  87.             } else {
  88.                 data_.erase(ix); // iy
  89.             }
  90.         } else if (d) {
  91.             iterator iy = direct->second;
  92.             direct_mapping_.erase(direct);
  93.             inverse_mapping_.erase(std::get< 1 >(*iy));
  94.             data_.erase(iy);
  95.         } else if (i) {
  96.             iterator ix = inverse->second;
  97.             inverse_mapping_.erase(inverse);
  98.             direct_mapping_.erase(std::get< 0 >(*ix));
  99.             data_.erase(ix);
  100.         }
  101.         data_.emplace_back(std::forward< X >(x), std::forward< Y >(y));
  102.         auto const & element = data_.back();
  103.         iterator it = --data_.end();
  104.         direct_mapping_.emplace(std::get< 0 >(element), it);
  105.         inverse_mapping_.emplace(std::get< 1 >(element), it);
  106.         return std::make_tuple(it, d, i);
  107.     }
  108.  
  109. private :
  110.  
  111.     data_type data_;
  112.     direct_mapping_type direct_mapping_;
  113.     inverse_mapping_type inverse_mapping_;
  114.  
  115. };
  116.  
  117. int main()
  118. {
  119.     using A = std::size_t;
  120.     using B = std::string;
  121.     using M = bijection< A, B >;
  122.     M m;
  123.     assert(1 == (m.insert(A(111), B("111")), m.size()));
  124.     assert(1 == (m.insert(A(111), B("111")), m.size()));
  125.     assert(2 == (m.insert(A(222), B("222")), m.size()));
  126.     assert(3 == (m.insert(A(333), B("333")), m.size()));
  127.     assert(2 == (m.insert(A(222), B("111")), m.size()));
  128.     assert(3 == (m.insert(A(111), B("222")), m.size()));
  129.     assert(2 == (m.insert(A(111), B("111")), m.size()));
  130.     assert(1 == (m.insert(A(333), B("111")), m.size()));
  131.     assert(1 == (m.insert(A(333), B("333")), m.size()));
  132.     assert(1 == (m.insert(A(111), B("333")), m.size()));
  133.     assert(0 == (m.erase(m.find(A(111))), m.size()));
  134.     return EXIT_SUCCESS;
  135. }
  136. __EOF
Add Comment
Please, Sign In to add comment