#!/usr/bin/ruby

#
## https://rosettacode.org/wiki/Permutations_with_some_identical_elements
#

func next_unique_perm (array) {

    var k = array.end
    return ([], false) if (k < 0)
    var i = k-1

    while ((i >= 0) && (array[i] >= array[i+1])) {
        --i
    }

    return (array.flip, false) if (i == -1)

    if (array[i+1] > array[k]) {
        array = [array.slice(0, i+1)..., array.slice(i+1, k+1).flip...]
    }

    var j = i+1
    while (array[i] >= array[j]) {
        j++
    }

    array.clone!
    array.swap(i,j)

    return (array, true)
}

func unique_permutations(array) {
    var perm  = array
    var perms = [perm]
    loop {
        (perm, var more) = next_unique_perm(perm)
        break if !more
        perms << perm
    }
    return perms
}

for arr in ([[1,1,2], [1,1,2,2,2,3], %w(A A B B B C)]) {
    say "\nPermutations with array = #{arr}:"
    var perms1 = unique_permutations(arr)
    var perms2 = arr.permutations.uniq
    assert_eq(perms1, perms2)
    say perms1.map{.join}.join(' ')
}
