├── README.md ├── combinations.h ├── combinations.html ├── fig1.tiff └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | See https://howardhinnant.github.io/combinations/combinations.html 2 | -------------------------------------------------------------------------------- /combinations.h: -------------------------------------------------------------------------------- 1 | #ifndef COMBINATIONS_H 2 | #define COMBINATIONS_H 3 | 4 | // (C) Copyright Howard Hinnant 2005-2011. 5 | // Use, modification and distribution are subject to the Boost Software License, 6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt). 8 | // 9 | // See http://www.boost.org/libs/type_traits for most recent version including documentation. 10 | 11 | // Details are in namespace detail. Every effort has been made to make 12 | // combine_discontinuous and permute as fast as possible. They minimize the number 13 | // of swaps that are performed. Everything else builds on these two primitives. 14 | // The most complicated algorithm is for_each_reversible_permutation. But it 15 | // builds on combine_discontinuous and permute and I believe represents a minimum 16 | // number of swaps. Without care, algorithms such as for_each_reversible_permutation 17 | // will take longer than for_each_permutation instead of the intended half the time. 18 | 19 | // Speed is everything. Lest you could just use std::next_permutation and manually 20 | // eliminate duplicate permutations. If the implementation fails in being orders 21 | // of magnitude faster than that, then it has failed miserably. 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace detail 30 | { 31 | 32 | // Rotates two discontinuous ranges to put *first2 where *first1 is. 33 | // If last1 == first2 this would be equivalent to rotate(first1, first2, last2), 34 | // but instead the rotate "jumps" over the discontinuity [last1, first2) - 35 | // which need not be a valid range. 36 | // In order to make it faster, the length of [first1, last1) is passed in as d1, 37 | // and d2 must be the length of [first2, last2). 38 | // In a perfect world the d1 > d2 case would have used swap_ranges and 39 | // reverse_iterator, but reverse_iterator is too inefficient. 40 | template 41 | void 42 | rotate_discontinuous(BidirIter first1, BidirIter last1, 43 | typename std::iterator_traits::difference_type d1, 44 | BidirIter first2, BidirIter last2, 45 | typename std::iterator_traits::difference_type d2) 46 | { 47 | using std::swap; 48 | if (d1 <= d2) 49 | std::rotate(first2, std::swap_ranges(first1, last1, first2), last2); 50 | else 51 | { 52 | BidirIter i1 = last1; 53 | while (first2 != last2) 54 | swap(*--i1, *--last2); 55 | std::rotate(first1, i1, last1); 56 | } 57 | } 58 | 59 | // Rotates the three discontinuous ranges to put *first2 where *first1 is. 60 | // Just like rotate_discontinuous, except the second range is now represented by 61 | // two discontinuous ranges: [first2, last2) + [first3, last3). 62 | template 63 | void 64 | rotate_discontinuous3(BidirIter first1, BidirIter last1, 65 | typename std::iterator_traits::difference_type d1, 66 | BidirIter first2, BidirIter last2, 67 | typename std::iterator_traits::difference_type d2, 68 | BidirIter first3, BidirIter last3, 69 | typename std::iterator_traits::difference_type d3) 70 | { 71 | rotate_discontinuous(first1, last1, d1, first2, last2, d2); 72 | if (d1 <= d2) 73 | rotate_discontinuous(std::next(first2, d2 - d1), last2, d1, first3, last3, d3); 74 | else 75 | { 76 | rotate_discontinuous(std::next(first1, d2), last1, d1 - d2, first3, last3, d3); 77 | rotate_discontinuous(first2, last2, d2, first3, last3, d3); 78 | } 79 | } 80 | 81 | // Call f() for each combination of the elements [first1, last1) + [first2, last2) 82 | // swapped/rotated into the range [first1, last1). As long as f() returns 83 | // false, continue for every combination and then return [first1, last1) and 84 | // [first2, last2) to their original state. If f() returns true, return 85 | // immediately. 86 | // Does the absolute mininum amount of swapping to accomplish its task. 87 | // If f() always returns false it will be called (d1+d2)!/(d1!*d2!) times. 88 | template 89 | bool 90 | combine_discontinuous(BidirIter first1, BidirIter last1, 91 | typename std::iterator_traits::difference_type d1, 92 | BidirIter first2, BidirIter last2, 93 | typename std::iterator_traits::difference_type d2, 94 | Function& f, 95 | typename std::iterator_traits::difference_type d = 0) 96 | { 97 | typedef typename std::iterator_traits::difference_type D; 98 | using std::swap; 99 | if (d1 == 0 || d2 == 0) 100 | return f(); 101 | if (d1 == 1) 102 | { 103 | for (BidirIter i2 = first2; i2 != last2; ++i2) 104 | { 105 | if (f()) 106 | return true; 107 | swap(*first1, *i2); 108 | } 109 | } 110 | else 111 | { 112 | BidirIter f1p = std::next(first1); 113 | BidirIter i2 = first2; 114 | for (D d22 = d2; i2 != last2; ++i2, --d22) 115 | { 116 | if (combine_discontinuous(f1p, last1, d1-1, i2, last2, d22, f, d+1)) 117 | return true; 118 | swap(*first1, *i2); 119 | } 120 | } 121 | if (f()) 122 | return true; 123 | if (d != 0) 124 | rotate_discontinuous(first1, last1, d1, std::next(first2), last2, d2-1); 125 | else 126 | rotate_discontinuous(first1, last1, d1, first2, last2, d2); 127 | return false; 128 | } 129 | 130 | // A binder for binding arguments to call combine_discontinuous 131 | template 132 | class call_combine_discontinuous 133 | { 134 | typedef typename std::iterator_traits::difference_type D; 135 | Function f_; 136 | BidirIter first1_; 137 | BidirIter last1_; 138 | D d1_; 139 | BidirIter first2_; 140 | BidirIter last2_; 141 | D d2_; 142 | 143 | public: 144 | call_combine_discontinuous( 145 | BidirIter first1, BidirIter last1, 146 | D d1, 147 | BidirIter first2, BidirIter last2, 148 | D d2, 149 | Function& f) 150 | : f_(f), first1_(first1), last1_(last1), d1_(d1), 151 | first2_(first2), last2_(last2), d2_(d2) {} 152 | 153 | bool operator()() 154 | { 155 | return combine_discontinuous(first1_, last1_, d1_, first2_, last2_, d2_, f_); 156 | } 157 | }; 158 | 159 | // See combine_discontinuous3 160 | template 161 | bool 162 | combine_discontinuous3_(BidirIter first1, BidirIter last1, 163 | typename std::iterator_traits::difference_type d1, 164 | BidirIter first2, BidirIter last2, 165 | typename std::iterator_traits::difference_type d2, 166 | BidirIter first3, BidirIter last3, 167 | typename std::iterator_traits::difference_type d3, 168 | Function& f, 169 | typename std::iterator_traits::difference_type d = 0) 170 | { 171 | typedef typename std::iterator_traits::difference_type D; 172 | using std::swap; 173 | if (d1 == 1) 174 | { 175 | for (BidirIter i2 = first2; i2 != last2; ++i2) 176 | { 177 | if (f()) 178 | return true; 179 | swap(*first1, *i2); 180 | } 181 | if (f()) 182 | return true; 183 | swap(*first1, *std::prev(last2)); 184 | swap(*first1, *first3); 185 | for (BidirIter i2 = std::next(first3); i2 != last3; ++i2) 186 | { 187 | if (f()) 188 | return true; 189 | swap(*first1, *i2); 190 | } 191 | } 192 | else 193 | { 194 | BidirIter f1p = std::next(first1); 195 | BidirIter i2 = first2; 196 | for (D d22 = d2; i2 != last2; ++i2, --d22) 197 | { 198 | if (combine_discontinuous3_(f1p, last1, d1-1, i2, last2, d22, first3, 199 | last3, d3, f, d+1)) 200 | return true; 201 | swap(*first1, *i2); 202 | } 203 | i2 = first3; 204 | for (D d22 = d3; i2 != last3; ++i2, --d22) 205 | { 206 | if (combine_discontinuous(f1p, last1, d1-1, i2, last3, d22, f, d+1)) 207 | return true; 208 | swap(*first1, *i2); 209 | } 210 | } 211 | if (f()) 212 | return true; 213 | if (d1 == 1) 214 | swap(*std::prev(last2), *first3); 215 | if (d != 0) 216 | { 217 | if (d2 > 1) 218 | rotate_discontinuous3(first1, last1, d1, std::next(first2), last2, d2-1, first3, last3, d3); 219 | else 220 | rotate_discontinuous(first1, last1, d1, first3, last3, d3); 221 | } 222 | else 223 | rotate_discontinuous3(first1, last1, d1, first2, last2, d2, first3, last3, d3); 224 | return false; 225 | } 226 | 227 | // Like combine_discontinuous, but swaps/rotates each combination out of 228 | // [first1, last1) + [first2, last2) + [first3, last3) into [first1, last1). 229 | // If f() always returns false, it is called (d1+d2+d3)!/(d1!*(d2+d3)!) times. 230 | template 231 | bool 232 | combine_discontinuous3(BidirIter first1, BidirIter last1, 233 | typename std::iterator_traits::difference_type d1, 234 | BidirIter first2, BidirIter last2, 235 | typename std::iterator_traits::difference_type d2, 236 | BidirIter first3, BidirIter last3, 237 | typename std::iterator_traits::difference_type d3, 238 | Function& f) 239 | { 240 | typedef call_combine_discontinuous F; 241 | F fbc(first2, last2, d2, first3, last3, d3, f); // BC 242 | return combine_discontinuous3_(first1, last1, d1, first2, last2, d2, first3, last3, d3, fbc); 243 | } 244 | 245 | // See permute 246 | template 247 | bool 248 | permute_(BidirIter first1, BidirIter last1, 249 | typename std::iterator_traits::difference_type d1, 250 | Function& f) 251 | { 252 | using std::swap; 253 | switch (d1) 254 | { 255 | case 0: 256 | case 1: 257 | return f(); 258 | case 2: 259 | if (f()) 260 | return true; 261 | swap(*first1, *std::next(first1)); 262 | return f(); 263 | case 3: 264 | { 265 | if (f()) 266 | return true; 267 | BidirIter f2 = std::next(first1); 268 | BidirIter f3 = std::next(f2); 269 | swap(*f2, *f3); 270 | if (f()) 271 | return true; 272 | swap(*first1, *f3); 273 | swap(*f2, *f3); 274 | if (f()) 275 | return true; 276 | swap(*f2, *f3); 277 | if (f()) 278 | return true; 279 | swap(*first1, *f2); 280 | swap(*f2, *f3); 281 | if (f()) 282 | return true; 283 | swap(*f2, *f3); 284 | return f(); 285 | } 286 | } 287 | BidirIter fp1 = std::next(first1); 288 | for (BidirIter p = fp1; p != last1; ++p) 289 | { 290 | if (permute_(fp1, last1, d1-1, f)) 291 | return true; 292 | std::reverse(fp1, last1); 293 | swap(*first1, *p); 294 | } 295 | return permute_(fp1, last1, d1-1, f); 296 | } 297 | 298 | // Calls f() for each permutation of [first1, last1) 299 | // Divided into permute and permute_ in a (perhaps futile) attempt to 300 | // squeeze a little more performance out of it. 301 | template 302 | bool 303 | permute(BidirIter first1, BidirIter last1, 304 | typename std::iterator_traits::difference_type d1, 305 | Function& f) 306 | { 307 | using std::swap; 308 | switch (d1) 309 | { 310 | case 0: 311 | case 1: 312 | return f(); 313 | case 2: 314 | { 315 | if (f()) 316 | return true; 317 | BidirIter i = std::next(first1); 318 | swap(*first1, *i); 319 | if (f()) 320 | return true; 321 | swap(*first1, *i); 322 | } 323 | break; 324 | case 3: 325 | { 326 | if (f()) 327 | return true; 328 | BidirIter f2 = std::next(first1); 329 | BidirIter f3 = std::next(f2); 330 | swap(*f2, *f3); 331 | if (f()) 332 | return true; 333 | swap(*first1, *f3); 334 | swap(*f2, *f3); 335 | if (f()) 336 | return true; 337 | swap(*f2, *f3); 338 | if (f()) 339 | return true; 340 | swap(*first1, *f2); 341 | swap(*f2, *f3); 342 | if (f()) 343 | return true; 344 | swap(*f2, *f3); 345 | if (f()) 346 | return true; 347 | swap(*first1, *f3); 348 | } 349 | break; 350 | default: 351 | BidirIter fp1 = std::next(first1); 352 | for (BidirIter p = fp1; p != last1; ++p) 353 | { 354 | if (permute_(fp1, last1, d1-1, f)) 355 | return true; 356 | std::reverse(fp1, last1); 357 | swap(*first1, *p); 358 | } 359 | if (permute_(fp1, last1, d1-1, f)) 360 | return true; 361 | std::reverse(first1, last1); 362 | break; 363 | } 364 | return false; 365 | } 366 | 367 | // Creates a functor with no arguments which calls f_(first_, last_). 368 | // Also has a variant that takes two It and ignores them. 369 | template 370 | class bound_range 371 | { 372 | Function f_; 373 | It first_; 374 | It last_; 375 | public: 376 | bound_range(Function f, It first, It last) 377 | : f_(f), first_(first), last_(last) {} 378 | 379 | bool 380 | operator()() 381 | { 382 | return f_(first_, last_); 383 | } 384 | 385 | bool 386 | operator()(It, It) 387 | { 388 | return f_(first_, last_); 389 | } 390 | }; 391 | 392 | // A binder for binding arguments to call permute 393 | template 394 | class call_permute 395 | { 396 | typedef typename std::iterator_traits::difference_type D; 397 | Function f_; 398 | It first_; 399 | It last_; 400 | D d_; 401 | public: 402 | call_permute(Function f, It first, It last, D d) 403 | : f_(f), first_(first), last_(last), d_(d) {} 404 | 405 | bool 406 | operator()() 407 | { 408 | return permute(first_, last_, d_, f_); 409 | } 410 | }; 411 | 412 | } // detail 413 | 414 | template 415 | Function 416 | for_each_combination(BidirIter first, BidirIter mid, 417 | BidirIter last, Function f) 418 | { 419 | detail::bound_range wfunc(f, first, mid); 420 | detail::combine_discontinuous(first, mid, std::distance(first, mid), 421 | mid, last, std::distance(mid, last), 422 | wfunc); 423 | return std::move(f); 424 | } 425 | 426 | template 427 | UInt 428 | gcd(UInt x, UInt y) 429 | { 430 | while (y != 0) 431 | { 432 | UInt t = x % y; 433 | x = y; 434 | y = t; 435 | } 436 | return x; 437 | } 438 | 439 | template 440 | inline 441 | typename std::enable_if 442 | < 443 | std::is_unsigned::value, 444 | void 445 | >::type 446 | check_non_negative(Int, Int) 447 | { 448 | } 449 | 450 | template 451 | typename std::enable_if 452 | < 453 | !std::is_unsigned::value, 454 | void 455 | >::type 456 | check_non_negative(Int d1, Int d2) 457 | { 458 | if (d1 < Int(0) || d2 < Int(0)) 459 | throw std::invalid_argument("expected non-negative argument"); 460 | } 461 | 462 | template 463 | UInt 464 | count_each_combination(UInt d1, UInt d2) 465 | { 466 | check_non_negative(d1, d2); 467 | if (d2 < d1) 468 | std::swap(d1, d2); 469 | if (d1 == UInt()) 470 | return 1; 471 | if (d1 > std::numeric_limits::max() - d2) 472 | throw std::overflow_error("overflow in count_each_combination"); 473 | UInt n = d1 + d2; 474 | UInt r = n; 475 | --n; 476 | for (UInt k = UInt(2); k <= d1; ++k, --n) 477 | { 478 | // r = r * n / k, known to not not have truncation error 479 | UInt g = gcd(r, k); 480 | r /= g; 481 | UInt t = n / (k / g); 482 | if (r > std::numeric_limits::max() / t) 483 | throw std::overflow_error("overflow in count_each_combination"); 484 | r *= t; 485 | } 486 | return r; 487 | } 488 | 489 | template 490 | std::uintmax_t 491 | count_each_combination(BidirIter first, BidirIter mid, BidirIter last) 492 | { 493 | return count_each_combination 494 | (std::distance(first, mid), std::distance(mid, last)); 495 | } 496 | 497 | // For each of the permutation algorithms, use for_each_combination (or 498 | // combine_discontinuous) to handle the "r out of N" part of the algorithm. 499 | // Thus each permutation algorithm has to deal only with an "N out of N" 500 | // problem. I.e. For each combination of r out of N items, permute it thusly. 501 | template 502 | Function 503 | for_each_permutation(BidirIter first, BidirIter mid, 504 | BidirIter last, Function f) 505 | { 506 | typedef typename std::iterator_traits::difference_type D; 507 | typedef detail::bound_range Wf; 508 | typedef detail::call_permute PF; 509 | Wf wfunc(f, first, mid); 510 | D d1 = std::distance(first, mid); 511 | PF pf(wfunc, first, mid, d1); 512 | detail::combine_discontinuous(first, mid, d1, 513 | mid, last, std::distance(mid, last), 514 | pf); 515 | return std::move(f); 516 | } 517 | 518 | template 519 | UInt 520 | count_each_permutation(UInt d1, UInt d2) 521 | { 522 | // return (d1+d2)!/d2! 523 | check_non_negative(d1, d2); 524 | if (d1 > std::numeric_limits::max() - d2) 525 | throw std::overflow_error("overflow in count_each_permutation"); 526 | UInt n = d1 + d2; 527 | UInt r(1); 528 | for (; n > d2; --n) 529 | { 530 | if (r > std::numeric_limits::max() / n) 531 | throw std::overflow_error("overflow in count_each_permutation"); 532 | r *= n; 533 | } 534 | return r; 535 | } 536 | 537 | template 538 | std::uintmax_t 539 | count_each_permutation(BidirIter first, BidirIter mid, BidirIter last) 540 | { 541 | return count_each_permutation(static_cast(std::distance(first, mid)), 542 | static_cast(std::distance(mid, last))); 543 | } 544 | 545 | namespace detail 546 | { 547 | 548 | // Adapt functor to permute over [first+1, last) 549 | // A circular permutation of N items is done by holding the first item and 550 | // permuting [first+1, last). 551 | template 552 | class circular_permutation 553 | { 554 | typedef typename std::iterator_traits::difference_type D; 555 | 556 | Function f_; 557 | D s_; 558 | 559 | public: 560 | explicit circular_permutation(Function f, D s) : f_(f), s_(s) {} 561 | 562 | bool 563 | operator()(BidirIter first, BidirIter last) 564 | { 565 | if (s_ <= 1) 566 | return f_(first, last); 567 | bound_range f(f_, first, last); 568 | return permute(std::next(first), last, s_ - 1, f); 569 | } 570 | }; 571 | 572 | } // detail 573 | 574 | template 575 | Function 576 | for_each_circular_permutation(BidirIter first, 577 | BidirIter mid, 578 | BidirIter last, Function f) 579 | { 580 | for_each_combination(first, mid, last, detail::circular_permutation(f, std::distance(first, mid))); 582 | return std::move(f); 583 | } 584 | 585 | template 586 | UInt 587 | count_each_circular_permutation(UInt d1, UInt d2) 588 | { 589 | // return d1 > 0 ? (d1+d2)!/(d1*d2!) : 1 590 | check_non_negative(d1, d2); 591 | if (d1 == UInt()) 592 | return 1; 593 | UInt r; 594 | if (d1 <= d2) 595 | { 596 | try 597 | { 598 | r = count_each_combination(d1, d2); 599 | } 600 | catch (const std::overflow_error&) 601 | { 602 | throw std::overflow_error("overflow in count_each_circular_permutation"); 603 | } 604 | for (--d1; d1 > UInt(1); --d1) 605 | { 606 | if (r > std::numeric_limits::max()/d1) 607 | throw std::overflow_error("overflow in count_each_circular_permutation"); 608 | r *= d1; 609 | } 610 | } 611 | else 612 | { // functionally equivalent but faster algorithm 613 | if (d1 > std::numeric_limits::max() - d2) 614 | throw std::overflow_error("overflow in count_each_circular_permutation"); 615 | UInt n = d1 + d2; 616 | r = 1; 617 | for (; n > d1; --n) 618 | { 619 | if (r > std::numeric_limits::max()/n) 620 | throw std::overflow_error("overflow in count_each_circular_permutation"); 621 | r *= n; 622 | } 623 | for (--n; n > d2; --n) 624 | { 625 | if (r > std::numeric_limits::max()/n) 626 | throw std::overflow_error("overflow in count_each_circular_permutation"); 627 | r *= n; 628 | } 629 | } 630 | return r; 631 | } 632 | 633 | template 634 | std::uintmax_t 635 | count_each_circular_permutation(BidirIter first, BidirIter mid, BidirIter last) 636 | { 637 | return count_each_circular_permutation 638 | (std::distance(first, mid), std::distance(mid, last)); 639 | } 640 | 641 | namespace detail 642 | { 643 | 644 | // Difficult!!! See notes for operator(). 645 | template 646 | class reversible_permutation 647 | { 648 | Function f_; 649 | Size s_; 650 | 651 | public: 652 | reversible_permutation(Function f, Size s) : f_(f), s_(s) {} 653 | 654 | template 655 | bool 656 | operator()(BidirIter first, BidirIter last); 657 | }; 658 | 659 | // rev1 looks like call_permute 660 | template 661 | class rev1 662 | { 663 | typedef typename std::iterator_traits::difference_type D; 664 | 665 | Function f_; 666 | BidirIter first1_; 667 | BidirIter last1_; 668 | D d1_; 669 | 670 | public: 671 | rev1(Function f, BidirIter first, BidirIter last, D d) 672 | : f_(f), first1_(first), last1_(last), d1_(d) {} 673 | 674 | bool operator()() 675 | { 676 | return permute(first1_, last1_, d1_, f_); 677 | } 678 | }; 679 | 680 | // For each permutation in [first1, last1), 681 | // call f() for each permutation of [first2, last2). 682 | template 683 | class rev2 684 | { 685 | typedef typename std::iterator_traits::difference_type D; 686 | 687 | Function f_; 688 | BidirIter first1_; 689 | BidirIter last1_; 690 | D d1_; 691 | BidirIter first2_; 692 | BidirIter last2_; 693 | D d2_; 694 | 695 | public: 696 | rev2(Function f, BidirIter first1, BidirIter last1, D d1, 697 | BidirIter first2, BidirIter last2, D d2) 698 | : f_(f), first1_(first1), last1_(last1), d1_(d1), 699 | first2_(first2), last2_(last2), d2_(d2) {} 700 | 701 | bool operator()() 702 | { 703 | call_permute f(f_, first2_, last2_, d2_); 704 | return permute(first1_, last1_, d1_, f); 705 | } 706 | }; 707 | 708 | // For each permutation in [first1, last1), 709 | // and for each permutation of [first2, last2) 710 | // call f() for each permutation of [first3, last3). 711 | template 712 | class rev3 713 | { 714 | typedef typename std::iterator_traits::difference_type D; 715 | 716 | Function f_; 717 | BidirIter first1_; 718 | BidirIter last1_; 719 | D d1_; 720 | BidirIter first2_; 721 | BidirIter last2_; 722 | D d2_; 723 | BidirIter first3_; 724 | BidirIter last3_; 725 | D d3_; 726 | 727 | public: 728 | rev3(Function f, BidirIter first1, BidirIter last1, D d1, 729 | BidirIter first2, BidirIter last2, D d2, 730 | BidirIter first3, BidirIter last3, D d3) 731 | : f_(f), first1_(first1), last1_(last1), d1_(d1), 732 | first2_(first2), last2_(last2), d2_(d2), 733 | first3_(first3), last3_(last3), d3_(d3) {} 734 | 735 | bool operator()() 736 | { 737 | rev2 f(f_, first2_, last2_, d2_, first3_, last3_, d3_); 738 | return permute(first1_, last1_, d1_, f); 739 | } 740 | }; 741 | 742 | // There are simpler implementations. I believe the simpler ones are far more 743 | // expensive. 744 | template 745 | template 746 | bool 747 | reversible_permutation::operator()(BidirIter first, 748 | BidirIter last) 749 | { 750 | typedef rev2, BidirIter> F2; 751 | typedef rev3, BidirIter> F3; 752 | // When the range is 0 - 2, then this is just a combination of N out of N 753 | // elements. 754 | if (s_ < 3) 755 | return f_(first, last); 756 | using std::swap; 757 | // Hold the first element steady and call f_(first, last) for each 758 | // permutation in [first+1, last). 759 | BidirIter a = std::next(first); 760 | bound_range f(f_, first, last); 761 | if (permute(a, last, s_-1, f)) 762 | return true; 763 | // Beginning with the first element, swap the previous element with the 764 | // next element. For each swap, call f_(first, last) for each 765 | // permutation of the discontinuous range: 766 | // [prior to the orignal element] + [after the original element]. 767 | Size s2 = s_ / 2; 768 | BidirIter am1 = first; 769 | BidirIter ap1 = std::next(a); 770 | for (Size i = 1; i < s2; ++i, ++am1, ++a, ++ap1) 771 | { 772 | swap(*am1, *a); 773 | F2 f2(f, first, a, i, ap1, last, s_ - i - 1); 774 | if (combine_discontinuous(first, a, i, ap1, last, s_ - i - 1, f2)) 775 | return true; 776 | } 777 | // If [first, last) has an even number of elements, then fix it up to the 778 | // original permutation. 779 | if (2 * s2 == s_) 780 | { 781 | std::rotate(first, am1, a); 782 | } 783 | // else if the range has length 3, we need one more call and the fix is easy. 784 | else if (s_ == 3) 785 | { 786 | swap(*am1, *a); 787 | if (f_(first, last)) 788 | return true; 789 | swap(*am1, *a); 790 | } 791 | // else the range is an odd number greater than 3. We need to permute 792 | // through exactly half of the permuations with the original element in 793 | // the middle. 794 | else 795 | { 796 | // swap the original first element into the middle, and hold the current 797 | // first element steady. This creates a discontinuous range: 798 | // [first+1, middle) + [middle+1, last). Run through all permutations 799 | // of that discontinuous range. 800 | swap(*am1, *a); 801 | BidirIter b = first; 802 | BidirIter bp1 = std::next(b); 803 | F2 f2(f, bp1, a, s2-1, ap1, last, s_ - s2 - 1); 804 | if (combine_discontinuous(bp1, a, s2-1, ap1, last, s_ - s2 - 1, f2)) 805 | return true; 806 | // Swap the current first element into every place from first+1 to middle-1. 807 | // For each location, hold it steady to create the following discontinuous 808 | // range (made of 3 ranges): [first, b-1) + [b+1, middle) + [middle+1, last). 809 | // For each b in [first+1, middle-1), run through all permutations of 810 | // the discontinuous ranges. 811 | b = bp1; 812 | ++bp1; 813 | BidirIter bm1 = first; 814 | for (Size i = 1; i < s2-1; ++i, ++bm1, ++b, ++bp1) 815 | { 816 | swap(*bm1, *b); 817 | F3 f3(f, first, b, i, bp1, a, s2-i-1, ap1, last, s_ - s2 - 1); 818 | if (combine_discontinuous3(first, b, i, bp1, a, s2-i-1, ap1, last, s_-s2-1, f3)) 819 | return true; 820 | } 821 | // swap b into into middle-1, creates a discontinuous range: 822 | // [first, middle-1) + [middle+1, last). Run through all permutations 823 | // of that discontinuous range. 824 | swap(*bm1, *b); 825 | F2 f21(f, first, b, s2-1, ap1, last, s_ - s2 - 1); 826 | if (combine_discontinuous(first, b, s2-1, ap1, last, s_ - s2 - 1, f21)) 827 | return true; 828 | // Revert [first, last) to original order 829 | std::reverse(first, b); 830 | std::reverse(first, ap1); 831 | } 832 | return false; 833 | } 834 | 835 | } // detail 836 | 837 | template 838 | Function 839 | for_each_reversible_permutation(BidirIter first, 840 | BidirIter mid, 841 | BidirIter last, Function f) 842 | { 843 | typedef typename std::iterator_traits::difference_type D; 844 | for_each_combination(first, mid, last, 845 | detail::reversible_permutation(f, 846 | std::distance(first, mid))); 847 | return std::move(f); 848 | } 849 | 850 | template 851 | UInt 852 | count_each_reversible_permutation(UInt d1, UInt d2) 853 | { 854 | // return d1 > 1 ? (d1+d2)!/(2*d2!) : (d1+d2)!/d2! 855 | check_non_negative(d1, d2); 856 | if (d1 > std::numeric_limits::max() - d2) 857 | throw std::overflow_error("overflow in count_each_reversible_permutation"); 858 | UInt n = d1 + d2; 859 | UInt r(1); 860 | if (d1 > UInt(1)) 861 | { 862 | r = n; 863 | if ((n & UInt(1)) == UInt(0)) 864 | r /= UInt(2); 865 | --n; 866 | UInt t = n; 867 | if ((t & UInt(1)) == UInt(0)) 868 | t /= UInt(2); 869 | if (r > std::numeric_limits::max() / t) 870 | throw std::overflow_error("overflow in count_each_reversible_permutation"); 871 | r *= t; 872 | --n; 873 | } 874 | for (; n > d2; --n) 875 | { 876 | if (r > std::numeric_limits::max() / n) 877 | throw std::overflow_error("overflow in count_each_reversible_permutation"); 878 | r *= n; 879 | } 880 | return r; 881 | } 882 | 883 | template 884 | std::uintmax_t 885 | count_each_reversible_permutation(BidirIter first, BidirIter mid, BidirIter last) 886 | { 887 | return count_each_reversible_permutation 888 | (std::distance(first, mid), std::distance(mid, last)); 889 | } 890 | 891 | namespace detail 892 | { 893 | 894 | // Adapt functor to permute over [first+1, last) 895 | // A reversible circular permutation of N items is done by holding the first 896 | // item and reverse-permuting [first+1, last). 897 | template 898 | class reverse_circular_permutation 899 | { 900 | typedef typename std::iterator_traits::difference_type D; 901 | 902 | Function f_; 903 | D s_; 904 | 905 | public: 906 | explicit reverse_circular_permutation(Function f, D s) : f_(f), s_(s) {} 907 | 908 | bool 909 | operator()(BidirIter first, BidirIter last) 910 | { 911 | if (s_ == 1) 912 | return f_(first, last); 913 | typedef bound_range BoundFunc; 914 | BoundFunc f(f_, first, last); 915 | BidirIter n = std::next(first); 916 | return reversible_permutation(f, std::distance(n, last))(n, last); 917 | } 918 | }; 919 | 920 | } // detail 921 | 922 | template 923 | Function 924 | for_each_reversible_circular_permutation(BidirIter first, 925 | BidirIter mid, 926 | BidirIter last, Function f) 927 | { 928 | for_each_combination(first, mid, last, detail::reverse_circular_permutation(f, std::distance(first, mid))); 930 | return std::move(f); 931 | } 932 | 933 | template 934 | UInt 935 | count_each_reversible_circular_permutation(UInt d1, UInt d2) 936 | { 937 | // return d1 == 0 ? 1 : d1 <= 2 ? (d1+d2)!/(d1*d2!) : (d1+d2)!/(2*d1*d2!) 938 | check_non_negative(d1, d2); 939 | UInt r; 940 | try 941 | { 942 | r = count_each_combination(d1, d2); 943 | } 944 | catch (const std::overflow_error&) 945 | { 946 | throw std::overflow_error("overflow in count_each_reversible_circular_permutation"); 947 | } 948 | if (d1 > UInt(3)) 949 | { 950 | for (--d1; d1 > UInt(2); --d1) 951 | { 952 | if (r > std::numeric_limits::max()/d1) 953 | throw std::overflow_error("overflow in count_each_reversible_circular_permutation"); 954 | r *= d1; 955 | } 956 | } 957 | return r; 958 | } 959 | 960 | template 961 | std::uintmax_t 962 | count_each_reversible_circular_permutation(BidirIter first, BidirIter mid, 963 | BidirIter last) 964 | { 965 | return count_each_reversible_circular_permutation 966 | (std::distance(first, mid), std::distance(mid, last)); 967 | } 968 | 969 | #endif // COMBINATIONS_H 970 | -------------------------------------------------------------------------------- /combinations.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Combinations and Permutations 6 | 20 | 21 | 22 | 23 |
24 | Document number: Dxxxx=xx-xxxx
25 |
26 | Howard Hinnant
27 | 28 | 2011-07-02 29 |
30 |
31 |

