Dukales

In-place permutation (O(n) time, O(1) memory)

Nov 12th, 2012
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <iterator>
  3. #include <vector>
  4. #include <algorithm>
  5.  
  6. #include <cstdlib>
  7. #include <cassert>
  8.  
  9. template< class V >
  10. struct perfect_shuffle_permutation_forward
  11. {
  12.  
  13.     typedef typename V::iterator I;
  14.     typedef typename V::size_type SIZE;
  15.  
  16.     void operator () (V & v) const
  17.     {
  18.         operator () (v.begin(), v.size());
  19.     }
  20.  
  21.     void operator () (I const begin, I const end) const
  22.     {
  23.         operator () (begin, std::distance(begin, end));
  24.     }
  25.  
  26.     void operator () (I const begin, SIZE const size) const
  27.     {
  28.         if (size < 3) {
  29.             return;
  30.         }
  31.         SIZE sub_size(1);
  32.         while (sub_size * 3 < size) { // std::pwr(3, (int)std::floor(std::log(size) / std::log(3)))
  33.             sub_size *= 3;
  34.         }
  35.         SIZE path(0);
  36.         SIZE rest(size);
  37.         while (sub_size > 0) {
  38.             cycle_leader(begin + (size - rest), sub_size);
  39.             path += sub_size;
  40.             rest -= (sub_size + 1);
  41.             if (!(rest > 1)) {
  42.                 break;
  43.             }
  44.             while (!(rest > sub_size)) {
  45.                 sub_size /= 3;
  46.             }
  47.         }
  48.         I curr(begin + (size - rest));
  49.         sub_size = 1;
  50.         while (path > 0) {
  51.             while ((path % 3) != 0) {
  52.                 --path;
  53.                 SIZE const h((sub_size + 1) / 2);
  54.                 if (rest > 0) {
  55.                     std::rotate(curr - h, curr, curr + rest);
  56.                     rest += h;
  57.                 } else {
  58.                     rest = h;
  59.                 }
  60.                 curr -= 2 * h;
  61.             }
  62.             path /= 3;
  63.             sub_size *= 3;
  64.         }
  65.     }
  66.  
  67. private :
  68.  
  69.     void cycle_leader(I const & begin, SIZE const & size) const
  70.     {
  71.         for (SIZE p(1); p < size; p *= 3) {
  72.             permutation permutation_(p, size);
  73.             I current(begin + p);
  74.             auto const leader(*current);
  75.             while (++permutation_) {
  76.                 I const next(begin + permutation_);
  77.                 *current = *next;
  78.                 current = next;
  79.             }
  80.             *current = leader;
  81.         }
  82.     }
  83.  
  84.     struct permutation
  85.     {
  86.  
  87.         permutation(SIZE const & leader_, SIZE  const & size_)
  88.             : leader(leader_)
  89.             , current(leader_)
  90.             , size(size_)
  91.         { ; }
  92.  
  93.         bool operator ++ ()
  94.         {
  95.             current *= 2;
  96.             if (current > size) {
  97.                 current -= size;
  98.             }
  99.             return (current != leader);
  100.         }
  101.  
  102.         operator SIZE () const
  103.         {
  104.             return current;
  105.         }
  106.  
  107.     private :
  108.  
  109.         SIZE const & leader;
  110.         SIZE current;
  111.         SIZE const & size;
  112.  
  113.     };
  114.  
  115. };
  116.  
  117. template< class V >
  118. struct perfect_shuffle_permutation_backward
  119. {
  120.  
  121.     typedef typename V::iterator I;
  122.     typedef typename V::size_type SIZE;
  123.  
  124.     void operator () (V & v) const
  125.     {
  126.         operator () (v.begin(), v.size());
  127.     }
  128.  
  129.     void operator () (I const begin, I const end) const
  130.     {
  131.         operator () (begin, std::distance(begin, end));
  132.     }
  133.  
  134.     void operator () (I const begin, SIZE const size) const
  135.     {
  136.         SIZE sub_size;
  137.         for (SIZE offset(0); offset + 1 < size; offset += sub_size) {
  138.             sub_size = 1;
  139.             while (offset + sub_size * 3 < size) {
  140.                 sub_size *= 3;
  141.             }
  142.             I const current(begin + offset);
  143.             {
  144.                 SIZE const rest(size - offset);
  145.                 I const first(current + (sub_size + 1) / 2);
  146.                 I const middle(current + (rest / 2 + rest % 2));
  147.                 I const last(middle + (sub_size + 1) / 2);
  148.                 std::rotate(first, middle, last);
  149.             }
  150.             cycle_leader(current, sub_size);
  151.             ++sub_size;
  152.         }
  153.     }
  154.  
  155. private :
  156.  
  157.     void cycle_leader(I const & begin, SIZE const & size) const
  158.     {
  159.         for (SIZE p(1); p < size; p *= 3) {
  160.             permutation permutation_(p, size);
  161.             I current(begin + p);
  162.             auto const leader(*current);
  163.             while (++permutation_) {
  164.                 I const next(begin + permutation_);
  165.                 *current = *next;
  166.                 current = next;
  167.             }
  168.             *current = leader;
  169.         }
  170.     }
  171.  
  172.     struct permutation
  173.     {
  174.  
  175.         permutation(SIZE const & leader_, SIZE  const & size_)
  176.             : leader(leader_)
  177.             , current(leader_)
  178.             , size(size_)
  179.         { ; }
  180.  
  181.         bool operator ++ ()
  182.         {
  183.             if ((current % 2) != 0) {
  184.                 current += size;
  185.             }
  186.             current /= 2;
  187.             return (current != leader);
  188.         }
  189.  
  190.         operator SIZE () const
  191.         {
  192.             return current;
  193.         }
  194.  
  195.     private :
  196.  
  197.         SIZE const & leader;
  198.         SIZE current;
  199.         SIZE const & size;
  200.  
  201.     };
  202.  
  203. };
  204.  
  205. template< class V >
  206. struct test
  207. {
  208.  
  209.     typedef typename V::size_type SIZE;
  210.     typedef typename V::value_type F;
  211.     typedef perfect_shuffle_permutation_forward< V > PF;
  212.     typedef perfect_shuffle_permutation_backward< V > PB;
  213.  
  214.     bool operator () (SIZE const VECTOR_SIZE) const
  215.     {
  216.         V v;
  217.         v.reserve(VECTOR_SIZE);
  218.         for (SIZE i(0); i < v.capacity(); ++i) {
  219.             v.push_back(F(i));
  220.         }
  221.  
  222.         V w(v);
  223.  
  224.         //std::copy(v.begin(), v.end(), std::ostream_iterator< F >(std::cout, " "));
  225.         //std::cout << std::endl;
  226.  
  227.         PF perfect_shuffle_permutation_forward_;
  228.         perfect_shuffle_permutation_forward_(v);
  229.  
  230.         //std::copy(v.begin(), v.end(), std::ostream_iterator< F >(std::cout, " "));
  231.         //std::cout << std::endl;
  232.  
  233.         PB perfect_shuffle_permutation_backward_;
  234.         perfect_shuffle_permutation_backward_(v);
  235.  
  236.         //std::copy(v.begin(), v.end(), std::ostream_iterator< F >(std::cout, " "));
  237.         //std::cout << std::endl;
  238.  
  239.         return ((v.size() == w.size()) && std::equal(v.begin(), v.end(), w.begin()));
  240.     }
  241.  
  242. };
  243.  
  244. int main(int argc, char *argv[])
  245. {
  246.     typedef std::vector< int > V;
  247.     test< V > test_;
  248.  
  249.     for (std::size_t i(1); i <= std::numeric_limits< std::size_t >::max(); i *= 2) {
  250.         std::cout << "@ " << i << std::endl;
  251.         assert(test_(i));
  252.     }
  253.  
  254.     return EXIT_SUCCESS;
  255. }
Advertisement
Add Comment
Please, Sign In to add comment