# How to elegantly express the same operation for permutations of x, y and z?

**URL:** <https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728>\
**Category:** General Usage\
**Created:** [November 7, 2020, 10:15am UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728 "2020-11-07T10:15:59Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 7, 2020, 10:15am UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/1 "2020-11-07T10:15:59Z")

</div>

This is a situation I face very often: I have the same operation that needs to be run once for each dimension of a 3D construct.

This is complicated because the order of indices differs for each variant, and I don’t know how to express this different ordering elegantly, causing me to duplicate or triplicate lots of code.

Here’s one example: Let’s say the task is to flip two dimensions of a point, the dimension staying intact is given as an integer. This would be a solution like the ones I usually write, which are annoying me because they are so redundant and need control flow:

```julia
function flip_parts(point, dim::Int)
    if dim == 1
        (point[1], point[3], point[2])
    elseif dim == 2
        (point[3], point[2], point[1])
    elseif dim == 3
        (point[2], point[1], point[3])
    else
        error()
    end
end

```

I don’t know how to generically express the different ordering of elements to build the return tuples given only the dim input argument.

Who can point me to an elegant way of solving problems like this? Ideally in the most generic and performant way possible?

---

<div class="post-metadata">

**Author:** ![jagot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jagot/32/12217_2.png) [@jagot](https://discourse.julialang.org/u/jagot)\
**Post date:** [November 7, 2020, 10:45am UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/2 "2020-11-07T10:45:15Z")

</div>

I have not thought through the whole problem, but one way of finding which the two dimensions that should be flipped are, given the fixed dimension `d` is using `mod1`:

```julia
julia> for d = 1:3
           @show d, mod1(d-1,3), mod1(d+1,3)
       end
(d, mod1(d - 1, 3), mod1(d + 1, 3)) = (1, 3, 2)
(d, mod1(d - 1, 3), mod1(d + 1, 3)) = (2, 1, 3)
(d, mod1(d - 1, 3), mod1(d + 1, 3)) = (3, 2, 1)

```

EDIT: It appears this snippet gives you the ordering you want:

```julia
julia> for d = 1:3
           @show circshift([d, mod1(d-1, 3), mod1(d+1, 3)], d-1)
       end
circshift([d, mod1(d - 1, 3), mod1(d + 1, 3)], d - 1) = [1, 3, 2]
circshift([d, mod1(d - 1, 3), mod1(d + 1, 3)], d - 1) = [3, 2, 1]
circshift([d, mod1(d - 1, 3), mod1(d + 1, 3)], d - 1) = [2, 1, 3]

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [November 7, 2020, 12:43pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/3 "2020-11-07T12:43:45Z")

</div>

Looks like the orderings are just the cyclic permutations of `(3,2,1)`. So maybe `circshift` is indeed the way to go:

```julia
julia> circshift.(Ref(reverse(1:3)), 1:3)
3-element Array{Array{Int64,1},1}:
 [1, 3, 2]
 [2, 1, 3]
 [3, 2, 1]

```

You can do the operation in place with `circshift!` to limit memory allocation. I don’t know if this can be better than the branching though.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 7, 2020, 12:46pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/4 "2020-11-07T12:46:33Z")

</div>

Maybe to get away from this particular problem, because it’s not about just this one, let me rephrase the question:

What is the best way to express an algorithm, in which the order of elements in something like a tuple, svector, etc. needs to be determined at runtime? Can this be done without allocating?

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [November 7, 2020, 1:12pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/5 "2020-11-07T13:12:11Z")

</div>

I’ve found [TupleTools.jl](https://github.com/Jutho/TupleTools.jl) to be useful for type stable tuple manipulations like sorting, maybe it can help here too.

---

<div class="post-metadata">

**Author:** ![jagot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jagot/32/12217_2.png) [@jagot](https://discourse.julialang.org/u/jagot)\
**Post date:** [November 7, 2020, 3:34pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/6 "2020-11-07T15:34:22Z")

</div>

I’m not sure that there is a one-size-fits-all solution without seeing more examples, but this appears to be allocation-free, and rather quick:

```julia
function test_permutation(d)
    a,b,c = ((1,3,2), (2,1,3), (3,2,1))[d]
end

using BenchmarkTools
@eval @benchmark test_permutation($(rand(1:3)))

```

```julia
BenchmarkTools.Trial:
  memory estimate: 0 bytes
  allocs estimate: 0
  --------------
  minimum time: 0.040 ns (0.00% GC)
  median time: 0.043 ns (0.00% GC)
  mean time: 0.043 ns (0.00% GC)
  maximum time: 0.220 ns (0.00% GC)
  --------------
  samples: 10000
  evals/sample: 1000

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [November 7, 2020, 8:46pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/7 "2020-11-07T20:46:36Z")

</div>

You need a `Ref` there. But still this solution takes “no time at all” and doesn’t allocate as you said.

```julia
julia> @btime test_permutation($(Ref(2))[])
  1.970 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [November 8, 2020, 9:32am UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/8 "2020-11-08T09:32:40Z")

</div>

`map` and `ntuple` are very helpful when dealing with `Tuple`s, so (complementing the reply above) things like

```julia
perm = ((1,3,2), (2,1,3), (3,2,1))[dim]
map(i -> point[i], perm)

```

should be fast and non-allocating.

Alternatively, if you have a function `f` (or a matrix `mat`) such as `f(i, dim)` (resp. `mat[i, dim]`) returns the new index, you could also use `ntuple`:

```julia
ntuple(3) do i
    idx = f(i, dim)
    return point[idx]
end

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 8, 2020, 12:22pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/9 "2020-11-08T12:22:19Z")

</div>

Ah the map and ntuple path could be what I was looking for!

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 8, 2020, 1:31pm UTC](https://discourse.julialang.org/t/how-to-elegantly-express-the-same-operation-for-permutations-of-x-y-and-z/49728/10 "2020-11-08T13:31:38Z")

</div>

I would just define tiny functions for the permutation, eg

```julia
dim2perm(t) = (t[3], t[2], t[1])

```

and pass these around as arguments to the relevant methods.