Combinations and Permutations

32 | 33 |

Contents

34 | 35 | 43 | 44 |

Introduction

45 | 46 |

47 | It doesn't happen very often, but every once in awhile one needs to iterate over 48 | all of the combinations or permutations of a set of objects. Or more 49 | specifically, given a set of N objects, you want to consider r 50 | of them at a time (for each combination or permutation). The standard library 51 | offers next_permutation, but this offering alone has a few drawbacks: 52 |

53 | 54 |
    55 |
  • 56 | next_permutation only offers permutations of N objects taken 57 | N at a time. If you only need to consider permutations of length 58 | r chosen from a list of length N then you can save a factor of 59 | (n-r)! by iterating over only the permutations you need. If r 60 | is small compared to N this can easily be several orders of magnitude 61 | faster than iterating over all N! permutations. 62 |
  • 63 |
  • 64 | If one only needs permutations, but not the reverse permutation, a factor 65 | of 2 can be saved by iterating only over reversible permutations. 66 |
  • 67 |
  • 68 | If your permutations are of a circular nature, you can save a factor of r 69 | by iterating over only distinct circular permutations. 70 |
  • 71 |
  • 72 | If your permutations are of a circular nature and it doesn't matter 73 | whether your permutation goes in a clockwise or counter-clockwise direction, 74 | then iterating only over distinct reversible, circular permutations can save 75 | a factor of 2r iterations compared to iterating over all N! 76 | permutations. 77 |
  • 78 |
  • 79 | If you're examining permutations of length r out of a list of length 80 | N and order doesn't matter at all in each list of length r, 81 | then it is far cheaper to iterate only over combinations of the N 82 | items taken r at a time (by a factor of r!). 83 |
  • 84 |
  • 85 | The user interface of next_permutation is potentially expensive: 86 | for each iteration the algorithm must do a search for the next iteration. When 87 | iterating N items taken r at a time, and when the number of 88 | iterations is far less than N! (as it will be for many practical 89 | problems), then the time spent finding the next iteration using a 90 | next_permutation-style interface can completely swamp the time you 91 | spend actually visiting each permutation. 92 |
  • 93 |
  • 94 | To use next_permutation, the sequence must be LessThanComparable 95 | and in sorted order. These requirements can be inconvenient, even impractical, 96 | and are completely unnecessary. 97 |
  • 98 |
