permutations_with_some_identical_elements.sf 1.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Permutations_with_some_identical_elements
  4. #
  5. func next_unique_perm (array) {
  6. var k = array.end
  7. return ([], false) if (k < 0)
  8. var i = k-1
  9. while ((i >= 0) && (array[i] >= array[i+1])) {
  10. --i
  11. }
  12. return (array.flip, false) if (i == -1)
  13. if (array[i+1] > array[k]) {
  14. array = [array.slice(0, i+1)..., array.slice(i+1, k+1).flip...]
  15. }
  16. var j = i+1
  17. while (array[i] >= array[j]) {
  18. j++
  19. }
  20. array.clone!
  21. array.swap(i,j)
  22. return (array, true)
  23. }
  24. func unique_permutations(array) {
  25. var perm = array
  26. var perms = [perm]
  27. loop {
  28. (perm, var more) = next_unique_perm(perm)
  29. break if !more
  30. perms << perm
  31. }
  32. return perms
  33. }
  34. for arr in ([[1,1,2], [1,1,2,2,2,3], %w(A A B B B C)]) {
  35. say "\nPermutations with array = #{arr}:"
  36. var perms1 = unique_permutations(arr)
  37. var perms2 = arr.permutations.uniq
  38. assert_eq(perms1, perms2)
  39. say perms1.map{.join}.join(' ')
  40. }