9
\$\begingroup\$

Challenge:

Output all distinct permutations of a, potentially long, list of positive integers. You may assume that the vector has less than 1,000 numbers when testing, but the process should in theory work for any vector with more than one number regardless of size.

Restrictions:

  • You must restrict the memory usage to O(n^2), where n is the number of elements in the input vector. You can't have O(n!). That means you can't store all permutations in memory.
  • You must restrict the time complexity to O(result size * n). If all numbers are equal, then this will be O(n), and if all are distinct, then this will be O(n!*n). That means you can't create a permutation and check it against all other permutations to ensure distinctness (that would be O(n!^2*n)).
  • Empirical measurements to show that time and memory restrictions are met are accepted.
  • You must actually print/output the permutations (since it's impossible to store them).

If you run your program long enough, then all permutations should be outputted (in theory)!

Distinct permutations:

The list [1, 1, 2] has three permutations, not six: [1, 1, 2], [1, 2, 1] and [2, 1, 1]. You may choose the order of the output.


Manageable test cases:

Input: 
[1, 2, 1]
Output:
[1, 1, 2]
[1, 2, 1]
[2, 1, 1] 

Input:
[1, 2, 3, 2]
Output:
[1, 2, 2, 3]
[1, 2, 3, 2]
[1, 3, 2, 2]
[2, 1, 2, 3]
[2, 1, 3, 2]
[2, 2, 1, 3]
[2, 2, 3, 1]
[2, 3, 1, 2]
[2, 3, 2, 1]
[3, 1, 2, 2]
[3, 2, 1, 2]
[3, 2, 2, 1]

Input:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Output:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Larger test case:

It's impossible to output all permutations for this one, but it should work in theory if you gave it enough time (but not unlimited memory).

Input:
[1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900]

You must explain how you know that all permutations are distinct, and that all permutations will be printed, eventually.

This is so the shortest code in bytes win.

\$\endgroup\$
  • 2
    \$\begingroup\$ Is there a reference implementation that meets these complexity requirements? \$\endgroup\$ – Steven H. Nov 7 '17 at 20:09
  • 1
    \$\begingroup\$ It shouldn't be too hard to come up with an algorithm that meets the requirements (it might not be very golfy though). I'm not a programmer or mathematician, I'm nothing but a humble challenge writer. I'll leave the tricky stuff for you guys/girls :) \$\endgroup\$ – Stewie Griffin Nov 7 '17 at 20:18
  • 6
    \$\begingroup\$ I think given the restrictions characteristics this would come better as a fastest code, since code golf is usually for clever use of built ins and language features. \$\endgroup\$ – Uriel Nov 7 '17 at 21:27
  • 3
    \$\begingroup\$ "It shouldn't be too hard" ≠ "it is possible" \$\endgroup\$ – Fatalize Nov 7 '17 at 21:54
  • 1
    \$\begingroup\$ Is a generating function acceptable or must we add boilerplate to such a solution to print/output? \$\endgroup\$ – Jonathan Allan Nov 7 '17 at 23:10
6
\$\begingroup\$

JavaScript (ES6), 177 169 bytes

a=>{s=''+a
do{console.log(a)
k=a.findIndex((e,i)=>a[i-1]>e)
if(~k)t=a[k],a[k]=a[l=a.findIndex(e=>e>t)],a[l]=t,a=a.map((e,i)=>i<k?a[k+~i]:e)
else a.reverse()}while(a!=s)}