99 | 100 |

101 | Below is a solution to each of these problems and more. The following generic 102 | algorithms permit a client to visit every combination or permuation of a 103 | sequence of length N, r items at time. 104 |

105 | 106 |
 107 | template <class BidirIter, class Function>
 108 | Function
 109 | for_each_permutation(BidirIter first,
 110 |                      BidirIter mid,
 111 |                      BidirIter last,
 112 |                      Function f);
 113 | 
 114 | template <class BidirIter, class Function>
 115 | Function
 116 | for_each_reversible_permutation(BidirIter first,
 117 |                                 BidirIter mid,
 118 |                                 BidirIter last,
 119 |                                 Function f);
 120 | 
 121 | template <class BidirIter, class Function>
 122 | Function
 123 | for_each_circular_permutation(BidirIter first,
 124 |                               BidirIter mid,
 125 |                               BidirIter last,
 126 |                               Function f);
 127 | 
 128 | template <class BidirIter, class Function>
 129 | Function
 130 | for_each_reversible_circular_permutation(BidirIter first,
 131 |                                          BidirIter mid,
 132 |                                          BidirIter last,
 133 |                                          Function f);
 134 | 
 135 | template <class BidirIter, class Function>
 136 | Function
 137 | for_each_combination(BidirIter first,
 138 |                      BidirIter mid,
 139 |                      BidirIter last,
 140 |                      Function f);
 141 | 
142 | 143 | 144 |

145 | These each follow a for_each style: The algorithm calls a user 146 | supplied function object for each combination/permutation in the sequence: 147 | f(begin, end). That function object can of course maintain state. The 148 | sequence need not be sorted, nor even contain unique objects. The algorithms do 149 | not consider the value of the sequence elements at all. That is, the element 150 | type need not support LessThanComparable nor 151 | EqualityComparable. Furthermore the algorithms follow three additional 152 | rules: 153 |

154 | 155 |
    156 |
  1. 157 | On normal (non-exceptional) completion, the sequence is always left in the 158 | original order. 159 |
  2. 160 | 161 |
  3. 162 |

    163 | The functor is always called with [first, mid). This enables the 164 | functor to also access the elements not in the sequence if it is aware of the 165 | sequence: [mid, last). This can come in handy when dealing 166 | with nested combination/permutation problems where for each permutation you 167 | also need to compute combinations and/or permutations on those elements 168 | not selected. 169 |

    170 |
  4. 171 | 172 |
  5. 173 |

    174 | The functor should return true or false: 175 |

    176 |
      177 |
    • 178 | true if the functor wishes to break out of the for_each_ loop. 179 |
    • 180 |
    • 181 | Otherwise false. 182 |
    • 183 |
    184 |
  6. 185 | 186 |
187 | 188 |

189 | The following generic algorithms take a (preferably unsigned) integral type and 190 | return the number of combinations or permutations that exist. Traditionally 191 | these functions represent functions such as nCr 192 | and nPr. This API breaks with tradition 193 | concerning the definition of n. These functions compute: 194 | d1+d2Cd1, and 195 | d1+d2Pd1, and the related variations for 196 | reversible and circular permuations. The rationale for this API is to avoid 197 | invalid inputs. For example if we input n and r from 198 | nCr, then we would have to check to make sure 199 | that the precondition n ≥ r is true, and if not throw an 200 | invalid_argument exception. But with the inputs d1 and 201 | d2, which represent distance(first, mid) and 202 | distance(mid, last) respectively, there is no opportunity for invalid 203 | inputs as long as we stick to unsigned integral types. However overflow is a 204 | very real possibility. And if signed integral types are input (or a type 205 | emulating signed integral types), then negative arguments will result in an 206 | invalid_argument exception. 207 |

208 | 209 |
 210 | template <class UInt>
 211 | UInt
 212 | count_each_combination(UInt d1, UInt d2);
 213 | 
 214 | template <class UInt>
 215 | UInt
 216 | count_each_permutation(UInt d1, UInt d2);
 217 | 
 218 | template <class UInt>
 219 | UInt
 220 | count_each_circular_permutation(UInt d1, UInt d2);
 221 | 
 222 | template <class UInt>
 223 | UInt
 224 | count_each_reversible_permutation(UInt d1, UInt d2);
 225 | 
 226 | template <class UInt>
 227 | UInt
 228 | count_each_reversible_circular_permutation(UInt d1, UInt d2);
 229 | 
230 | 231 |

232 | Each of the above algorithms avoids intermediate overflow. That is, if the 233 | final answer is representable as a UInt, then they will return the 234 | correct answer. Otherwise they will throw a std::overflow_error. This 235 | noisy overflow protection is necessary as these functions can easily overflow. 236 | For example count_each_combination(33ull, 34ull) returns 237 | 14,226,520,737,620,288,370. But 238 | count_each_combination(33ull, 35ull) overflows for a 64 bit 239 | unsigned long long. Without overflow protection, the returned result 240 | will look quite reasonable to the casual observer and overflow is likely to 241 | happen accidentally, go unnoticed, and cause further problems in program logic 242 | which will be more difficult to diagnose. 243 |

244 | 245 |

246 | Furthermore the following convenience functions are provided in order to more 247 | easily "preflight" ranges sent to the for_each_* algorithms. The 248 | reason that the UInt overloads of these algorithms exist is so that you 249 | don't have to create a range to compute 250 | 3000C2. Instead you can simply call 251 | count_each_combination(2ull, 2998ull) (for example). 252 |

253 | 254 |
 255 | template <class BidirIter>
 256 | std::uintmax_t
 257 | count_each_combination(BidirIter first,
 258 |                        BidirIter mid,
 259 |                        BidirIter last);
 260 | 
 261 | 
 262 | template <class BidirIter>
 263 | std::uintmax_t
 264 | count_each_permutation(BidirIter first,
 265 |                        BidirIter mid,
 266 |                        BidirIter last);
 267 | 
 268 | template <class BidirIter>
 269 | std::uintmax_t
 270 | count_each_circular_permutation(BidirIter first,
 271 |                                 BidirIter mid,
 272 |                                 BidirIter last);
 273 | 
 274 | template <class BidirIter>
 275 | std::uintmax_t
 276 | count_each_reversible_permutation(BidirIter first,
 277 |                                   BidirIter mid,
 278 |                                   BidirIter last);
 279 | 
 280 | template <class BidirIter>
 281 | std::uintmax_t
 282 | count_each_reversible_circular_permutation(BidirIter first,
 283 |                                            BidirIter mid,
 284 |                                            BidirIter last);
 285 | 
286 | 287 |

Examples

288 | 289 |

290 | Below an example simply fills a vector with consecutive integers, and calls 291 | for_each_permutation on a functor that will print out the permutation. 292 | The functor will also print out items not in the permutation after a trailing 293 | '|'. The functor also counts the number of permutations visited so 294 | that the client can query that amount after the call to 295 | for_each_permutation. 296 |

297 | 298 |
 299 | #include <iostream>
 300 | #include <vector>
 301 | #include <numeric>
 302 | #include <cstdint>
 303 | #include <cassert>
 304 | 
 305 | // print out a range separated by commas,
 306 | //    return number of values printed.
 307 | template <class It>
 308 | unsigned
 309 | display(It begin, It end)
 310 | {
 311 |     unsigned r = 0;
 312 |     if (begin != end)
 313 |     {
 314 |         std::cout << *begin;
 315 |         ++r;
 316 |         for (++begin; begin != end; ++begin)
 317 |         {
 318 |             std::cout << ", " << *begin;
 319 |             ++r;
 320 |         }
 321 |     }
 322 |     return r;
 323 | }
 324 | 
 325 | // functor called for each permutation
 326 | class f
 327 | {
 328 |     unsigned len;
 329 |     std::uint64_t count;
 330 | public:
 331 |     explicit f(unsigned l) : len(l), count(0) {}
 332 | 
 333 |     template <class It>
 334 |         bool operator()(It first, It last)  // called for each permutation
 335 |         {
 336 |             // count the number of times this is called
 337 |             ++count;
 338 |             // print out [first, mid) surrounded with [ ... ]
 339 |             std::cout << "[ ";
 340 |             unsigned r = display(first, last);
 341 |             // If [mid, last) is not empty, then print it out too
 342 |             //     prefixed by " | "
 343 |             if (r < len)
 344 |             {
 345 |                 std::cout << " | ";
 346 |                 display(last, std::next(last, len - r));
 347 |             }
 348 |             std::cout << " ]\n";
 349 |             return false;  // Don't break out of the loop
 350 |         }
 351 | 
 352 |     operator std::uint64_t() const {return count;}
 353 | };
 354 | 
 355 | int main()
 356 | {
 357 |     const int r = 3;
 358 |     const int n = 5;
 359 |     std::vector<int> v(n);
 360 |     std::iota(v.begin(), v.end(), 0);
 361 |     std::uint64_t count = for_each_permutation(v.begin(),
 362 |                                                v.begin() + r,
 363 |                                                v.end(),
 364 |                                                f(v.size()));
 365 |     // print out "---" to the correct length for the above output
 366 |     unsigned e = 3 * r + 2;
 367 |     if (r < v.size())
 368 |         e += 1 + 3 * (v.size() - r);
 369 |     for (unsigned i = 0; i < e; ++i)
 370 |         std::cout << '-';
 371 |     // print out the permuted vector to show that it has the original order
 372 |     std::cout << "\n[ ";
 373 |     display(v.begin(), v.end());
 374 |     std::cout << " ]\n";
 375 |     // sanity check
 376 |     assert(count == count_each_permutation(v.begin(), v.begin() + r, v.end()));
 377 |     // print out summary of what has happened,
 378 |     //   using 'count' from functor state returned from for_each_permutation algorithm.
 379 |     std::cout << "Found " << count << " permutations of " << v.size()
 380 |               << " objects taken " << r << " at a time.\n";
 381 | }
 382 | 
