Timothée HENRY
Timothée HENRY

Reputation: 14614

Generate all permutations of the combination of two arrays

I am not sure the title is right, below are some explanation:

# I have two arrays: segments and directions
k = 3
segments = collect(1:k)
directions = ["same","reversed"]

# I wish now to generate all possible ways to order the k segments, 
# given that each segment can be either in direction "same" or "reversed"
# so the results should look like:

[[1,"same"], [2,"same"], [3,"same"]]
[[1,"same"], [2,"same"], [3,"reversed"]]
[[1,"same"], [2,"reversed"], [3,"same"]]
[[1,"reversed"], [2,"same"], [3,"same"]]
[[1,"same"], [2,"reversed"], [3,"reversed"]]
...
[[2,"same"], [1,"same"], [3,"same"]]
[[2,"same"], [1,"same"], [3,"reversed"]]
...

# I have tried a few things like this (with no success):
using IterTools
collect(product(segments, directions))

The objective is that each row covers the three segments, each having a single direction.

Upvotes: 6

Views: 799

Answers (1)

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69939

This is an initial answer (which is incorrect, as I incorrectly understood the question, see edit below for a corrected answer).


A natural way to do it is:

julia> collect(Iterators.product(fill(directions, k)...))
2×2×2 Array{Tuple{String, String, String}, 3}:
[:, :, 1] =
 ("same", "same", "same")      ("same", "reversed", "same")
 ("reversed", "same", "same")  ("reversed", "reversed", "same")

[:, :, 2] =
 ("same", "same", "reversed")      ("same", "reversed", "reversed")
 ("reversed", "same", "reversed")  ("reversed", "reversed", "reversed")

since you do not really need the numbers 1,2,3 here as they are encoded by the index. Also using tuples instead of vectors should be a bit more efficient in this case.

If you want to add them and convert the result to a vector of vectors per your question then do:

julia> [vcat.(1:k, x) for x in Iterators.product(fill(directions, k)...)]
2×2×2 Array{Vector{Vector{Any}}, 3}:
[:, :, 1] =
 [[1, "same"], [2, "same"], [3, "same"]]      [[1, "same"], [2, "reversed"], [3, "same"]]
 [[1, "reversed"], [2, "same"], [3, "same"]]  [[1, "reversed"], [2, "reversed"], [3, "same"]]

[:, :, 2] =
 [[1, "same"], [2, "same"], [3, "reversed"]]      [[1, "same"], [2, "reversed"], [3, "reversed"]]
 [[1, "reversed"], [2, "same"], [3, "reversed"]]  [[1, "reversed"], [2, "reversed"], [3, "reversed"]]

finally if you want a vector then do:

julia> [vcat.(1:k, x) for x in Iterators.product(fill(directions, k)...)] |> vec
8-element Vector{Vector{Vector{Any}}}:
 [[1, "same"], [2, "same"], [3, "same"]]
 [[1, "reversed"], [2, "same"], [3, "same"]]
 [[1, "same"], [2, "reversed"], [3, "same"]]
 [[1, "reversed"], [2, "reversed"], [3, "same"]]
 [[1, "same"], [2, "same"], [3, "reversed"]]
 [[1, "reversed"], [2, "same"], [3, "reversed"]]
 [[1, "same"], [2, "reversed"], [3, "reversed"]]
 [[1, "reversed"], [2, "reversed"], [3, "reversed"]]

EDIT

Is this what you want then:

julia> using Combinatorics

julia> x1 = permutations(segments)
Combinatorics.Permutations{Vector{Int64}}([1, 2, 3], 3)

julia> x2 = Iterators.product(fill(directions, k)...)
Base.Iterators.ProductIterator{Tuple{Vector{String}, Vector{String}, Vector{String}}}((["same", "reversed"], ["same", "reversed"], ["same", "reversed"]))

julia> [vcat.(v...) for v in Iterators.product(x1, x2)]
6×2×2×2 Array{Vector{Vector{Any}}, 4}:
[:, :, 1, 1] =
 [[1, "same"], [2, "same"], [3, "same"]]  [[1, "reversed"], [2, "same"], [3, "same"]]
 [[1, "same"], [3, "same"], [2, "same"]]  [[1, "reversed"], [3, "same"], [2, "same"]]
 [[2, "same"], [1, "same"], [3, "same"]]  [[2, "reversed"], [1, "same"], [3, "same"]]
 [[2, "same"], [3, "same"], [1, "same"]]  [[2, "reversed"], [3, "same"], [1, "same"]]
 [[3, "same"], [1, "same"], [2, "same"]]  [[3, "reversed"], [1, "same"], [2, "same"]]
 [[3, "same"], [2, "same"], [1, "same"]]  [[3, "reversed"], [2, "same"], [1, "same"]]

[:, :, 2, 1] =
 [[1, "same"], [2, "reversed"], [3, "same"]]  [[1, "reversed"], [2, "reversed"], [3, "same"]]
 [[1, "same"], [3, "reversed"], [2, "same"]]  [[1, "reversed"], [3, "reversed"], [2, "same"]]
 [[2, "same"], [1, "reversed"], [3, "same"]]  [[2, "reversed"], [1, "reversed"], [3, "same"]]
 [[2, "same"], [3, "reversed"], [1, "same"]]  [[2, "reversed"], [3, "reversed"], [1, "same"]]
 [[3, "same"], [1, "reversed"], [2, "same"]]  [[3, "reversed"], [1, "reversed"], [2, "same"]]
 [[3, "same"], [2, "reversed"], [1, "same"]]  [[3, "reversed"], [2, "reversed"], [1, "same"]]

[:, :, 1, 2] =
 [[1, "same"], [2, "same"], [3, "reversed"]]  [[1, "reversed"], [2, "same"], [3, "reversed"]]
 [[1, "same"], [3, "same"], [2, "reversed"]]  [[1, "reversed"], [3, "same"], [2, "reversed"]]
 [[2, "same"], [1, "same"], [3, "reversed"]]  [[2, "reversed"], [1, "same"], [3, "reversed"]]
 [[2, "same"], [3, "same"], [1, "reversed"]]  [[2, "reversed"], [3, "same"], [1, "reversed"]]
 [[3, "same"], [1, "same"], [2, "reversed"]]  [[3, "reversed"], [1, "same"], [2, "reversed"]]
 [[3, "same"], [2, "same"], [1, "reversed"]]  [[3, "reversed"], [2, "same"], [1, "reversed"]]

[:, :, 2, 2] =
 [[1, "same"], [2, "reversed"], [3, "reversed"]]  [[1, "reversed"], [2, "reversed"], [3, "reversed"]]
 [[1, "same"], [3, "reversed"], [2, "reversed"]]  [[1, "reversed"], [3, "reversed"], [2, "reversed"]]
 [[2, "same"], [1, "reversed"], [3, "reversed"]]  [[2, "reversed"], [1, "reversed"], [3, "reversed"]]
 [[2, "same"], [3, "reversed"], [1, "reversed"]]  [[2, "reversed"], [3, "reversed"], [1, "reversed"]]
 [[3, "same"], [1, "reversed"], [2, "reversed"]]  [[3, "reversed"], [1, "reversed"], [2, "reversed"]]
 [[3, "same"], [2, "reversed"], [1, "reversed"]]  [[3, "reversed"], [2, "reversed"], [1, "reversed"]]

Upvotes: 6

Related Questions