Output all distinct permutations of a vector

9

2

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.

Stewie Griffin

Posted 2017-11-07T19:50:00.623

Reputation: 43 471

2Is there a reference implementation that meets these complexity requirements? – Steven H. – 2017-11-07T20:09:37.513

1It 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 :) – Stewie Griffin – 2017-11-07T20:18:23.433

6I 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. – Uriel – 2017-11-07T21:27:46.353

3"It shouldn't be too hard" ≠ "it is possible" – Fatalize – 2017-11-07T21:54:38.990

Is the memory limitation only for RAM? As in can I store temporary results in a file to not technically have them "in memory"? – Magic Octopus Urn – 2017-11-07T22:08:48.883

The so-called larger test case has binomial(905,6)*899! permutations.

– Jeppe Stig Nielsen – 2017-11-07T23:04:03.043

1Is a generating function acceptable or must we add boilerplate to such a solution to print/output? – Jonathan Allan – 2017-11-07T23:10:39.483

Is it mandatory that the answerer prove the time complexity and memory usage of the code, or are empirical measurements sufficient (e.g. by using built-in benchmarks)? – JungHwan Min – 2017-11-08T01:03:32.380

@JungHwanMin empirical measurements are sufficient. – Stewie Griffin – 2017-11-08T06:22:45.427

@JeppeStigNielsen I know. That's why it's not in the list of test cases that can be tested properly. The large test case should in theory output every permutation if you kept it running long enough. It can't print all permutations, but it shouldn't fail due to memory usage. – Stewie Griffin – 2017-11-08T06:26:18.610

@MagicOctopusUrn will that help you? There aren't enough atoms in the universe to store even a tiny fraction of the total number of permutations for the large test case, so you can't store permutations in order to check for distinctness, if that's what you're aiming for. – Stewie Griffin – 2017-11-08T06:29:14.093

@JonathanAllan I don't know exactly what a generator is to be honest, but if I'm not mistaken, you would need to create all permutations and return that list when you're finished. I think (but I'm not sure) that it would require O(n!) memory? If you can create all permutations for large lists, given enough time (but not unlimited memory), then it's OK. – Stewie Griffin – 2017-11-08T06:37:33.603

1Why 3 down vote ? Is it one impossible exercise ? – RosLuP – 2018-10-22T09:45:53.007

Answers

6

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.

Neil

Posted 2017-11-07T19:50:00.623

Reputation: 95 035

5

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)

Jonathan Allan

Posted 2017-11-07T19:50:00.623

Reputation: 67 804

There's no need to write "at the time of writing the function is at line 983", you can permalink to the latest commit: https://github.com/sympy/sympy/blob/8ada3462d6c1fbf3d7f733af494da1e055529d92/sympy/utilities/iterables.py#L983 .

– orlp – 2017-11-08T07:04:57.497

@orlp Isn't there a permalink to there already? – Erik the Outgolfer – 2017-11-08T13:24:30.160

@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. – orlp – 2017-11-08T13:26:36.803

2

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.

user202729

Posted 2017-11-07T19:50:00.623

Reputation: 14 620

Maybe you should mention why std::sort doesn't make time complexity overflow – l4m2 – 2018-10-20T17:23:52.357

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()));} – l4m2 – 2018-10-20T17:29:13.533

#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 – l4m2 – 2018-10-21T12:57:25.003

2

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)

l4m2

Posted 2017-11-07T19:50:00.623

Reputation: 5 985

2

Scala (48 bytes)

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

Try it online

permutations returns an iterator over distinct permutations.

jrook

Posted 2017-11-07T19:50:00.623

Reputation: 211

0

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

RosLuP

Posted 2017-11-07T19:50:00.623

Reputation: 3 036