383 | 384 |

385 | And this is the output of this program: 386 |

387 | 388 |
 389 | [ 0, 1, 2 | 3, 4 ]
 390 | [ 0, 2, 1 | 3, 4 ]
 391 | [ 1, 0, 2 | 3, 4 ]
 392 | [ 1, 2, 0 | 3, 4 ]
 393 | [ 2, 0, 1 | 3, 4 ]
 394 | [ 2, 1, 0 | 3, 4 ]
 395 | [ 0, 1, 3 | 2, 4 ]
 396 | [ 0, 3, 1 | 2, 4 ]
 397 | [ 1, 0, 3 | 2, 4 ]
 398 | [ 1, 3, 0 | 2, 4 ]
 399 | [ 3, 0, 1 | 2, 4 ]
 400 | [ 3, 1, 0 | 2, 4 ]
 401 | [ 0, 1, 4 | 2, 3 ]
 402 | [ 0, 4, 1 | 2, 3 ]
 403 | [ 1, 0, 4 | 2, 3 ]
 404 | [ 1, 4, 0 | 2, 3 ]
 405 | [ 4, 0, 1 | 2, 3 ]
 406 | [ 4, 1, 0 | 2, 3 ]
 407 | [ 0, 2, 3 | 1, 4 ]
 408 | [ 0, 3, 2 | 1, 4 ]
 409 | [ 2, 0, 3 | 1, 4 ]
 410 | [ 2, 3, 0 | 1, 4 ]
 411 | [ 3, 0, 2 | 1, 4 ]
 412 | [ 3, 2, 0 | 1, 4 ]
 413 | [ 0, 2, 4 | 1, 3 ]
 414 | [ 0, 4, 2 | 1, 3 ]
 415 | [ 2, 0, 4 | 1, 3 ]
 416 | [ 2, 4, 0 | 1, 3 ]
 417 | [ 4, 0, 2 | 1, 3 ]
 418 | [ 4, 2, 0 | 1, 3 ]
 419 | [ 0, 3, 4 | 1, 2 ]
 420 | [ 0, 4, 3 | 1, 2 ]
 421 | [ 3, 0, 4 | 1, 2 ]
 422 | [ 3, 4, 0 | 1, 2 ]
 423 | [ 4, 0, 3 | 1, 2 ]
 424 | [ 4, 3, 0 | 1, 2 ]
 425 | [ 1, 2, 3 | 0, 4 ]
 426 | [ 1, 3, 2 | 0, 4 ]
 427 | [ 2, 1, 3 | 0, 4 ]
 428 | [ 2, 3, 1 | 0, 4 ]
 429 | [ 3, 1, 2 | 0, 4 ]
 430 | [ 3, 2, 1 | 0, 4 ]
 431 | [ 1, 2, 4 | 0, 3 ]
 432 | [ 1, 4, 2 | 0, 3 ]
 433 | [ 2, 1, 4 | 0, 3 ]
 434 | [ 2, 4, 1 | 0, 3 ]
 435 | [ 4, 1, 2 | 0, 3 ]
 436 | [ 4, 2, 1 | 0, 3 ]
 437 | [ 1, 3, 4 | 0, 2 ]
 438 | [ 1, 4, 3 | 0, 2 ]
 439 | [ 3, 1, 4 | 0, 2 ]
 440 | [ 3, 4, 1 | 0, 2 ]
 441 | [ 4, 1, 3 | 0, 2 ]
 442 | [ 4, 3, 1 | 0, 2 ]
 443 | [ 2, 3, 4 | 0, 1 ]
 444 | [ 2, 4, 3 | 0, 1 ]
 445 | [ 3, 2, 4 | 0, 1 ]
 446 | [ 3, 4, 2 | 0, 1 ]
 447 | [ 4, 2, 3 | 0, 1 ]
 448 | [ 4, 3, 2 | 0, 1 ]
 449 | ------------------
 450 | [ 0, 1, 2, 3, 4 ]
 451 | Found 60 permutations of 5 objects taken 3 at a time.
 452 | 
453 | 454 |

455 | The above list can be cut in half by instead calling: 456 |

457 | 458 |
 459 | for_each_reversible_permutation(v.begin(), v.begin() + r, v.end(), f(v.size()));
 460 | 
 461 | [ 0, 1, 2 | 3, 4 ]
 462 | [ 0, 2, 1 | 3, 4 ]
 463 | [ 1, 0, 2 | 3, 4 ]
 464 | [ 0, 1, 3 | 2, 4 ]
 465 | [ 0, 3, 1 | 2, 4 ]
 466 | [ 1, 0, 3 | 2, 4 ]
 467 | [ 0, 1, 4 | 2, 3 ]
 468 | [ 0, 4, 1 | 2, 3 ]
 469 | [ 1, 0, 4 | 2, 3 ]
 470 | [ 0, 2, 3 | 1, 4 ]
 471 | [ 0, 3, 2 | 1, 4 ]
 472 | [ 2, 0, 3 | 1, 4 ]
 473 | [ 0, 2, 4 | 1, 3 ]
 474 | [ 0, 4, 2 | 1, 3 ]
 475 | [ 2, 0, 4 | 1, 3 ]
 476 | [ 0, 3, 4 | 1, 2 ]
 477 | [ 0, 4, 3 | 1, 2 ]
 478 | [ 3, 0, 4 | 1, 2 ]
 479 | [ 1, 2, 3 | 0, 4 ]
 480 | [ 1, 3, 2 | 0, 4 ]
 481 | [ 2, 1, 3 | 0, 4 ]
 482 | [ 1, 2, 4 | 0, 3 ]
 483 | [ 1, 4, 2 | 0, 3 ]
 484 | [ 2, 1, 4 | 0, 3 ]
 485 | [ 1, 3, 4 | 0, 2 ]
 486 | [ 1, 4, 3 | 0, 2 ]
 487 | [ 3, 1, 4 | 0, 2 ]
 488 | [ 2, 3, 4 | 0, 1 ]
 489 | [ 2, 4, 3 | 0, 1 ]
 490 | [ 3, 2, 4 | 0, 1 ]
 491 | ------------------
 492 | [ 0, 1, 2, 3, 4 ]
 493 | Found 30 permutations of 5 objects taken 3 at a time.
 494 | 
495 | 496 |

497 | For example [ 2, 1, 0 ] is not found in the above list. 498 |

499 | 500 |

501 | By instead calling: 502 |

503 | 504 |
 505 | for_each_circular_permutation(v.begin(), v.begin() + r, v.end(), f(v.size()));
 506 | 
507 | 508 |

509 | the original list can be cut by a third: 510 |

511 | 512 |
 513 | [ 0, 1, 2 | 3, 4 ]
 514 | [ 0, 2, 1 | 3, 4 ]
 515 | [ 0, 1, 3 | 2, 4 ]
 516 | [ 0, 3, 1 | 2, 4 ]
 517 | [ 0, 1, 4 | 2, 3 ]
 518 | [ 0, 4, 1 | 2, 3 ]
 519 | [ 0, 2, 3 | 1, 4 ]
 520 | [ 0, 3, 2 | 1, 4 ]
 521 | [ 0, 2, 4 | 1, 3 ]
 522 | [ 0, 4, 2 | 1, 3 ]
 523 | [ 0, 3, 4 | 1, 2 ]
 524 | [ 0, 4, 3 | 1, 2 ]
 525 | [ 1, 2, 3 | 0, 4 ]
 526 | [ 1, 3, 2 | 0, 4 ]
 527 | [ 1, 2, 4 | 0, 3 ]
 528 | [ 1, 4, 2 | 0, 3 ]
 529 | [ 1, 3, 4 | 0, 2 ]
 530 | [ 1, 4, 3 | 0, 2 ]
 531 | [ 2, 3, 4 | 0, 1 ]
 532 | [ 2, 4, 3 | 0, 1 ]
 533 | ------------------
 534 | [ 0, 1, 2, 3, 4 ]
 535 | Found 20 permutations of 5 objects taken 3 at a time.
 536 | 
537 | 538 |

539 | For example you will not find the following in the above list: 540 |

541 | 542 |
 543 | [ 1, 2, 0 ]  // rotate(0, 1, 3) of permutation 1
 544 | [ 2, 0, 1 ]  // rotate(0, 2, 3) of permutation 1
 545 | 
546 | 547 |

548 | And if your circular permutations are also reversible, your list (and time 549 | spent) can be halved again: 550 |

551 | 552 |
 553 | for_each_reversible_circular_permutation(v.begin(), v.begin() + r, v.end(), f(v.size()));
 554 | 
 555 | [ 0, 1, 2 | 3, 4 ]
 556 | [ 0, 1, 3 | 2, 4 ]
 557 | [ 0, 1, 4 | 2, 3 ]
 558 | [ 0, 2, 3 | 1, 4 ]
 559 | [ 0, 2, 4 | 1, 3 ]
 560 | [ 0, 3, 4 | 1, 2 ]
 561 | [ 1, 2, 3 | 0, 4 ]
 562 | [ 1, 2, 4 | 0, 3 ]
 563 | [ 1, 3, 4 | 0, 2 ]
 564 | [ 2, 3, 4 | 0, 1 ]
 565 | ------------------
 566 | [ 0, 1, 2, 3, 4 ]
 567 | Found 10 permutations of 5 objects taken 3 at a time.
 568 | 
569 | 570 |

571 | For example you will not find the following in the above list: 572 |

573 | 574 |
 575 | [ 2, 1, 0 ]  // reverse(0, 3) of permutation(1)
 576 | [ 1, 2, 0 ]  // rotate(0, 1, 3) of permutation(1)
 577 | [ 0, 2, 1 ]  // reverse of rotate(0, 1, 3) of permutation(1)
 578 | [ 2, 0, 1 ]  // rotate(0, 2, 3) of permutation(1)
 579 | [ 1, 0, 2 ]  // reverse of rotate(0, 2, 3) of permutation(1)
 580 | 
581 | 582 |

583 | When r is 3 or less, then reversible circular permutations are the 584 | exact same as combinations. In this case use of for_each_combination 585 | should be preferred as it will be a little more efficient. Additionally when 586 | r is 2 or less, for_each_combination produces the same result 587 | as for_each_circular_permutation and 588 | for_each_reversible_permutation. When r == 1, all five 589 | algorithms produce the same N permutations. When r == 0, all 590 | five algorithms call the functor once with the empty range [first, 591 | first). 592 |

593 | 594 |

595 | 596 |

597 | 598 |

Performance Considerations

599 | 600 |

601 | Hervé Brönnimann published 602 | N2639 603 | proposing functionality somewhat similar as to what is outlined herein, 604 | including: 605 |

606 | 607 |
 608 | template <class BidirIter>
 609 | bool
 610 | next_partial_permutation(BidirIter first,
 611 |                          BidirIter mid,
 612 |                          BidirIter last);
 613 | 
 614 | template <class BidirIter >
 615 | bool
 616 | next_combination(BidirIter first,
 617 |                  BidirIter mid,
 618 |                  BidirIter last);
 619 | 
620 | 621 | 622 |

623 | This interface follows the style of the existing std::next_permutation 624 | algorithm. It is the inverse of the for_each style: The client calls 625 | the functor directly, and then calls the algorithm to find the next iteration. 626 |

627 | 628 |

629 | The problem with this interface is that it can get expensive to find the next 630 | iteration. For example when calling for_each_permutation and 631 | next_partial_permutation with r == 4 and varying N 632 | from 4 to 100, the time to iterate through the permutations skyrockets for 633 | next_partial_permutation, but not for for_each_permutation. By 634 | the time N == 100, for_each_permutation is running over 137 635 | times faster than next_partial_permutation which takes 20 seconds to do 636 | what for_each_permutation accomplishes in well under one sixth of a 637 | second. This trend rapidly gets worse as N grows. 638 |

639 | 640 |

641 | The same performance comparison can be made between next_combination 642 | and for_each_combination. It should be stressed that this isn't a lack 643 | of quality or care put into the 644 | N2639 645 | implementation. I've studied that implementation carefully and consider it very 646 | high quality. It is simply that the number of comparisons that need to be done 647 | to find out which swaps need to be done gets outrageously expensive. The number 648 | of swaps actually performed in both algorithms is approximately the same. At N == 649 | 100 for_each_combination is running about 14 times faster 650 | than next_combination. And that discrepancy only grows as the number 651 | of combinations increases. 652 |

653 | 654 |

Synopsis

655 | 656 |
 657 | // Integral-based count_each_*
 658 | 
 659 | template <class UInt>
 660 | UInt
 661 | count_each_permutation(UInt d1, UInt d2);
 662 | 
 663 | template <class UInt>
 664 | UInt
 665 | count_each_reversible_permutation(UInt d1, UInt d2);
 666 | 
 667 | template <class UInt>
 668 | UInt
 669 | count_each_circular_permutation(UInt d1, UInt d2);
 670 | 
 671 | template <class UInt>
 672 | UInt
 673 | count_each_reversible_circular_permutation(UInt d1, UInt d2);
 674 | 
 675 | template <class UInt>
 676 | UInt
 677 | count_each_combination(UInt d1, UInt d2);
 678 | 
 679 | // Iterator-based count_each_*
 680 | 
 681 | template <class BidirIter>
 682 | std::uintmax_t
 683 | count_each_permutation(BidirIter first,
 684 |                        BidirIter mid,
 685 |                        BidirIter last);
 686 | 
 687 | template <class BidirIter>
 688 | std::uintmax_t
 689 | count_each_reversible_permutation(BidirIter first,
 690 |                                   BidirIter mid,
 691 |                                   BidirIter last);
 692 | 
 693 | template <class BidirIter>
 694 | std::uintmax_t
 695 | count_each_circular_permutation(BidirIter first,
 696 |                                 BidirIter mid,
 697 |                                 BidirIter last);
 698 | 
 699 | template <class BidirIter>
 700 | std::uintmax_t
 701 | count_each_reversible_circular_permutation(BidirIter first,
 702 |                                            BidirIter mid,
 703 |                                            BidirIter last);
 704 | 
 705 | template <class BidirIter>
 706 | std::uintmax_t
 707 | count_each_combination(BidirIter first,
 708 |                        BidirIter mid,
 709 |                        BidirIter last);
 710 | 
 711 | // Iterator-based for_each_* algorithms
 712 | 
 713 | template <class BidirIter, class Function>
 714 | Function
 715 | for_each_permutation(BidirIter first,
 716 |                      BidirIter mid,
 717 |                      BidirIter last,
 718 |                      Function f);
 719 | 
 720 | template <class BidirIter, class Function>
 721 | Function
 722 | for_each_reversible_permutation(BidirIter first,
 723 |                                 BidirIter mid,
 724 |                                 BidirIter last,
 725 |                                 Function f);
 726 | 
 727 | template <class BidirIter, class Function>
 728 | Function
 729 | for_each_circular_permutation(BidirIter first,
 730 |                               BidirIter mid,
 731 |                               BidirIter last,
 732 |                               Function f);
 733 | 
 734 | template <class BidirIter, class Function>
 735 | Function
 736 | for_each_reversible_circular_permutation(BidirIter first,
 737 |                                          BidirIter mid,
 738 |                                          BidirIter last,
 739 |                                          Function f);
 740 | 
 741 | template <class BidirIter, class Function>
 742 | Function
 743 | for_each_combination(BidirIter first,
 744 |                      BidirIter mid,
 745 |                      BidirIter last,
 746 |                      Function f);
 747 | 
