# Julia: Unique n-item sets with replacement

Given a vector `v = [1,..,n]`

, I am trying to compute all unique sets of n elements with replacements in julia.

Since I want to do this for large n values, I am looking for an efficient solution, perhaps using iterators.

For example, consider `v = [1, 2, 3]`

: this should result in `[1,1,1], [1,1,2], [1,1,3], [1,2,2], [1,2,3], [1,3,3], [2,2,2], [2,2,3], [2,3,3], [3,3,3]`

. By unique, I mean that if it `[1,1,2]`

is a solution, any permutation of `[1,2,1], [2,1,1]`

it is not.

My current solution is function based `partitions`

but does not allow me to restrict the computation on elements [1, .., n]

``````for i in n:n^2
for j in partitions(i, n)
## ignore sets which exceed the range [1,n]
if maximum(j) <= n
## accept as solution
end
end
end
```

```
+3

source to share

I guess it doesn't get any shorter than a one-liner (using iterators).

``````using Iterators
n=3
collect(imap(c -> Int[c[k]-k+1 for k=1:length(c)],combinations([1:(2n-1)],n)))
```

```
+2

source

I believe you are looking for a product feature from the Iterators package. In your case, the product (v, v, v) should do what is required.

+2

source

Here is the function to calculate the required collection:

``````function calcset(n=3)
res = []
for c in combinations([1:(2n-1)],n-1)
c3 = [c,2n].-[0,c]
push!(res,vcat([fill(i,c3[n-i+1]-1) for i=1:n]...))
end
return res
end
calcset(3)
```

```

There is probably a better way to code this, but that should be enough. Note that the result is generated through repeated `push!`

s, so it easily turns into an iterator if needed.

+1

source

And in the form of an iterator:

``````import Base: start, next, done, eltype, length
type ImageTypeIterator
inneritr::Base.Combinations{Array{Int64,1}}
n::Int
end
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n-1),n)
eltype(itr::ImageTypeIterator) = Array{Int64,1}
start(itr::ImageTypeIterator) = start(itr.inneritr)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
c3 = [c,2*itr.n].-[0,c]
(vcat([fill(i,c3[itr.n-i+1]-1) for i=1:itr.n]...),s)
end
done(itr::ImageTypeIterator,s) = done(itr.inneritr,s)
length(itr::ImageTypeIterator) = length(itr.inneritr)
# test with [1,2,3]
for t in imagetype(3) println(t) ; end
```

```

The test at the end should print the collection set in question.

By the way, the name ImageTypeIterator is an attempt to characterize the collection as different types of preimage sizes when looking at the function f: [1: n] → [1: n]. But there may be a different interpretation. Other name suggestions are welcome in the comments.

Faster? / Clearer? the implementation can use:

``````imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n),n)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
v = Array(Int,itr.n)
j = 1 ; p = 1
for k=1:itr.n
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
(v,s)
end
```

```

Its the same logic as above, but without unnecessary cutting. The logic takes a subset of 2n-1 and treats non-whitespaces as duplicate values ​​and whitespaces as a trigger to move to the next value.

+1

source

OK, a simpler version using Iterators.jl:

``````using Iterators
function ff(c)
v = Array(Int,length(c))
j = 1 ; p = 1
for k=1:length(c)
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
v
end
# test
n = 3
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end
```

```

This is perhaps the simplest version, although it is equivalent to the methods of the other answers.

And in a spirit of brevity:

``````using Iterators
ff(c) = begin
j=1;p=1; [(while !(j in c) j+=1;p+=1 ; end ; j+=1 ; p) for k=1:length(c)]
end
n = 3 # test
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end
```

```
+1

source

As of julia v0.5.0 it `combinatorics.jl`

has a method `with_replacement_combinations`

.

``````julia> collect(with_replacement_combinations(1:4,3))
20-element Array{Array{Int64,1},1}:
[1,1,1]
[1,1,2]
[1,1,3]
[1,1,4]
[1,2,2]
[1,2,3]
[1,2,4]
[1,3,3]
[1,3,4]
[1,4,4]
[2,2,2]
[2,2,3]
[2,2,4]
[2,3,3]
[2,3,4]
[2,4,4]
[3,3,3]
[3,3,4]
[3,4,4]
[4,4,4]
```

```
+1

source

All Articles