Uses the well-known next lexicographic permutation generation algorithm, which I believe has memory O(len(array)) and time O(len(array)*len(output)). (Note that the array elements are considered to be in reverse order, so that e.g. 2, 2, 1, 1 will enumerate to 2, 1, 2, 1; 1, 2, 2, 1 etc.

\$\endgroup\$
5
\$\begingroup\$

Python 3 with sympy, (50?) 81 bytes

lambda a:[print(v)for v in sympy.iterables.multiset_permutations(a)]
import sympy

Try it online!

50 bytes if a generator function is acceptable:

import sympy
sympy.iterables.multiset_permutations

The implementation is open source and currently available on git hub, at the time of writing the function is at line 983.

I think it does, but do let me know if it does not, fulfil the asymptotic bounds.


Python 2, (411?) 439 bytes

A golfed version (also ignoring cases we are not required to cover) in Python 2 (still using the built-in itertools.permutations function) comes in at 439 bytes, or 411 with no additional boilerplate to print rather than generate (the for v in h(input()):print v):

from itertools import*
def h(a,z=-1,g=1):
 x=[v for v in[g,[[v,a.count(v)]for v in set(a)]][g==1]if 0<v[1]];S=sum([v[1]for v in x])
 if x==x[:1]:k,v=x[0];yield[k for i in range([[0,z][z<=v],v][z<1])]
 elif all(v<2for k,v in x):
    for p in permutations([v[0]for v in x],[z,None][z<0]):yield list(p)
 else:
    z=[S,z][z>-1];i=0
    for k,v in x:
     x[i][1]-=1
     for j in h([],z-1,x):
        if j:yield[k]+j
     x[i][1]+=1;i+=1
for v in h(input()):print v

(note: this uses the Python 2 golf of alternating tab and spaces for indents)

\$\endgroup\$
  • \$\begingroup\$ There's no need to write "at the time of writing the function is at line 983", you can permalink to the latest commit: github.com/sympy/sympy/blob/… . \$\endgroup\$ – orlp Nov 8 '17 at 7:04
  • \$\begingroup\$ @orlp Isn't there a permalink to there already? \$\endgroup\$ – Erik the Outgolfer Nov 8 '17 at 13:24
  • \$\begingroup\$ @EriktheOutgolfer I linked to a specific commit, not 'the latest version', so that means my link will not be made out-of-date by future changes. \$\endgroup\$ – orlp Nov 8 '17 at 13:26
2
\$\begingroup\$

C++ (gcc), 203 bytes

Apparently C++ has this as a builtin function...

#import<bits/stdc++.h>
using namespace std;main(){vector<int>v;int x;while(cin>>x)v.push_back(x);sort(v.begin(),v.end());do{for(int y:v)cout<<y<<' ';puts("");}while(next_permutation(v.begin(),v.end()));}

Try it online!

Ungolfed code: TIO link.

This use O(n) memory (guaranteed by std::vector) and optimal runtime.

Some optimizations in code:

  • Use import instead of include (G++ deprecated extension)
  • Use bits/stdc++.h (precompiled header contains all other headers) instead of multiple necessary headers. Often this makes compile time slower.
  • using namespace std which is known to be a bad idea.
  • Use puts("") instead of cout<<'\n' for writing a newline. This is normal for C program, but feels weird for me. So I think this should be mentioned.
  • main return value (int) can be omitted.

Otherwise (apart from whitespace deletion) it's the same way how I often program in C++.

Some possible optimizations: (I don't know if that is allowed by default):

  • Enter array size before enter elements. This will allow dynamic-size array, overall save 30 bytes.
  • Not separate the outputs with separators. So the output will like 1 1 2 3 1 1 3 2 1 2 1 3 1 2 3 1 1 3 1 2 1 3 2 1 2 1 1 3 2 1 3 1 2 3 1 1 3 1 1 2 3 1 2 1 3 2 1 1 for 1 2 1 3. This allows save more 9 bytes.
  • While in C it is allowed to omit headers, I don't know if there is a shorter way to use those functions without #import the headers in C++, or a shorter header name.
\$\endgroup\$
  • \$\begingroup\$ Maybe you should mention why std::sort doesn't make time complexity overflow \$\endgroup\$ – l4m2 Oct 20 '18 at 17:23
  • \$\begingroup\$ Also 2 bytes saved using namespace std;main(){vector<int>v;for(int x;cin>>x;v.push_back(x));sort(v.begin(),v.end());do for(int y:v)cout<<y<<' ';while(puts(""),next_permutation(v.begin(),v.end()));} \$\endgroup\$ – l4m2 Oct 20 '18 at 17:29
  • \$\begingroup\$ #import<bits/stdc++.h>@#define Q v.begin(),v.end())@using namespace std;main(){vector<int>v;for(int x;cin>>x;v.push_back(x));sort(Q;do for(int y:v)cout<<y<<' ';while(puts(""),next_permutation(Q);} @ is newline \$\endgroup\$ – l4m2 Oct 21 '18 at 12:57
2
\$\begingroup\$

Scala (48 bytes)

def%(i:Seq[Int])=i.permutations.foreach(println)

Try it online

permutations returns an iterator over distinct permutations.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 137 128 123 bytes

s=>f(x=c=[],s.map(g=i=>g[i]=-~g[i]));f=i=>Object.keys(g).map(i=>g(i,--g[i]||delete g[i],f(x[c++]=i),c--))<1&&console.log(x)

Try it online!

s=>
    f(
        x=c=[],
        s.map(g=i=>g[i]=-~g[i]) // O(n) if all same, <=O(n^2) if different
    )
;
f=i=>
    Object.keys(g).map( // for(i in g) breaks when other items get removed
        i=>g(
            i,
            --g[i]||delete g[i], // O(left possible numbers)<O(child situations)
            f(x[c++]=i),
            c--
        )
    )<1
&&
    console.log(x)
\$\endgroup\$
0
\$\begingroup\$

APL(NARS), 156 chars, 312 bytes

r←d F w;i;k;a;m;j;v
r←w⋄→0×⍳1≥k←↑⍴w⋄a←⍳k⋄j←i←1⋄r←⍬⋄→C
A: m←i⊃w⋄→B×⍳(i≠1)∧j=m
   v←m,¨(d,m)∇w[a∼i]
   →H×⍳0=↑⍴v⋄⎕←∊d,v
H: j←m
B: i+←1
C: →A×⍳i≤k

G←{⍬F⍵[⍋⍵]}

They, F and G would be 2 function to use togheter... G first order the array than apply to the that ordined array the function F and write permutations using the observation that if the element is already found, better not to go to recursion (because all the result would be already found). I don't know if this fit all restritions... Test:

  G 1 1 2
1 1 2 
1 2 1 
2 1 1 

  G 1 2 3 2
1 2 2 3 
1 2 3 2 
1 3 2 2 
2 1 2 3 
2 1 3 2 
2 2 1 3 
2 2 3 1 
2 3 1 2 
2 3 2 1 
3 1 2 2 
3 2 1 2 
3 2 2 1 

  G 'abb'
abb
bab
bba
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.