748 | 749 |

Specification

750 | 751 |

752 | Remarks: In this section a post-fix ! indicates a 753 | factorial operator and has 754 | higher precedence than any other operator. 755 |

756 | 757 |
 758 | template <class UInt>
 759 | UInt
 760 | count_each_permutation(UInt d1, UInt d2);
 761 | 
762 |
763 |

764 | Requires: Uint is an integral type or a type emulating an 765 | integral type. 766 |

767 | 768 |

769 | Returns: (d1 + d2)!/d2!. 770 |

771 | 772 |

773 | Throws: If the computed value is not representable in the type 774 | UInt, throws std::overflow_error. If d1 < UInt(0) 775 | or d2 < UInt(0), throws std::invalid_argument. 776 |

777 | 778 |

779 | Remarks: If the computed value is representable in the type 780 | UInt, returns the correct value. This algorithm avoids intermediate 781 | overflow. 782 |

783 | 784 |
785 |
786 | 787 |
 788 | template <class UInt>
 789 | UInt
 790 | count_each_reversible_permutation(UInt d1, UInt d2);
 791 | 
792 |
793 |

794 | Requires: Uint is an integral type or a type emulating an 795 | integral type. 796 |

797 | 798 |

799 | Returns: If d1 <= 1 returns (d1 + d2)!/d2!. Else 800 | returns (d1 + d2)!/(2*d2!). 801 |

802 | 803 |

804 | Throws: If the computed value is not representable in the type 805 | UInt, throws std::overflow_error. If d1 < UInt(0) 806 | or d2 < UInt(0), throws std::invalid_argument. 807 |

808 | 809 |

810 | Remarks: If the computed value is representable in the type 811 | UInt, returns the correct value. This algorithm avoids intermediate 812 | overflow. 813 |

814 | 815 |
816 |
817 | 818 |
 819 | template <class UInt>
 820 | UInt
 821 | count_each_circular_permutation(UInt d1, UInt d2);
 822 | 
823 |
824 |

825 | Requires: Uint is an integral type or a type emulating an 826 | integral type. 827 |

828 | 829 |

830 | Returns: If d1 == 0 returns 1. Else returns (d1 + 831 | d2)!/(d1*d2!). 832 |

833 | 834 |

835 | Throws: If the computed value is not representable in the type 836 | UInt, throws std::overflow_error. If d1 < UInt(0) 837 | or d2 < UInt(0), throws std::invalid_argument. 838 |

839 | 840 |

841 | Remarks: If the computed value is representable in the type 842 | UInt, returns the correct value. This algorithm avoids intermediate 843 | overflow. 844 |

845 | 846 |
847 |
848 | 849 |
 850 | template <class UInt>
 851 | UInt
 852 | count_each_reversible_circular_permutation(UInt d1, UInt d2);
 853 | 
854 |
855 |

856 | Requires: Uint is an integral type or a type emulating an 857 | integral type. 858 |

859 | 860 |

861 | Returns: If d1 == 0 returns 1. Else if d1 <= 2 862 | returns (d1 + d2)!/(d1*d2!). Else returns (d1 + 863 | d2)!/(2*d1*d2!). 864 |

865 | 866 |

867 | Throws: If the computed value is not representable in the type 868 | UInt, throws std::overflow_error. If d1 < UInt(0) 869 | or d2 < UInt(0), throws std::invalid_argument. 870 |

871 | 872 |

873 | Remarks: If the computed value is representable in the type 874 | UInt, returns the correct value. This algorithm avoids intermediate 875 | overflow. 876 |

877 | 878 |
879 |
880 | 881 |
 882 | template <class UInt>
 883 | UInt
 884 | count_each_combination(UInt d1, UInt d2);
 885 | 
886 |
887 |

888 | Requires: Uint is an integral type or a type emulating an 889 | integral type. 890 |

891 | 892 |

893 | Returns: (d1 + d2)!/(d1!*d2!). 894 |

895 | 896 |

897 | Throws: If the computed value is not representable in the type 898 | UInt, throws std::overflow_error. If d1 < UInt(0) 899 | or d2 < UInt(0), throws std::invalid_argument. 900 |

901 | 902 |

903 | Remarks: If the computed value is representable in the type 904 | UInt, returns the correct value. This algorithm avoids intermediate 905 | overflow. 906 |

907 | 908 |
909 |
910 | 911 |
 912 | template <class FwdIter>
 913 | std::uintmax_t
 914 | count_each_permutation(FwdIter first,
 915 |                            FwdIter mid,
 916 |                            FwdIter last);
 917 | 
918 |
919 |

920 | Requires: [first, mid) and [mid, last) are valid 921 | ranges. 922 |

923 | 924 |

925 | Returns: 926 | count_each_permutation<std::uintmax_t>(std::distance(first, mid), 927 | std::distance(mid, last)). 928 |

929 | 930 |
931 |
932 | 933 |
 934 | template <class FwdIter>
 935 | std::uintmax_t
 936 | count_each_reversible_permutation(FwdIter first,
 937 |                                       FwdIter mid,
 938 |                                       FwdIter last);
 939 | 
940 |
941 |

942 | Requires: [first, mid) and [mid, last) are valid 943 | ranges. 944 |

945 | 946 |

947 | Returns: 948 | count_each_reversible_permutation<std::uintmax_t>(std::distance(first, mid), 949 | std::distance(mid, last)). 950 |

951 | 952 |
953 |
954 | 955 |
 956 | template <class FwdIter>
 957 | std::uintmax_t
 958 | count_each_circular_permutation(FwdIter first,
 959 |                                     FwdIter mid,
 960 |                                     FwdIter last);
 961 | 
962 |
963 |

964 | Requires: [first, mid) and [mid, last) are valid 965 | ranges. 966 |

967 | 968 |

969 | Returns: 970 | count_each_circular_permutation<std::uintmax_t>(std::distance(first, mid), 971 | std::distance(mid, last)). 972 |

973 | 974 |
975 |
976 | 977 |
 978 | template <class FwdIter>
 979 | std::uintmax_t
 980 | count_each_reversible_circular_permutation(FwdIter first,
 981 |                                                FwdIter mid,
 982 |                                                FwdIter last);
 983 | 
984 |
985 |

986 | Requires: [first, mid) and [mid, last) are valid 987 | ranges. 988 |

989 | 990 |

991 | Returns: 992 | count_each_reversible_circular_permutation<std::uintmax_t>(std::distance(first, mid), 993 | std::distance(mid, last)). 994 |

995 | 996 |
997 |
998 | 999 |
1000 | template <class FwdIter>
1001 | std::uintmax_t
1002 | count_each_combination(FwdIter first,
1003 |                            FwdIter mid,
1004 |                            FwdIter last);
1005 | 
1006 |
1007 |

1008 | Requires: [first, mid) and [mid, last) are valid 1009 | ranges. 1010 |

1011 | 1012 |

1013 | Returns: 1014 | count_each_combination<std::uintmax_t>(std::distance(first, mid), 1015 | std::distance(mid, last)). 1016 |

1017 | 1018 |
1019 |
1020 | 1021 |
1022 | template <class BidirIter, class Function>
1023 | Function
1024 | for_each_permutation(BidirIter first,
1025 |                      BidirIter mid,
1026 |                      BidirIter last,
1027 |                      Function f);
1028 | 
1029 |
1030 |

1031 | Requires: 1032 |

1033 | 1034 |
    1035 |
  • 1036 | The type of *first shall satisfy the requirements of 1037 | Swappable, MoveConstructible and MoveAssignable. 1038 |
  • 1039 |
  • 1040 | [first, mid) and [mid, last) are valid ranges. 1041 |
  • 1042 |
  • 1043 | Function shall meet the requirements of MoveConstructible and 1044 | MoveAssignable. 1045 |
  • 1046 |
  • 1047 | f is callable as f(first, mid) and returns a type contextually 1048 | convertible to bool. 1049 |
  • 1050 |
1051 | 1052 |

1053 | Effects: Repeatedly permutes the range [first, last) such that 1054 | the range [first, mid) represents each permutation of the values in 1055 | [first, last) taken distance(first, mid) at a time. For each 1056 | permutation calls f(first, mid). On each call, the range [mid, 1057 | last) holds the values not in the current permutation. If f 1058 | returns true then returns immediately without permuting the sequence 1059 | any futher. Otherwise, after the last call to f, and prior to 1060 | returning, the range [first, last) is restored to its original order. 1061 | [Note: If f always returns false it is called 1062 | count_each_permutation(first, mid, last) times. — end 1063 | note] 1064 |

1065 | 1066 |

1067 | Returns: f. 1068 |

1069 | 1070 |

1071 | Notes: The type referenced by *first need not be 1072 | EqualityComparable nor LessThanComparable. The input range 1073 | need not be sorted. The algorithm does not take the values in the range 1074 | [first, last) into account in any way. 1075 |

1076 | 1077 |
1078 |
1079 | 1080 |
1081 | template <class BidirIter, class Function>
1082 | Function
1083 | for_each_reversible_permutation(BidirIter first,
1084 |                                 BidirIter mid,
1085 |                                 BidirIter last,
1086 |                                 Function f);
1087 | 
1088 |
1089 |

1090 | Requires: 1091 |

1092 | 1093 |
    1094 |
  • 1095 | The type of *first shall satisfy the requirements of 1096 | Swappable, MoveConstructible and MoveAssignable. 1097 |
  • 1098 |
  • 1099 | [first, mid) and [mid, last) are valid ranges. 1100 |
  • 1101 |
  • 1102 | Function shall meet the requirements of MoveConstructible and 1103 | MoveAssignable. 1104 |
  • 1105 |
  • 1106 | f is callable as f(first, mid) and returns a type contextually 1107 | convertible to bool. 1108 |
  • 1109 |
1110 | 1111 |

1112 | Effects: Repeatedly permutes the range [first, last) such that 1113 | the range [first, mid) represents each permutation of the values in 1114 | [first, last) taken distance(first, mid) at a time, except 1115 | that f is never called with the reverse of a permutation which has been 1116 | previously called. For each permutation calls f(first, mid). On each 1117 | call, the range [mid, last) holds the values not in the current 1118 | permutation. If f returns true then returns immediately 1119 | without permuting the sequence any futher. Otherwise, after the last call to 1120 | f, and prior to returning, the range [first, last) is restored 1121 | to its original order. [Note: If f always returns false 1122 | it is called count_each_reversible_permutation(first, mid, last) times. 1123 | — end note] 1124 |

1125 | 1126 |

1127 | Returns: f. 1128 |

1129 | 1130 |

1131 | Notes: The type referenced by *first need not be 1132 | EqualityComparable nor LessThanComparable. The input range 1133 | need not be sorted. The algorithm does not take the values in the range 1134 | [first, last) into account in any way. 1135 |

1136 | 1137 |
1138 |
1139 | 1140 |
1141 | template <class BidirIter, class Function>
1142 | Function
1143 | for_each_circular_permutation(BidirIter first,
1144 |                               BidirIter mid,
1145 |                               BidirIter last,
1146 |                               Function f);
1147 | 
1148 |
1149 |

1150 | Requires: 1151 |

1152 | 1153 |
    1154 |
  • 1155 | The type of *first shall satisfy the requirements of 1156 | Swappable, MoveConstructible and MoveAssignable. 1157 |
  • 1158 |
  • 1159 | [first, mid) and [mid, last) are valid ranges. 1160 |
  • 1161 |
  • 1162 | Function shall meet the requirements of MoveConstructible and 1163 | MoveAssignable. 1164 |
  • 1165 |
  • 1166 | f is callable as f(first, mid) and returns a type contextually 1167 | convertible to bool. 1168 |
  • 1169 |
1170 | 1171 |

1172 | Effects: Repeatedly permutes the range [first, last) such that 1173 | the range [first, mid) represents each permutation of the values in 1174 | [first, last) taken distance(first, mid) at a time, except 1175 | that f is never called with a circular permutation which has been 1176 | previously called. For each permutation calls f(first, mid). On each 1177 | call, the range [mid, last) holds the values not in the current 1178 | permutation. If f returns true then returns immediately 1179 | without permuting the sequence any futher. Otherwise, after the last call to 1180 | f, and prior to returning, the range [first, last) is restored 1181 | to its original order. [Note: If f always returns false 1182 | it is called count_each_circular_permutation(first, mid, last) times. 1183 | — end note] 1184 |

1185 | 1186 |

1187 | Returns: f. 1188 |

1189 | 1190 |

1191 | Notes: The type referenced by *first need not be 1192 | EqualityComparable nor LessThanComparable. The input range 1193 | need not be sorted. The algorithm does not take the values in the range 1194 | [first, last) into account in any way. 1195 |

1196 | 1197 |
1198 |
1199 | 1200 | 1201 |
1202 | template <class BidirIter, class Function>
1203 | Function
1204 | for_each_reversible_circular_permutation(BidirIter first,
1205 |                                          BidirIter mid,
1206 |                                          BidirIter last,
1207 |                                          Function f);
1208 | 
1209 |
1210 |

1211 | Requires: 1212 |

1213 | 1214 |
    1215 |
  • 1216 | The type of *first shall satisfy the requirements of 1217 | Swappable, MoveConstructible and MoveAssignable. 1218 |
  • 1219 |
  • 1220 | [first, mid) and [mid, last) are valid ranges. 1221 |
  • 1222 |
  • 1223 | Function shall meet the requirements of MoveConstructible and 1224 | MoveAssignable. 1225 |
  • 1226 |
  • 1227 | f is callable as f(first, mid) and returns a type contextually 1228 | convertible to bool. 1229 |
  • 1230 |
1231 | 1232 |

1233 | Effects: Repeatedly permutes the range [first, last) such that 1234 | the range [first, mid) represents each permutation of the values in 1235 | [first, last) taken distance(first, mid) at a time, except 1236 | that f is never called with a circular permutation which has been 1237 | previously called, or the reverse of that permutation. For each permutation 1238 | calls f(first, mid). On each call, the range [mid, last) 1239 | holds the values not in the current permutation. If f returns 1240 | true then returns immediately without permuting the sequence any 1241 | futher. Otherwise, after the last call to f, and prior to returning, 1242 | the range [first, last) is restored to its original order. 1243 | [Note: If f always returns false it is called 1244 | count_each_reversible_circular_permutation(first, mid, last) times. 1245 | — end note] 1246 |

1247 | 1248 |

1249 | Returns: f. 1250 |

1251 | 1252 |

1253 | Notes: The type referenced by *first need not be 1254 | EqualityComparable nor LessThanComparable. The input range 1255 | need not be sorted. The algorithm does not take the values in the range 1256 | [first, last) into account in any way. 1257 |

1258 | 1259 |
1260 |
1261 | 1262 | 1263 |
1264 | template <class BidirIter, class Function>
1265 | Function
1266 | for_each_combination(BidirIter first,
1267 |                      BidirIter mid,
1268 |                      BidirIter last,
1269 |                      Function f);
1270 | 
1271 |
1272 |

1273 | Requires: 1274 |

1275 | 1276 |
    1277 |
  • 1278 | The type of *first shall satisfy the requirements of 1279 | Swappable, MoveConstructible and MoveAssignable. 1280 |
  • 1281 |
  • 1282 | [first, mid) and [mid, last) are valid ranges. 1283 |
  • 1284 |
  • 1285 | Function shall meet the requirements of MoveConstructible and 1286 | MoveAssignable. 1287 |
  • 1288 |
  • 1289 | f is callable as f(first, mid) and returns a type contextually 1290 | convertible to bool. 1291 |
  • 1292 |
1293 | 1294 |

1295 | Effects: Repeatedly permutes the range [first, last) such that 1296 | the range [first, mid) represents each combination of the values in 1297 | [first, last) taken distance(first, mid) at a time. For each 1298 | permutation calls f(first, mid). On each call, the range [mid, 1299 | last) holds the values not in the current permutation. If f 1300 | returns true then returns immediately without permuting the sequence 1301 | any futher. Otherwise, after the last call to f, and prior to 1302 | returning, the range [first, last) is restored to its original order. 1303 | [Note: If f always returns false it is called 1304 | count_each_combination(first, mid, last) times. — end 1305 | note] 1306 |

1307 | 1308 |

1309 | Returns: f. 1310 |

1311 | 1312 |

1313 | Notes: The type referenced by *first need not be 1314 | EqualityComparable nor LessThanComparable. The input range 1315 | need not be sorted. The algorithm does not take the values in the range 1316 | [first, last) into account in any way. 1317 |

1318 | 1319 |
1320 |
1321 | 1322 |

1323 | Oh, and gcd. I'm tired of reinventing it. 1324 |

1325 | 1326 | 1327 |
1328 | template 
1329 | UInt
1330 | gcd(UInt x, UInt y) noexcept;
1331 | 
1332 |
1333 | 1334 |

1335 | Requires: Uint is an integral type or a type emulating an 1336 | integral type. x and y are positive. 1337 |

1338 | 1339 |

1340 | Returns: The greatest common divisor of x and y. 1341 |

1342 | 1343 |
1344 |
1345 | 1346 | 1347 |

Implementation

1348 | 1349 |

1350 | Here is the code. 1351 |

1352 | 1353 |
1354 | //  (C) Copyright Howard Hinnant 2005-2011.
1355 | //  Use, modification and distribution are subject to the Boost Software License,
1356 | //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
1357 | //  http://www.boost.org/LICENSE_1_0.txt).
1358 | //
1359 | //  See http://www.boost.org/libs/type_traits for most recent version including documentation.
1360 | 
1361 | //  Details are in namespace detail.  Every effort has been made to make
1362 | //  combine_discontinuous and permute as fast as possible.  They minimize the number
1363 | //  of swaps that are performed. Everything else builds on these two primitives. 
1364 | //  The most complicated algorithm is for_each_reversible_permutation.  But it
1365 | //  builds on combine_discontinuous and permute and I believe represents a minimum
1366 | //  number of swaps.  Without care, algorithms such as for_each_reversible_permutation
1367 | //  will take longer than for_each_permutation instead of the intended half the time.
1368 | 
1369 | //  Speed is everything.  Lest you could just use std::next_permutation and manually
1370 | //  eliminate duplicate permutations.  If the implementation fails in being orders
1371 | //  of magnitude faster than that, then it has failed miserably.
1372 | 
1373 | #include <iterator>
1374 | #include <algorithm>
1375 | #include <cstdint>
1376 | #include <limits>
1377 | #include <stdexcept>
1378 | 
1379 | namespace detail
1380 | {
1381 | 
1382 | // Rotates two discontinuous ranges to put *first2 where *first1 is.
1383 | //     If last1 == first2 this would be equivalent to rotate(first1, first2, last2),
1384 | //     but instead the rotate "jumps" over the discontinuity [last1, first2) -
1385 | //     which need not be a valid range.
1386 | //     In order to make it faster, the length of [first1, last1) is passed in as d1,
1387 | //     and d2 must be the length of [first2, last2).
1388 | //  In a perfect world the d1 > d2 case would have used swap_ranges and
1389 | //     reverse_iterator, but reverse_iterator is too inefficient.
1390 | template <class BidirIter>
1391 | void
1392 | rotate_discontinuous(BidirIter first1, BidirIter last1,
1393 |                      typename std::iterator_traits<BidirIter>::difference_type d1,
1394 |                      BidirIter first2, BidirIter last2,
1395 |                      typename std::iterator_traits<BidirIter>::difference_type d2)
1396 | {
1397 |     using std::swap;
1398 |     if (d1 <= d2)
1399 |         std::rotate(first2, std::swap_ranges(first1, last1, first2), last2);
1400 |     else
1401 |     {
1402 |         BidirIter i1 = last1;
1403 |         while (first2 != last2)
1404 |             swap(*--i1, *--last2);
1405 |         std::rotate(first1, i1, last1);
1406 |     }
1407 | }
1408 | 
1409 | // Rotates the three discontinuous ranges to put *first2 where *first1 is.
1410 | // Just like rotate_discontinuous, except the second range is now represented by
1411 | //    two discontinuous ranges: [first2, last2) + [first3, last3).
1412 | template <class BidirIter>
1413 | void
1414 | rotate_discontinuous3(BidirIter first1, BidirIter last1,
1415 |                       typename std::iterator_traits<BidirIter>::difference_type d1,
1416 |                       BidirIter first2, BidirIter last2,
1417 |                       typename std::iterator_traits<BidirIter>::difference_type d2,
1418 |                       BidirIter first3, BidirIter last3,
1419 |                       typename std::iterator_traits<BidirIter>::difference_type d3)
1420 | {
1421 |     rotate_discontinuous(first1, last1, d1, first2, last2, d2);
1422 |     if (d1 <= d2)
1423 |         rotate_discontinuous(std::next(first2, d2 - d1), last2, d1, first3, last3, d3);
1424 |     else
1425 |     {
1426 |         rotate_discontinuous(std::next(first1, d2), last1, d1 - d2, first3, last3, d3);
1427 |         rotate_discontinuous(first2, last2, d2, first3, last3, d3);
1428 |     }
1429 | }
1430 | 
1431 | // Call f() for each combination of the elements [first1, last1) + [first2, last2)
1432 | //    swapped/rotated into the range [first1, last1).  As long as f() returns
1433 | //    false, continue for every combination and then return [first1, last1) and
1434 | //    [first2, last2) to their original state.  If f() returns true, return
1435 | //    immediately.
1436 | //  Does the absolute mininum amount of swapping to accomplish its task.
1437 | //  If f() always returns false it will be called (d1+d2)!/(d1!*d2!) times.
1438 | template <class BidirIter, class Function>
1439 | bool
1440 | combine_discontinuous(BidirIter first1, BidirIter last1,
1441 |                       typename std::iterator_traits<BidirIter>::difference_type d1,
1442 |                       BidirIter first2, BidirIter last2,
1443 |                       typename std::iterator_traits<BidirIter>::difference_type d2,
1444 |                       Function& f,
1445 |                       typename std::iterator_traits<BidirIter>::difference_type d = 0)
1446 | {
1447 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
1448 |     using std::swap;
1449 |     if (d1 == 0 || d2 == 0)
1450 |         return f();
1451 |     if (d1 == 1)
1452 |     {
1453 |         for (BidirIter i2 = first2; i2 != last2; ++i2)
1454 |         {
1455 |             if (f())
1456 |                 return true;
1457 |             swap(*first1, *i2);
1458 |         }
1459 |     }
1460 |     else
1461 |     {
1462 |         BidirIter f1p = std::next(first1);
1463 |         BidirIter i2 = first2;
1464 |         for (D d22 = d2; i2 != last2; ++i2, --d22)
1465 |         {
1466 |             if (combine_discontinuous(f1p, last1, d1-1, i2, last2, d22, f, d+1))
1467 |                 return true;
1468 |             swap(*first1, *i2);
1469 |         }
1470 |     }
1471 |     if (f())
1472 |         return true;
1473 |     if (d != 0)
1474 |         rotate_discontinuous(first1, last1, d1, std::next(first2), last2, d2-1);
1475 |     else
1476 |         rotate_discontinuous(first1, last1, d1, first2, last2, d2);
1477 |     return false;
1478 | }
1479 | 
1480 | // A binder for binding arguments to call combine_discontinuous
1481 | template <class Function, class BidirIter>
1482 | class call_combine_discontinuous
1483 | {
1484 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
1485 |     Function f_;
1486 |     BidirIter first1_;
1487 |     BidirIter last1_;
1488 |     D d1_;
1489 |     BidirIter first2_;
1490 |     BidirIter last2_;
1491 |     D d2_;
1492 | 
1493 | public:
1494 |     call_combine_discontinuous(
1495 |                       BidirIter first1, BidirIter last1,
1496 |                       D d1,
1497 |                       BidirIter first2, BidirIter last2,
1498 |                       D d2,
1499 |                       Function& f)
1500 |         : f_(f), first1_(first1), last1_(last1), d1_(d1),
1501 |                  first2_(first2), last2_(last2), d2_(d2) {}
1502 | 
1503 |     bool operator()()
1504 |     {
1505 |         return combine_discontinuous(first1_, last1_, d1_, first2_, last2_, d2_, f_);
1506 |     }
1507 | };
1508 | 
1509 | // See combine_discontinuous3
1510 | template <class BidirIter, class Function>
1511 | bool
1512 | combine_discontinuous3_(BidirIter first1, BidirIter last1,
1513 |                         typename std::iterator_traits<BidirIter>::difference_type d1,
1514 |                         BidirIter first2, BidirIter last2,
1515 |                         typename std::iterator_traits<BidirIter>::difference_type d2,
1516 |                         BidirIter first3, BidirIter last3,
1517 |                         typename std::iterator_traits<BidirIter>::difference_type d3,
1518 |                         Function& f,
1519 |                         typename std::iterator_traits<BidirIter>::difference_type d = 0)
1520 | {
1521 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
1522 |     using std::swap;
1523 |     if (d1 == 1)
1524 |     {
1525 |         for (BidirIter i2 = first2; i2 != last2; ++i2)
1526 |         {
1527 |             if (f())
1528 |                 return true;
1529 |             swap(*first1, *i2);
1530 |         }
1531 |         if (f())
1532 |             return true;
1533 |         swap(*first1, *std::prev(last2));
1534 |         swap(*first1, *first3);
1535 |         for (BidirIter i2 = std::next(first3); i2 != last3; ++i2)
1536 |         {
1537 |             if (f())
1538 |                 return true;
1539 |             swap(*first1, *i2);
1540 |         }
1541 |     }
1542 |     else
1543 |     {
1544 |         BidirIter f1p = std::next(first1);
1545 |         BidirIter i2 = first2;
1546 |         for (D d22 = d2; i2 != last2; ++i2, --d22)
1547 |         {
1548 |             if (combine_discontinuous3_(f1p, last1, d1-1, i2, last2, d22, first3,
1549 |                                         last3, d3, f, d+1))
1550 |                 return true;
1551 |             swap(*first1, *i2);
1552 |         }
1553 |         i2 = first3;
1554 |         for (D d22 = d3; i2 != last3; ++i2, --d22)
1555 |         {
1556 |             if (combine_discontinuous(f1p, last1, d1-1, i2, last3, d22, f, d+1))
1557 |                 return true;
1558 |             swap(*first1, *i2);
1559 |         }
1560 |     }
1561 |     if (f())
1562 |         return true;
1563 |     if (d1 == 1)
1564 |         swap(*std::prev(last2), *first3);
1565 |     if (d != 0)
1566 |     {
1567 |         if (d2 > 1)
1568 |             rotate_discontinuous3(first1, last1, d1, std::next(first2), last2, d2-1, first3, last3, d3);
1569 |         else
1570 |             rotate_discontinuous(first1, last1, d1, first3, last3, d3);
1571 |     }
1572 |     else
1573 |         rotate_discontinuous3(first1, last1, d1, first2, last2, d2, first3, last3, d3);
1574 |     return false;
1575 | }
1576 | 
1577 | // Like combine_discontinuous, but swaps/rotates each combination out of
1578 | //    [first1, last1) + [first2, last2) + [first3, last3) into [first1, last1).
1579 | //    If f() always returns false, it is called (d1+d2+d3)!/(d1!*(d2+d3)!) times.
1580 | template <class BidirIter, class Function>
1581 | bool
1582 | combine_discontinuous3(BidirIter first1, BidirIter last1,
1583 |                        typename std::iterator_traits<BidirIter>::difference_type d1,
1584 |                        BidirIter first2, BidirIter last2,
1585 |                        typename std::iterator_traits<BidirIter>::difference_type d2,
1586 |                        BidirIter first3, BidirIter last3,
1587 |                        typename std::iterator_traits<BidirIter>::difference_type d3,
1588 |                        Function& f)
1589 | {
1590 |     typedef call_combine_discontinuous<Function&, BidirIter> F;
1591 |     F fbc(first2, last2, d2, first3, last3, d3, f);  // BC
1592 |     return combine_discontinuous3_(first1, last1, d1, first2, last2, d2, first3, last3, d3, fbc);
1593 | }
1594 | 
1595 | // See permute
1596 | template <class BidirIter, class Function>
1597 | bool
1598 | permute_(BidirIter first1, BidirIter last1,
1599 |          typename std::iterator_traits<BidirIter>::difference_type d1,
1600 |          Function& f)
1601 | {
1602 |     using std::swap;
1603 |     switch (d1)
1604 |     {
1605 |     case 0:
1606 |     case 1:
1607 |         return f();
1608 |     case 2:
1609 |         if (f())
1610 |             return true;
1611 |         swap(*first1, *std::next(first1));
1612 |         return f();
1613 |     case 3:
1614 |         {
1615 |         if (f())
1616 |             return true;
1617 |         BidirIter f2 = std::next(first1);
1618 |         BidirIter f3 = std::next(f2);
1619 |         swap(*f2, *f3);
1620 |         if (f())
1621 |             return true;
1622 |         swap(*first1, *f3);
1623 |         swap(*f2, *f3);
1624 |         if (f())
1625 |             return true;
1626 |         swap(*f2, *f3);
1627 |         if (f())
1628 |             return true;
1629 |         swap(*first1, *f2);
1630 |         swap(*f2, *f3);
1631 |         if (f())
1632 |             return true;
1633 |         swap(*f2, *f3);
1634 |         return f();
1635 |         }
1636 |     }
1637 |     BidirIter fp1 = std::next(first1);
1638 |     for (BidirIter p = fp1; p != last1; ++p)
1639 |     {
1640 |         if (permute_(fp1, last1, d1-1, f))
1641 |             return true;
1642 |         std::reverse(fp1, last1);
1643 |         swap(*first1, *p);
1644 |     }
1645 |     return permute_(fp1, last1, d1-1, f);
1646 | }
1647 | 
1648 | // Calls f() for each permutation of [first1, last1)
1649 | // Divided into permute and permute_ in a (perhaps futile) attempt to
1650 | //    squeeze a little more performance out of it.
1651 | template <class BidirIter, class Function>
1652 | bool
1653 | permute(BidirIter first1, BidirIter last1,
1654 |         typename std::iterator_traits<BidirIter>::difference_type d1,
1655 |         Function& f)
1656 | {
1657 |     using std::swap;
1658 |     switch (d1)
1659 |     {
1660 |     case 0:
1661 |     case 1:
1662 |         return f();
1663 |     case 2:
1664 |         {
1665 |         if (f())
1666 |             return true;
1667 |         BidirIter i = std::next(first1);
1668 |         swap(*first1, *i);
1669 |         if (f())
1670 |             return true;
1671 |         swap(*first1, *i);
1672 |         }
1673 |         break;
1674 |     case 3:
1675 |         {
1676 |         if (f())
1677 |             return true;
1678 |         BidirIter f2 = std::next(first1);
1679 |         BidirIter f3 = std::next(f2);
1680 |         swap(*f2, *f3);
1681 |         if (f())
1682 |             return true;
1683 |         swap(*first1, *f3);
1684 |         swap(*f2, *f3);
1685 |         if (f())
1686 |             return true;
1687 |         swap(*f2, *f3);
1688 |         if (f())
1689 |             return true;
1690 |         swap(*first1, *f2);
1691 |         swap(*f2, *f3);
1692 |         if (f())
1693 |             return true;
1694 |         swap(*f2, *f3);
1695 |         if (f())
1696 |             return true;
1697 |         swap(*first1, *f3);
1698 |         }
1699 |         break;
1700 |     default:
1701 |         BidirIter fp1 = std::next(first1);
1702 |         for (BidirIter p = fp1; p != last1; ++p)
1703 |         {
1704 |             if (permute_(fp1, last1, d1-1, f))
1705 |                 return true;
1706 |             std::reverse(fp1, last1);
1707 |             swap(*first1, *p);
1708 |         }
1709 |         if (permute_(fp1, last1, d1-1, f))
1710 |             return true;
1711 |         std::reverse(first1, last1);
1712 |         break;
1713 |     }
1714 |     return false;
1715 | }
1716 | 
1717 | // Creates a functor with no arguments which calls f_(first_, last_).
1718 | //   Also has a variant that takes two It and ignores them.
1719 | template <class Function, class It>
1720 | class bound_range
1721 | {
1722 |     Function f_;
1723 |     It first_;
1724 |     It last_;
1725 | public:
1726 |     bound_range(Function f, It first, It last)
1727 |         : f_(f), first_(first), last_(last) {}
1728 | 
1729 |     bool
1730 |     operator()()
1731 |     {
1732 |         return f_(first_, last_);
1733 |     }
1734 | 
1735 |     bool
1736 |     operator()(It, It)
1737 |     {
1738 |         return f_(first_, last_);
1739 |     }
1740 | };
1741 | 
1742 | // A binder for binding arguments to call permute
1743 | template <class Function, class It>
1744 | class call_permute
1745 | {
1746 |     typedef typename std::iterator_traits<It>::difference_type D;
1747 |     Function f_;
1748 |     It first_;
1749 |     It last_;
1750 |     D d_;
1751 | public:
1752 |     call_permute(Function f, It first, It last, D d)
1753 |         : f_(f), first_(first), last_(last), d_(d) {}
1754 | 
1755 |     bool
1756 |     operator()()
1757 |     {
1758 |         return permute(first_, last_, d_, f_);
1759 |     }
1760 | };
1761 | 
1762 | }  // detail
1763 | 
1764 | template <class BidirIter, class Function>
1765 | Function
1766 | for_each_combination(BidirIter first, BidirIter mid,
1767 |                      BidirIter last, Function f)
1768 | {
1769 |     detail::bound_range<Function&, BidirIter> wfunc(f, first, mid);
1770 |     detail::combine_discontinuous(first, mid, std::distance(first, mid),
1771 |                                   mid, last, std::distance(mid, last),
1772 |                                   wfunc);
1773 |     return f;
1774 | }
1775 | 
1776 | template <class UInt>
1777 | UInt
1778 | gcd(UInt x, UInt y)
1779 | {
1780 |     while (y != 0)
1781 |     {
1782 |         UInt t = x % y;
1783 |         x = y;
1784 |         y = t;
1785 |     }
1786 |     return x;
1787 | }
1788 | 
1789 | template <class Int>
1790 | inline
1791 | typename std::enable_if
1792 | <
1793 |     std::is_unsigned<Int>::value,
1794 |     void
1795 | >::type
1796 | check_non_negative(Int d1, Int d2)
1797 | {
1798 | }
1799 | 
1800 | template <class Int>
1801 | typename std::enable_if
1802 | <
1803 |     !std::is_unsigned<Int>::value,
1804 |     void
1805 | >::type
1806 | check_non_negative(Int d1, Int d2)
1807 | {
1808 |     if (d1 < Int(0) || d2 < Int(0))
1809 |         throw std::invalid_argument("expected non-negative argument");
1810 | }
1811 | 
1812 | template <class UInt>
1813 | UInt
1814 | count_each_combination(UInt d1, UInt d2)
1815 | {
1816 |     check_non_negative(d1, d2);
1817 |     if (d2 < d1)
1818 |         std::swap(d1, d2);
1819 |     if (d1 == UInt())
1820 |         return 1;
1821 |     if (d1 > std::numeric_limits<UInt>::max() - d2)
1822 |         throw std::overflow_error("overflow in count_each_combination");
1823 |     UInt n = d1 + d2;
1824 |     UInt r = n;
1825 |     --n;
1826 |     for (UInt k = UInt(2); k <= d1; ++k, --n)
1827 |     {
1828 |         // r = r * n / k, known to not not have truncation error
1829 |         UInt g = gcd(r, k);
1830 |         r /= g;
1831 |         UInt t = n / (k / g);
1832 |         if (r > std::numeric_limits<UInt>::max() / t)
1833 |             throw std::overflow_error("overflow in count_each_combination");
1834 |         r *= t;
1835 |     }
1836 |     return r;
1837 | }
1838 | 
1839 | template <class BidirIter>
1840 | std::uintmax_t
1841 | count_each_combination(BidirIter first, BidirIter mid, BidirIter last)
1842 | {
1843 |     return count_each_combination<std::uintmax_t>
1844 |                           (std::distance(first, mid), std::distance(mid, last));
1845 | }
1846 | 
1847 | // For each of the permutation algorithms, use for_each_combination (or
1848 | //    combine_discontinuous) to handle the "r out of N" part of the algorithm.
1849 | //    Thus each permutation algorithm has to deal only with an "N out of N"
1850 | //    problem.  I.e. For each combination of r out of N items, permute it thusly.
1851 | template <class BidirIter, class Function>
1852 | Function
1853 | for_each_permutation(BidirIter first, BidirIter mid,
1854 |                      BidirIter last, Function f)
1855 | {
1856 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
1857 |     typedef detail::bound_range<Function&, BidirIter> Wf;
1858 |     typedef detail::call_permute<Wf, BidirIter> PF;
1859 |     Wf wfunc(f, first, mid);
1860 |     D d1 = std::distance(first, mid);
1861 |     PF pf(wfunc, first, mid, d1);
1862 |     detail::combine_discontinuous(first, mid, d1,
1863 |                                   mid, last, std::distance(mid, last),
1864 |                                   pf);
1865 |     return f;
1866 | }
1867 | 
1868 | template <class UInt>
1869 | UInt
1870 | count_each_permutation(UInt d1, UInt d2)
1871 | {
1872 |     // return (d1+d2)!/d2!
1873 |     check_non_negative(d1, d2);
1874 |     if (d1 > std::numeric_limits<UInt>::max() - d2)
1875 |         throw std::overflow_error("overflow in count_each_permutation");
1876 |     UInt n = d1 + d2;
1877 |     UInt r(1);
1878 |     for (; n > d2; --n)
1879 |     {
1880 |         if (r > std::numeric_limits<UInt>::max() / n)
1881 |             throw std::overflow_error("overflow in count_each_permutation");
1882 |         r *= n;
1883 |     }
1884 |     return r;
1885 | }
1886 | 
1887 | template <class BidirIter>
1888 | std::uintmax_t
1889 | count_each_permutation(BidirIter first, BidirIter mid, BidirIter last)
1890 | {
1891 |     return count_each_permutation<std::uintmax_t>
1892 |                           (std::distance(first, mid), std::distance(mid, last));
1893 | }
1894 | 
1895 | namespace detail
1896 | {
1897 | 
1898 | // Adapt functor to permute over [first+1, last)
1899 | //   A circular permutation of N items is done by holding the first item and
1900 | //   permuting [first+1, last).
1901 | template <class Function, class BidirIter>
1902 | class circular_permutation
1903 | {
1904 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
1905 | 
1906 |     Function f_;
1907 |     D s_;
1908 | 
1909 | public:
1910 |     explicit circular_permutation(Function f, D s) : f_(f), s_(s) {}
1911 | 
1912 |     bool
1913 |     operator()(BidirIter first, BidirIter last)
1914 |     {
1915 |         if (s_ <= 1)
1916 |             return f_(first, last);
1917 |         bound_range<Function, BidirIter> f(f_, first, last);
1918 |         return permute(std::next(first), last, s_ - 1, f);
1919 |     }
1920 | };
1921 | 
1922 | }  // detail
1923 | 
1924 | template <class BidirIter, class Function>
1925 | Function
1926 | for_each_circular_permutation(BidirIter first,
1927 |                               BidirIter mid,
1928 |                               BidirIter last, Function f)
1929 | {
1930 |     for_each_combination(first, mid, last, detail::circular_permutation<Function&,
1931 |                           BidirIter>(f, std::distance(first, mid)));
1932 |     return f;
1933 | }    
1934 | 
1935 | template <class UInt>
1936 | UInt
1937 | count_each_circular_permutation(UInt d1, UInt d2)
1938 | {
1939 |     // return d1 > 0 ? (d1+d2)!/(d1*d2!) : 1
1940 |     check_non_negative(d1, d2);
1941 |     if (d1 == UInt())
1942 |         return 1;
1943 |     UInt r;
1944 |     if (d1 <= d2)
1945 |     {
1946 |         try
1947 |         {
1948 |             r = count_each_combination(d1, d2);
1949 |         }
1950 |         catch (const std::overflow_error&)
1951 |         {
1952 |             throw std::overflow_error("overflow in count_each_circular_permutation");
1953 |         }
1954 |         for (--d1; d1 > UInt(1); --d1)
1955 |         {
1956 |             if (r > std::numeric_limits<UInt>::max()/d1)
1957 |                 throw std::overflow_error("overflow in count_each_circular_permutation");
1958 |             r *= d1;
1959 |         }
1960 |     }
1961 |     else
1962 |     {   // functionally equivalent but faster algorithm
1963 |         if (d1 > std::numeric_limits<UInt>::max() - d2)
1964 |             throw std::overflow_error("overflow in count_each_circular_permutation");
1965 |         UInt n = d1 + d2;
1966 |         r = 1;
1967 |         for (; n > d1; --n)
1968 |         {
1969 |             if (r > std::numeric_limits<UInt>::max()/n)
1970 |                 throw std::overflow_error("overflow in count_each_circular_permutation");
1971 |             r *= n;
1972 |         }
1973 |         for (--n; n > d2; --n)
1974 |         {
1975 |             if (r > std::numeric_limits<UInt>::max()/n)
1976 |                 throw std::overflow_error("overflow in count_each_circular_permutation");
1977 |             r *= n;
1978 |         }
1979 |     }
1980 |     return r;
1981 | }
1982 | 
1983 | template <class BidirIter>
1984 | std::uintmax_t
1985 | count_each_circular_permutation(BidirIter first, BidirIter mid, BidirIter last)
1986 | {
1987 |     return count_each_circular_permutation<std::uintmax_t>
1988 |                           (std::distance(first, mid), std::distance(mid, last));
1989 | }
1990 | 
1991 | namespace detail
1992 | {
1993 | 
1994 | // Difficult!!!  See notes for operator().
1995 | template <class Function, class Size>
1996 | class reversible_permutation
1997 | {
1998 |     Function f_;
1999 |     Size s_;
2000 | 
2001 | public:
2002 |     reversible_permutation(Function f, Size s) : f_(f), s_(s) {}
2003 | 
2004 |     template <class BidirIter>
2005 |     bool
2006 |     operator()(BidirIter first, BidirIter last);
2007 | };
2008 | 
2009 | // rev1 looks like call_permute
2010 | template <class Function, class BidirIter>
2011 | class rev1
2012 | {
2013 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
2014 | 
2015 |     Function f_;
2016 |     BidirIter first1_;
2017 |     BidirIter last1_;
2018 |     D d1_;
2019 | 
2020 | public:
2021 |     rev1(Function f, BidirIter first, BidirIter last, D d)
2022 |         : f_(f), first1_(first), last1_(last), d1_(d) {}
2023 | 
2024 |     bool operator()()
2025 |     {
2026 |         return permute(first1_, last1_, d1_, f_);
2027 |     }
2028 | };
2029 | 
2030 | // For each permutation in [first1, last1),
2031 | //     call f() for each permutation of [first2, last2).
2032 | template <class Function, class BidirIter>
2033 | class rev2
2034 | {
2035 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
2036 | 
2037 |     Function f_;
2038 |     BidirIter first1_;
2039 |     BidirIter last1_;
2040 |     D d1_;
2041 |     BidirIter first2_;
2042 |     BidirIter last2_;
2043 |     D d2_;
2044 | 
2045 | public:
2046 |     rev2(Function f, BidirIter first1, BidirIter last1, D d1,
2047 |                      BidirIter first2, BidirIter last2, D d2)
2048 |         : f_(f), first1_(first1), last1_(last1), d1_(d1),
2049 |                  first2_(first2), last2_(last2), d2_(d2) {}
2050 | 
2051 |     bool operator()()
2052 |     {
2053 |         call_permute<Function, BidirIter> f(f_, first2_, last2_, d2_);
2054 |         return permute(first1_, last1_, d1_, f);
2055 |     }
2056 | };
2057 | 
2058 | // For each permutation in [first1, last1),
2059 | //     and for each permutation of [first2, last2)
2060 | //     call f() for each permutation of [first3, last3).
2061 | template <class Function, class BidirIter>
2062 | class rev3
2063 | {
2064 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
2065 | 
2066 |     Function f_;
2067 |     BidirIter first1_;
2068 |     BidirIter last1_;
2069 |     D d1_;
2070 |     BidirIter first2_;
2071 |     BidirIter last2_;
2072 |     D d2_;
2073 |     BidirIter first3_;
2074 |     BidirIter last3_;
2075 |     D d3_;
2076 | 
2077 | public:
2078 |     rev3(Function f, BidirIter first1, BidirIter last1, D d1,
2079 |                      BidirIter first2, BidirIter last2, D d2,
2080 |                      BidirIter first3, BidirIter last3, D d3)
2081 |         : f_(f), first1_(first1), last1_(last1), d1_(d1),
2082 |                  first2_(first2), last2_(last2), d2_(d2),
2083 |                  first3_(first3), last3_(last3), d3_(d3) {}
2084 | 
2085 |     bool operator()()
2086 |     {
2087 |         rev2<Function, BidirIter> f(f_, first2_, last2_, d2_, first3_, last3_, d3_);
2088 |         return permute(first1_, last1_, d1_, f);
2089 |     }
2090 | };
2091 | 
2092 | // There are simpler implementations.  I believe the simpler ones are far more
2093 | //     expensive.
2094 | template <class Function, class Size>
2095 | template <class BidirIter>
2096 | bool
2097 | reversible_permutation<Function, Size>::operator()(BidirIter first,
2098 |                                                    BidirIter last)
2099 | {
2100 |     typedef typename std::iterator_traits<BidirIter>::difference_type difference_type;
2101 |     typedef rev2<bound_range<Function&, BidirIter>, BidirIter> F2;
2102 |     typedef rev3<bound_range<Function&, BidirIter>, BidirIter> F3;
2103 |     // When the range is 0 - 2, then this is just a combination of N out of N
2104 |     //   elements.
2105 |     if (s_ < 3)
2106 |         return f_(first, last);
2107 |     using std::swap;
2108 |     // Hold the first element steady and call f_(first, last) for each
2109 |     //    permutation in [first+1, last).
2110 |     BidirIter a = std::next(first);
2111 |     bound_range<Function&, BidirIter> f(f_, first, last);
2112 |     if (permute(a, last, s_-1, f))
2113 |         return true;
2114 |     // Beginning with the first element, swap the previous element with the
2115 |     //    next element.  For each swap, call f_(first, last) for each
2116 |     //    permutation of the discontinuous range:
2117 |     //    [prior to the orignal element] + [after the original element].
2118 |     Size s2 = s_ / 2;
2119 |     BidirIter am1 = first;
2120 |     BidirIter ap1 = std::next(a);
2121 |     for (Size i = 1; i < s2; ++i, ++am1, ++a, ++ap1)
2122 |     {
2123 |         swap(*am1, *a);
2124 |         F2 f2(f, first, a, i, ap1, last, s_ - i - 1);
2125 |         if (combine_discontinuous(first, a, i, ap1, last, s_ - i - 1, f2))
2126 |             return true;
2127 |     }
2128 |     // If [first, last) has an even number of elements, then fix it up to the
2129 |     //     original permutation.
2130 |     if (2 * s2 == s_)
2131 |     {
2132 |         std::rotate(first, am1, a);
2133 |     }
2134 |     // else if the range has length 3, we need one more call and the fix is easy.
2135 |     else if (s_ == 3)
2136 |     {
2137 |         swap(*am1, *a);
2138 |         if (f_(first, last))
2139 |             return true;
2140 |         swap(*am1, *a);
2141 |     }
2142 |     // else the range is an odd number greater than 3.  We need to permute
2143 |     //     through exactly half of the permuations with the original element in
2144 |     //     the middle.
2145 |     else
2146 |     {
2147 |         // swap the original first element into the middle, and hold the current
2148 |         //   first element steady.  This creates a discontinuous range:
2149 |         //     [first+1, middle) + [middle+1, last).  Run through all permutations
2150 |         //     of that discontinuous range.
2151 |         swap(*am1, *a);
2152 |         BidirIter b = first;
2153 |         BidirIter bp1 = std::next(b);
2154 |         F2 f2(f, bp1, a, s2-1, ap1, last, s_ - s2 - 1);
2155 |         if (combine_discontinuous(bp1, a, s2-1, ap1, last, s_ - s2 - 1, f2))
2156 |             return true;
2157 |         // Swap the current first element into every place from first+1 to middle-1.
2158 |         //   For each location, hold it steady to create the following discontinuous
2159 |         //   range (made of 3 ranges): [first, b-1) + [b+1, middle) + [middle+1, last).
2160 |         //   For each b in [first+1, middle-1), run through all permutations of
2161 |         //      the discontinuous ranges.
2162 |         b = bp1;
2163 |         ++bp1;
2164 |         BidirIter bm1 = first;
2165 |         for (Size i = 1; i < s2-1; ++i, ++bm1, ++b, ++bp1)
2166 |         {
2167 |             swap(*bm1, *b);
2168 |             F3 f3(f, first, b, i, bp1, a, s2-i-1, ap1, last, s_ - s2 - 1);
2169 |             if (combine_discontinuous3(first, b, i, bp1, a, s2-i-1, ap1, last, s_-s2-1, f3))
2170 |                 return true;
2171 |         }
2172 |         // swap b into into middle-1, creates a discontinuous range:
2173 |         //     [first, middle-1) + [middle+1, last).  Run through all permutations
2174 |         //     of that discontinuous range.
2175 |         swap(*bm1, *b);
2176 |         F2 f21(f, first, b, s2-1, ap1, last, s_ - s2 - 1);
2177 |         if (combine_discontinuous(first, b, s2-1, ap1, last, s_ - s2 - 1, f21))
2178 |             return true;
2179 |         // Revert [first, last) to original order
2180 |         std::reverse(first, b);
2181 |         std::reverse(first, ap1);
2182 |     }
2183 |     return false;
2184 | }
2185 | 
2186 | }  // detail
2187 | 
2188 | template <class BidirIter, class Function>
2189 | Function
2190 | for_each_reversible_permutation(BidirIter first,
2191 |                                 BidirIter mid,
2192 |                                 BidirIter last, Function f)
2193 | {
2194 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
2195 |     for_each_combination(first, mid, last,
2196 |                   detail::reversible_permutation<Function&, D>(f,
2197 |                                               std::distance(first, mid)));
2198 |     return f;
2199 | }    
2200 | 
2201 | template <class UInt>
2202 | UInt
2203 | count_each_reversible_permutation(UInt d1, UInt d2)
2204 | {
2205 |     // return d1 > 1 ? (d1+d2)!/(2*d2!) : (d1+d2)!/d2!
2206 |     check_non_negative(d1, d2);
2207 |     if (d1 > std::numeric_limits<UInt>::max() - d2)
2208 |         throw std::overflow_error("overflow in count_each_reversible_permutation");
2209 |     UInt n = d1 + d2;
2210 |     UInt r(1);
2211 |     if (d1 > UInt(1))
2212 |     {
2213 |         r = n;
2214 |         if ((n & UInt(1)) == UInt(0))
2215 |             r /= UInt(2);
2216 |         --n;
2217 |         UInt t = n;
2218 |         if ((t & UInt(1)) == UInt(0))
2219 |             t /= UInt(2);
2220 |         if (r > std::numeric_limits<UInt>::max() / t)
2221 |             throw std::overflow_error("overflow in count_each_reversible_permutation");
2222 |         r *= t;
2223 |         --n;
2224 |     }
2225 |     for (; n > d2; --n)
2226 |     {
2227 |         if (r > std::numeric_limits<UInt>::max() / n)
2228 |             throw std::overflow_error("overflow in count_each_reversible_permutation");
2229 |         r *= n;
2230 |     }
2231 |     return r;
2232 | }
2233 | 
2234 | template <class BidirIter>
2235 | std::uintmax_t
2236 | count_each_reversible_permutation(BidirIter first, BidirIter mid, BidirIter last)
2237 | {
2238 |     return count_each_reversible_permutation<std::uintmax_t>
2239 |                           (std::distance(first, mid), std::distance(mid, last));
2240 | }
2241 | 
2242 | namespace detail
2243 | {
2244 | 
2245 | // Adapt functor to permute over [first+1, last)
2246 | //   A reversible circular permutation of N items is done by holding the first
2247 | //   item and reverse-permuting [first+1, last).
2248 | template <class Function, class BidirIter>
2249 | class reverse_circular_permutation
2250 | {
2251 |     typedef typename std::iterator_traits<BidirIter>::difference_type D;
2252 | 
2253 |     Function f_;
2254 |     D s_;
2255 | 
2256 | public:
2257 |     explicit reverse_circular_permutation(Function f, D s) : f_(f), s_(s) {}
2258 | 
2259 |     bool
2260 |     operator()(BidirIter first, BidirIter last)
2261 |     {
2262 |         if (s_ == 1)
2263 |             return f_(first, last);
2264 |         typedef typename std::iterator_traits<BidirIter>::difference_type D;
2265 |         typedef bound_range<Function, BidirIter> BoundFunc;
2266 |         BoundFunc f(f_, first, last);
2267 |         BidirIter n = std::next(first);
2268 |         return reversible_permutation<BoundFunc, D>(f, std::distance(n, last))(n, last);
2269 |     }
2270 | };
2271 | 
2272 | }  // detail
2273 | 
2274 | template <class BidirIter, class Function>
2275 | Function
2276 | for_each_reversible_circular_permutation(BidirIter first,
2277 |                                          BidirIter mid,
2278 |                                          BidirIter last, Function f)
2279 | {
2280 |     for_each_combination(first, mid, last, detail::reverse_circular_permutation<Function&,
2281 |                           BidirIter>(f, std::distance(first, mid)));
2282 |     return f;
2283 | }    
2284 | 
2285 | template <class UInt>
2286 | UInt
2287 | count_each_reversible_circular_permutation(UInt d1, UInt d2)
2288 | {
2289 |     // return d1 == 0 ? 1 : d1 <= 2 ? (d1+d2)!/(d1*d2!) : (d1+d2)!/(2*d1*d2!)
2290 |     check_non_negative(d1, d2);
2291 |     UInt r;
2292 |     try
2293 |     {
2294 |         r = count_each_combination(d1, d2);
2295 |     }
2296 |     catch (const std::overflow_error&)
2297 |     {
2298 |         throw std::overflow_error("overflow in count_each_reversible_circular_permutation");
2299 |     }
2300 |     if (d1 > UInt(3))
2301 |     {
2302 |         for (--d1; d1 > UInt(2); --d1)
2303 |         {
2304 |             if (r > std::numeric_limits<UInt>::max()/d1)
2305 |                 throw std::overflow_error("overflow in count_each_reversible_circular_permutation");
2306 |             r *= d1;
2307 |         }
2308 |     }
2309 |     return r;
2310 | }
2311 | 
2312 | template <class BidirIter>
2313 | std::uintmax_t
2314 | count_each_reversible_circular_permutation(BidirIter first, BidirIter mid,
2315 |                                                BidirIter last)
2316 | {
2317 |     return count_each_reversible_circular_permutation<std::uintmax_t>
2318 |                           (std::distance(first, mid), std::distance(mid, last));
2319 | }
2320 | 
2321 | 2322 | 2323 | 2324 | 2325 | -------------------------------------------------------------------------------- /fig1.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HowardHinnant/combinations/ece66e0a0b97efc4d6739a0133f0916192a15c30/fig1.tiff -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "combinations.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // print out a range separated by commas, 10 | // return number of values printed. 11 | template 12 | size_t 13 | display(It begin, It end) 14 | { 15 | size_t r = 0; 16 | if (begin != end) 17 | { 18 | std::cout << *begin; 19 | ++r; 20 | for (++begin; begin != end; ++begin) 21 | { 22 | std::cout << ", " << *begin; 23 | ++r; 24 | } 25 | } 26 | return r; 27 | } 28 | 29 | // functor called for each permutation 30 | class f 31 | { 32 | size_t len; 33 | std::uint64_t count; 34 | public: 35 | explicit f(size_t l) : len(l), count(0) {} 36 | 37 | template 38 | bool operator()(It first, It last) // called for each permutation 39 | { 40 | // count the number of times this is called 41 | ++count; 42 | // print out [first, mid) surrounded with [ ... ] 43 | std::cout << "[ "; 44 | size_t r = display(first, last); 45 | // If [mid, last) is not empty, then print it out too 46 | // prefixed by " | " 47 | if (r < len) 48 | { 49 | std::cout << " | "; 50 | display(last, std::next(last, len - r)); 51 | } 52 | std::cout << " ]\n"; 53 | return false; // Don't break out of the loop 54 | } 55 | 56 | operator std::uint64_t() const {return count;} 57 | }; 58 | 59 | int main() 60 | { 61 | const int r = 3; 62 | const int n = 5; 63 | std::vector v(n); 64 | std::iota(v.begin(), v.end(), 0); 65 | std::uint64_t count = for_each_permutation(v.begin(), 66 | v.begin() + r, 67 | v.end(), 68 | f(v.size())); 69 | // print out "---" to the correct length for the above output 70 | size_t e = 3 * r + 2; 71 | if (r < v.size()) 72 | e += 1 + 3 * (v.size() - r); 73 | for (size_t i = 0; i < e; ++i) 74 | std::cout << '-'; 75 | // print out the permuted vector to show that it has the original order 76 | std::cout << "\n[ "; 77 | display(v.begin(), v.end()); 78 | std::cout << " ]\n"; 79 | // sanity check 80 | assert(count == count_each_permutation(v.begin(), v.begin() + r, v.end())); 81 | // print out summary of what has happened, 82 | // using 'count' from functor state returned from for_each_permutation algorithm. 83 | std::cout << "Found " << count << " permutations of " << v.size() 84 | << " objects taken " << r << " at a time.\n"; 85 | } 86 | 87 | --------------------------------------------------------------------------------