[Question]
  [
Given an N-dimensional orthogonal (non-ragged) array of non-negative integers, and an indication of which dimensions to reverse, return the array but reversed along those dimensions. The indication may be given as a Boolean list of length N or a list of a subset of the first N dimensions indexed from 0 or 1.
Please state your input formats. Code explanations are much appreciated.
## Walked-through example
We are given the 2-layer 3-row 4-column 3D-array
```
[[[ 1, 2, 3, 4],
  [ 5, 6, 7, 8],
  [ 9,10,11,12]],
 [[13,14,15,16],
  [17,18,19,20],
  [21,22,23,24]]]
```
and one of
`[true,false,true]` (Boolean list)  
`[0,2]` (0-indexed list)  
`[1,3]` (1-indexed list)
We need to reverse order of the first and last dimensions, that is the layers and the elements of the rows (the columns), but not the rows of each layer. First (the actual order you do this in does not matter) we reverse the order of the layers:
```
[[[13,14,15,16],
  [17,18,19,20],
  [21,22,23,24]],
 [[ 1, 2, 3, 4],
  [ 5, 6, 7, 8],
  [ 9,10,11,12]]]
```
and then we reverse the order of the elements of each row:
```
[[[16,15,14,13],
  [20,19,18,17],
  [24,23,22,21]],
 [[ 4, 3, 2, 1],
  [ 8, 7, 6, 5],
  [12,11,10, 9]]]
```
## Test cases
`[[[1,2,3,4],[5,6,7,8],[9,10,11,12]],[[13,14,15,16],[17,18,19,20],[21,22,23,24]]]`  
`[true,false,true]`/`[0,2]`/`[1,3]`  
 ↓   
`[[[16,15,14,13],[20,19,18,17],[24,23,22,21]],[[4,3,2,1],[8,7,6,5],[12,11,10,9]]]`
---
`[[1,2,3],[4,5,6]]`  
`[true,false]`/`[0]`/`[1]`  
 ↓  
`[[4,5,6],[1,2,3]]`
---
`[[1],[4]]`  
`[true,false]`/`[0]`/`[1]`  
 ↓  
`[[4],[1]]`
---
`[[7]]`  
`[true,true]`/`[0,1]`/`[1,2]`  
 ↓  
`[[7]]`
---
`[1,2,3,4,5,6,7]`  
`[true]`/`[0]`/`[1]`  
 ↓  
`[7,6,5,4,3,2,1]`
---
`[]`  
`[true]`/`[0]`/`[1]`  
 ↓  
`[]`
---
`[[],[]]`  
`[false,false]`/`[]`/`[]`  
 ↓  
`[[],[]]`
---
`[[[[3,1,4,1],[5,9,2,6]],[[5,3,5,8],[9,7,9,3]]],[[[2,3,8,4],[6,2,6,4]],[[3,3,8,3],[2,7,9,5]]]]`  
`[true,false,true,true]`/`[0,2,3]`/`[1,3,4]`  
 ↓  
`[[[[4,6,2,6],[4,8,3,2]],[[5,9,7,2],[3,8,3,3]]],[[[6,2,9,5],[1,4,1,3]],[[3,9,7,9],[8,5,3,5]]]]`
---
`[[[[3,1,4,1],[5,9,2,6]],[[5,3,5,8],[9,7,9,3]]],[[[2,3,8,4],[6,2,6,4]],[[3,3,8,3],[2,7,9,5]]]]`  
`[false,true,false,false]`/`[1]`/`[2]`  
 ↓  
`[[[[5,3,5,8],[9,7,9,3]],[[3,1,4,1],[5,9,2,6]]],[[[3,3,8,3],[2,7,9,5]],[[2,3,8,4],[6,2,6,4]]]]`
---
`[[[[3,1,4,1],[5,9,2,6]],[[5,3,5,8],[9,7,9,3]]],[[[2,3,8,4],[6,2,6,4]],[[3,3,8,3],[2,7,9,5]]]]`  
`[false,false,false,false]`/`[]`/`[]`  
 ↓  
`[[[[3,1,4,1],[5,9,2,6]],[[5,3,5,8],[9,7,9,3]]],[[[2,3,8,4],[6,2,6,4]],[[3,3,8,3],[2,7,9,5]]]]`
  
[Answer]
# [APL (Dyalog)](https://www.dyalog.com/), ~~20~~ 9 bytes
```
⊃{⌽[⍺]⍵}/
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///P@1R24RHXc3Vj3r2Rj/q3RX7qHdrrT5QWMFQwVhBwwhImDzq3fKod7ORiSYA)
**How?**
`/` - reduce - take the rightmost element in the input (the array) and apply the function with next left element as left argument
`{⌽[⍺]⍵}` - reverse in the `left argument` (`⍺`) dimension
`⊃` - flatten the enclosed array
[Answer]
# [APL (Dyalog Unicode)](https://www.dyalog.com/), 9 [bytes](https://github.com/abrudz/SBCS)
```
⊃{⊖[⍺]⍵}⌿
```
[Try it online!](https://tio.run/##tZCxTsMwGIT3PsVtLQNS/t92nA5MLLBSNsRQCZWlEl0RYmklhghXLPAUjLCw8C7/i4SzQUIguRPESmT7vtzZN18t9y@u58ury2GwfnNj/dOZpbdzS6@3dv8@LOzuwdJWqdn2cXZyyO/p0fFsNOKE2gICN1E4eEsvgjJDQIuIDlNIAxGIQhzEQwKkhURIB5lCGyj/UaiD@r0vz/FBfsbfCdn/p/suVApad4NOpECx7hJ/X6aONkQtPVcA69c80m4mVwhPLI9cI6tirjCZFTE9UA@lzsjXlXN1JNqieq7yOu9nPdRi9N8jPm/7VxnDBw "APL (Dyalog Unicode) – Try It Online")
It looks like [Uriel edited into something almost identical](https://codegolf.stackexchange.com/a/171630/41024) first, but I developed it independently. I thought this input format is invalid.
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), ~~58~~ ~~55~~ ~~53~~ 45 bytes
*Saved 8 bytes thanks to @Shaggy*
Takes input as `(indications)(array)`, where *indications* is a Boolean list.
```
f=([r,...b])=>a=>1/r?a.sort(_=>r).map(f(b)):a
```
[Try it online!](https://tio.run/##zVHLTsMwELzzJbE0mK7zLFLCnQMcOFoWcktSBYWkcgISXx/WpuJ5STlUXKzd1Yx3ZufRvthx69r9dN4PD/U8N2WkHaSUGyPKypYVXbgrK8fBTdF9WTkhn@w@aqKNEJd23g79OHS17IZddH13eyPHybX9rm1eGaIn91yjsd1Yw5dGRFprgkKMxECnyJCj4GoNWoEIpAx3mmJQAkpBGbeUgwrQGmrFnWK@goqhEmOMEOJsqYawPmznbxLw9r/wPXcx78N1vpTi0YcLIdznCN4C6HsYn3bYzXFHwHdfWnNULJVCnByRPyonmLKB9BBtzvPYhLH2xooQfuaxXPlxHKY@FhXQqVkU7RdBP339A12/3hMIm98A "JavaScript (Node.js) – Try It Online")
### Commented
```
f = (                // f is a function taking:
  [r,                //   r = next 'reverse' Boolean flag
      ...b]          //   b = array of remaining flags
) =>                 // and returning an anonymous function taking:
  a =>               //   a = array (or sub-array) to process, or atomic element
    1 / r ?          // if r is defined:
      a.sort(_ => r) //   reverse a if r = 1; leave it unchanged otherwise
      .map(f(b))     //   for each element in the resulting array: do a recursive call,
                     //   using f to generate a new callback function for the next flag
    :                // else:
      a              //   a must be an atomic element and is simply left unchanged
```
[Answer]
# [Python 2](https://docs.python.org/2/), ~~56~~ 55 bytes
```
f=lambda a,t:t and[f(l,t[1:])for l in a][::1|-t[0]]or a
```
[Try it online!](https://tio.run/##vVHLasNADLznK/aYwBSs9duQa7@gN7EHl8Q04DohdQ@F/rsryU5qU1@by6LdndGMNJev/u3c@WFo9m39/nqoXY2@6l3dHbjZtuiZqrBrzlfXulPn6sBVRd9PPUchyGM9XK6nrnfNlpkJHjGSAE6RIUchVQmKQATyQW5MMSgBpaBMrpSDClAJH8nNC9/Dx/BJUPDL9fOI57r9OELLsNvvnapkxpcusZIi5WuXXG@J8aULmVwifjxIykL8ZEhV1JufCKWobDa//s2@ABKIfaG7mQMTdzz9YcIu6Upd@h5ZSlPKEp7foffhFJkvUNNGYfuc8DeozYPbhDPSAscLUflS2XGpS4v2NccyS1bSnyxPyciWwlLHojtmm8t7bGExq9PC0s8UC9uF9NBXS8rQaVjLdrkDXbP1sDAKnXBSVkUvpfW8Kyu2HLNVv/puyubPsjfPITxwwNlsa9teVcGqI9NeUcGqo4eP@Oeczfhv4pvhBw "Python 2 – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 8 bytes
```
”€ẋ”ṚpFv
```
Takes a 0-indexed list of dimensions.
[Try it online!](https://tio.run/##tVA7bkIxEOw5xTvASLxd@324AHeIVi5pIgoqpHRR2nSpokjUNFyAtIiDPC7ijBeTKElNtzM7np3x42q9fsr58ry7vBymz1cO0/Fjs9zm017n57fp@M7FQ85mLTShaRozEygCYoJ16DFg5LSAtBCBaCIyCZAI6SA9oQyQEbKAtkTK9woN0JgonjXWunPxdmtqImj9b1kWlYTUNMMfVQ0Hj/Z75agCvqTbzcyPlmrG3Hws3o15PYRxDjS89hzIh@S0lVOj/0RftIhOB2dLDXV1l2pP@a5y50M/Je94aJa@AA "Jelly – Try It Online")
### How it works
```
”€ẋ”ṚpFv  Main link. Left arg: D (dimensions, 0-based), Right arg: A (array)
”€ẋ       Repeat '€' d times, for each d in D.
   ”Ṛp    Perform Cartesian product of ['Ṛ'] and each string of '€'s, prepending a
          'Ṛ' to each string of '€'s.
      F   Flatten the result.
          If, e.g., D = [0,2,4], we build the string "ṚṚ€€Ṛ€€€€".
       v  Eval the resulting string, using A as left argument.
```
[Answer]
# [R](https://www.r-project.org/), ~~80~~ ~~78~~ 77 bytes
Create the call to R's extractor `[` by creating a list of sequences reversed where indicated. They actually contain zeros, which are silently ignored. The `drop=F` is needed to prevent R's default dropping of dimensions. We need the `rev` call to the dimension reverse indicator, because of the way R fills arrays.
-2 thanks @Giuseppe
-1 using in-line assignment.
```
function(x,a,d=dim(x))do.call("[",c(list(x),Map(seq,r<-d*rev(a),d-r),drop=F))
```
[Try it online!](https://tio.run/##XZDLasMwEEX3@QqhLDoK42I9/CrJNrtuinddCUsGg2q7klOSr3dlt2ATBIN0jq6GkZ9bck7m9tY3Uzf0cEeN5mK6L7gzZobXRjsH9JNiA64LU6T4rkcI9hv9OTEnb39AMzSJj8UP4@XK2NyC9l4/gL8JFYMKJQrG4q7GK9aMHQ7bjTzind7LBjiqhQvkq38KR79Q/m/r56eLCIs/tRdpBCmmW4Ycj@SDmMGG/mUi3saRH/FI@ptzZM2ELW0dhMmH0XUTUMkVzyqRZzIrq6KSQpYqF7mSspSiqDKKlK59FIplbZ@w9J1/AQ "R – Try It Online")
Honorable mention to @JayCe who came up with a variation that gets the same result in the same length:
```
function(x,a,d=dim(x))array(x[t(t(expand.grid(Map(seq,r<-d*rev(a),d-r))))],d)
```
[Try it online!](https://tio.run/##XZA9a8MwEIb3/ArhDD2Vc7E@/FXStVuX4q10EJZcDKrjSkpxfr0rOwWb6Bbpee69A7m5I6d07i5DG/rzABMq1C@6/4aJUuWcusL0ESCAmUY16Kcv12t4UyN484PulOpHZ35BUdSpo/F8oqZzB7cke@YSW5AokFMabw2@YkPp4bB1FBHv9F62wFAunCNb/V04@oWyf9vcjy4jLG9qL7IIMsy2DDkeyTvRZ@OHh0CcUdZe45MMF2vJmvFb2ljwwfnR9gESwSTLa17kIq/qshZcVLLghRSiErys8wSTZN0jkS@1fcKyd/4D "R – Try It Online")
[Answer]
# Haskell, ~~120~~ 119 bytes
the function f takes the N-dimensional list and a list of bool as input
```
class F r where f::[Bool]->r->r
instance F Int where f=seq
instance F r=>F[r]where f(a:y)=last(id:[reverse|a]).map(f y)
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~23~~ ~~11~~ 10 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
'€s×'R«J.V
```
[Try it online.](https://tio.run/##yy9OTMpM/f9f/VHTmuLD09WDDq320gv7/z/aQMdIxziWKxoIjHUMdUx0DGN1ok11LIHCZrFAJpBtrGOqYwFkWuqYA8WNY8HC0UBtOhY6JkC2GUgtkAUSNgaLGgOZRmDVpkDVsQA)
-12 bytes thanks to *@Mr.Xcoder*.
Input as 0-indexed truthy-values (i.e. `[0,2,3]`), which is the first input.
**Explanation:**
```
'€s×           # Repeat "€" the indices amount of times
               #  i.e. [0,2,3] → ["","€€","€€€"]
    'R«        # Append each with "R"
               #  i.e. ["","€€","€€€"] → ["R","€€R","€€€R"]
        J      # Join them all together
               #  i.e. ["R","€€R","€€€R"] → R€€R€€€R
         .V    # Execute string as 05AB1E code
```
For example: if the indices input-list is `[0,2,3]`, it will create the following string:
```
R€€R€€€R
```
Which will:
```
    €€€R    # Reverse the items in the most inner (4th level) lists
 €€R        # Reverse the most inner (3rd level) lists themselves
            # Do nothing with the inner (2nd level) lists 
R           # Reverse the entire outer (1st level) list
```
---
**Original 23 byte answer:**
```
ćURvy„ RèJ…εÿ}}„ RXèJ.V
```
Input as boolean-list (i.e. `[1,0,1,1]`), which is the first input.
[Try it online.](https://tio.run/##yy9OTMpM/f//SHtoUFllpnrQ4dWHt9Z6PWpYdm7r4f21sY8a5ikERRxe4aUX9v9/tKGOgY6hjmEsVzQQGAOZJkCOTrSpjqWOkY5ZLJAJZBvrmOpYAJmWOuZAceNYsHC0EVDcQscEyDYDqQWyQMLGYFFjINMIrNoUqDoWAA)
**Explanation:**
```
ćU                 # Pop and save the first boolean in variable `X`
  R                # Reverse the remaining boolean-list
   v    }          # Loop `y` over each of them:
    „ Rè           #  Take the string "R ", and index the current boolean (0 or 1) in it
    J              #  Join it together with the string of the previous iteration
    …εÿ}           #  Surround it with "ε" and "}"
         „ RXè     # Index variable `X` also in "R "
              J    # Join it together with the rest
.V                 # Execute string as 05AB1E code
```
For example: If the boolean input-list is `[1,0,1,1]`, it will create the following string:
```
εεεR}R} }R
```
Which will:
```
  εR}         # Reverse the items in the most inner (4th level) lists
 ε   R}       # Reverse the most inner (3rd level) lists themselves
ε       }     # Do nothing with the inner (2nd level) lists 
         R    # Reverse the entire outer (1st level) list
```
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 60 bytes
*A different (recursive) approach. doesn't beat Arnauld's answer ... yet....*
Takes the input as `array, boolean list`
```
f=(a,r)=>r>[]?(r[0]?a.reverse():a).map(c=>f(c,r.slice(1))):a
```
```
f=(a,r)=>r>[]?(r[0]?a.reverse():a).map(c=>f(c,r.slice(1))):a
console.log(f([[[[3,1,4,1],[5,9,2,6]],[[5,3,5,8],[9,7,9,3]]],[[[2,3,8,4],[6,2,6,4]],[[3,3,8,3],[2,7,9,5]]]],[true,false,true,true]))
```
[Answer]
# [Pyth](https://pyth.readthedocs.io), 15 bytes
```
.v+jk.n*\_*L\ME
```
[Try it here!](https://pyth.herokuapp.com/?code=.v%2Bjk.n%2a%5C_%2aL%5CME&input=%22%5B%5B%5B1+2+3+4%29+%5B5+6+7+8%29+%5B9+10+11+12%29%29+%5B%5B13+14+15+16%29+%5B17+18+19+20%29+%5B21+22+23+24%29%29%29%22%0A%5B0%2C2%5D&debug=0)
Annoyingly, handling the empty dimension list case takes no less than 2 bytes... I'd rather use `ss` in place of `jk.n` but :| Assumes that the list to be transformed can be given in native Pyth syntax, as a string. I've written a [converter to Pyth syntax](https://pyth.herokuapp.com/?code=XXz%5C%5D%5C%29%5C%2Cd&input=%5B%5B%5B1%2C2%2C3%2C4%5D%2C%5B5%2C6%2C7%2C8%5D%2C%5B9%2C10%2C11%2C12%5D%5D%2C%5B%5B13%2C14%2C15%2C16%5D%2C%5B17%2C18%2C19%2C20%5D%2C%5B21%2C22%2C23%2C24%5D%5D%5D&debug=0) to make testing easier. In the unfortunate case that the OP chooses not to allow this, a 17-byter will "fix" it:
```
.v+jk.n*\_*L\ME\E
```
[Answer]
# [Japt](https://github.com/ETHproductions/japt), ~~15~~ 14 bytes
With some inspiration from [Arnauld's solution](https://codegolf.stackexchange.com/a/171632/58974).
Takes the indications as the first input, as a boolean array of `1`s and `0`s.
```
Ê?Vn@ÎÃ£ßUÅX:V
```
[Try it](https://ethproductions.github.io/japt/?v=1.4.6&code=yj9WbkDOw6PfVcVYOlY=&input=WzEsMCwxXQpbW1sxLDIsMyw0XSxbNSw2LDcsOF0sWzksMTAsMTEsMTJdXSxbWzEzLDE0LDE1LDE2XSxbMTcsMTgsMTksMjBdLFsyMSwyMiwyMywyNF1dXQotUQ==)
---
## Explanation
```
                   :Implicit input of boolean array U=indications and multi-dimensional integer array V
Ê                  :Get the length of U
 ?                 :If truthy (i.e., >0)
  Vn               :  Sort V
    @ÎÃ            :   Function that gets the first element of U; 0 will leave the array untouched, 1 will reverse it.
       £           :  Map each X
        ß          :  Run the programme again with the following inputs
         UÅ        :   U with the first element removed
           X       :   X will serve as the new value of V
            :      :Else
             V     :  Just return V
```
[Answer]
# [Clean](https://github.com/Ourous/curated-clean-linux), ~~122~~ 112 bytes
```
import StdEnv
class$r::[Bool]->r->r
instance$r where$_=id
instance$[r]| $r where$[a:y]=if(a)reverse id o map($y)
```
[Try it online!](https://tio.run/##RY1PS8QwFMTv/RQBe9iFt7Av7f4r1IOoIHgQ1lsI8mhTDaRJSdKVgp/dGBUU5jC/GYbpjCKbRtfPRrGRtE16nJyP7Bz7O3spOkMhlL5pxI1zRm6ufVahbYhkO1V69v6mvCpfWt3/p8LLD/bXCWoW2ephRWuvLsoHxXTPXH6bVuWyTudIPhZX2k5zZC0TQiBwqKCWIHawhwMcszsBbgERkMtMAivAGnAHuM@IB8Aj4An4NhPPew68Al5LKYuWleLZzwruyQQF31ayn7f02Q2GXkPaPDym28XSqLtfeDIUB@fHLw "Clean – Try It Online")
A version of Damien's Haskell answer using Clean's golfier type system. Really shows the extensive similarities between the two languages.
Explained:
```
import StdEnv                 // import basic stuff
class $ r :: [Bool] -> r -> r // $ takes a boolean list and returns a function on r to r
instance $ r                  // instance on all types, taken when no more specific instances exist
    where $ _ = id            // return the identity function for all arguments
instance $ [r] | $ r          // instance for lists of a type which has an instance itself
    where $ [a: y]
        = if(a) reverse id    // reverse if the head of the argument is true
            o map ($ y)       // composed with the map function acting on $ applied to the tail
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), 54 bytes
```
f=->a,d{r,*z=d;r&&a.reverse!;d==[]?a:a.map{|w|f[w,z]}}
```
[Try it online!](https://tio.run/##NU7LDoIwELzzFXjhYEbClrek@iFNDyXASRNSRCKPb69LlD3szmQyM2vH@uNcJy83g2axOM@yqWwQmNC279YO7alqpFT6bq4mfJp@Wae1UxNmvW1O8RCEhoqRaD4vO7bYFxPvr2LXoFJkyFEwKkERiEBityiKQQkoBWVMKQcVoBIiYibYLyBiCI4/8jvzGI4WT/@eMqhXv/c7xUBv7gs "Ruby – Try It Online")
[Answer]
(untested but I *think* correct. compiler asm output looks like what I expect. Will update if/when I find time to write a test harness that creates and prints this data structure.)
# GNU C++ (portable) 148 bytes
```
#include<algorithm>
#include<cstdint>
struct m{intptr_t d,l,a[];void R(int*r){if(*r)std::reverse(a,a+l);for(int i=0;d&&i<l;((m*)a[i++])->R(r+1));}};
```
# GNU C++ (int=pointer and falls off a non-void function UB) 120 bytes
```
#include<algorithm>
struct m{int d,l,a[],R(int*r){if(*r)std::reverse(a,a+l);for(int i=0;d&&i<l;((m*)a[i++])->R(r+1));}};
```
This is a struct of depth counter, length, array of {integers or pointers}. In the bottom level of this non-binary tree (`depth==0`), the array of `intptr_t` is an array of integers. In higher levels, it's a `struct m*` stored in `intptr_t`. Traversal takes a cast.
The `R()` reverse function is a member function because that saves declaring an arg, and saves a lot of `p->` syntax to reference the struct members vs. the implicit `this` pointer.
**The only GNU extension is the [C99 flexible array member](https://en.wikipedia.org/wiki/Flexible_array_member) to make a variable-sized struct**, which is supported in C++ as a GNU extension. I could have used a `*a` member pointing to a separately-allocated array and have this be plain ISO C++. (And that would actually save a byte without requiring any other changes). I wrote this as a mockup / reference implementation for an asm version.
---
The shorter version with just `int` also declares `R()` as returning `int` instead of `void`. These two bits of hackery are unrelated; this is just the "works on at least one implementation" version.
It should work fine on 32-bit targets (where `int` can hold a pointer), as long as you compile with gcc7 or older, or disable optimizations. (`gcc8 -O3` assumes that execution can't reach the bottom of a non-`void` function because that would be UB.) x86 `gcc -m32 -O3` should work fine with gcc7, [like on Godbolt](https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAKxAEZSAbAQwDtRkBSAJgCFufSAZ1QBXYskwgA5AHoZHAMx8linggIEADoJBy0WYKgYAzAHSCCTZAGtMAD2QJWwTKbQBbGQEcRmC3lQWQRlaAHZaADYuUJl3EQYCPABafHdMIICWJgYk4kwAN0xiQWyOAAYAQXKKuW4FPBZkBhEsAGpFAGELdAY8ACNTBEVsarqGppbMTuzDYkIEd2HqrLTBTStMVsMTTHQAfQBVHj2GgnbQvkrqi2IRZDPFi9PW9EZSJg4AVj5PgBFSABKEFOACpiABKDhPYwQMHg7ogEB5QrFTAQJjvfgMSEqSrGEjAlhnPCKX5lVTobgRKkkhQdBiqKDuEHgj7fEm8fhfX7gpLDIHEfi0cE4y5VUK/KGS3FVK6VJgiIitYyaAjEdoKX7tLgRdyIgGqVpyLaYM7AZDIVpKzDuQitVj2wTuF6YYwNQiZUYSo0yVorPzrCRbIzGXaHY6nUZy2VVLj1RrNLDTBizeaLBQjK5x8aJqZ05DdSMZ5ZMVaBzbbUPoc5i65qu4PKE8U6q4h7M6vBiY77c1T5VB4atA0EQpt4GFwhFIgpFQRojEfXjY1TVfHEQnE0nkpSUnU0zoMpRMlls5tczl/Xn8iCC3jC0VeyUSlfRhVKlVqjVaql6kAGpQ%2BiaZoWlaqCtDadoOkwToum6LAeoEj6Af6awbMGOyUtGKHlq0IhsCGuw1tUrStDcDatI8tZlAAnHsJxEq27YvG8p69gBJGAVgqoIF%2BrRlBRmCsIIrT5NkviCKQGrYPxaRCa0mgDkSs6mMRHHGgwvEMOkwAEEMcrUcaeGehcIkDtWmhfD80o8LhLZqkxlI9n8hpSi%2BsoGTIdF2W2HaWWxNmAcYWl2P0Wn2sQxBMAAngJ7h9EUIDhZFMVoESeDACIojCQA7vMVoIJsZH3FGFQcaZg6tMORKtIKTk8kRlRleU1HjrCo6NRxzXNVOyKzvOkmLjwy4ymVZWteg4KAXkyBiHOrTjvleDCUtLBgFIZy6ZsfSoBoqDOlxumqaNnU0WuG7zVuGo2bS9JXRdnK8JNgFqpgmxqkwKIlAyHUkV1NFlcerKWSSl58hmApCqKam%2Brlun5ZseQWK0qDGPDLrca0vQWEd5ySh1rkytUxouMBlrWraZxQTBWBwQhLBEzI/YVb1qIQEVDwgu4knPLVVmTU2HHuGD2AClDuPVG%2BYEfuqpLarq%2BpuVKyGlgGaF4ZWuwlWMqP8caLCBEkaRxUUSTGHh9yZCJs6epUtTZgmkwal0BA9P0gxLFm8YTG0yaprp6aZjG7MUUwZxNlGtH0Vo9kdpg3GGoBMmCUEIliX4knDEnckKacykR15DEx5j6SKzRhnwYhJlM%2BZfnOQBIjeQ5tfWeLhM0QX0c%2BS8oesXXAXGkF9ihZsTARdFsXxcQiWj8lrSpYkGVZa0sM8ZtpH1sVVzPm3FTVyHL35GzG8PKHrQgpo3PVSzc7N5CW9US1MLX1M3yaMLB1DJeONlT1M6s2/wx0A90kgAjMQDLD8FAdgLSLAHw/XmjCKBH8vyyzKJNPIBAxD0zbtRM6zxaRkjujdKBMCiHnh4PzC4EdmruFDsiJkocWRIJ7sDbkkln5wPcq5LeeNYwKHSPgYwUhwSMGkJ8KQpAWDSDKBI1A0gOjkNIqIcQmw6i0AkQQaRwiRHWBAJ8BQphQifFoGEUIERqKhDMdRExERRFSAACwSL1LQMoZRJFaNIHIqQEidBuM0VIGRIi4CwBgIgFAe1NB4C0mQCgEAPCROiSAYAoQFCkDdAkWclA%2BgeL6A0UeUVpDqNIB4NIRIADyLAGAFICRIrAtC2BaQ8fgaaiRCg6BqaQewmAZoEEkFIIpucGAeLVHgPU/ThGMGcCgchjB%2Bg6EgCI1AqpMjtKSN0UkwAWAiHISY1oSQynCVNvrJIeFiBGByAwVASzhJ7OMMcl6mAkiFHuCQPAAAvTYSQADq2QNLfM0LsVgiRLSGwUFwHxyiJB0BEUMqQ4j3EdK8XYAAHBEJIER7FbBAqEUwChWgQFwIQEg2oFD0FaB0CJUSigkuFOS8hGitEilIAVJgWAp4QB0SAexERTBcHsci5FXA4xlCFQoGidjHGkD1KEexph7EyvlfYxVyrkUIpkZ46QPiQB%2BMZaQYJYTRBaEVOQSg8SqVT3oLsIlFrSDZUipoQpEzYXwqkYi6Qajl55RRWijFWLLQ4oUAympTKWVssoDC6Qkq9RcE%2BKYT4Mb42fETcm6IarZGaqENq0g/jAmcu5by/lgrhWivFbCwNaaNXeOzYyiNUhwVSroK4itXig25tIJ9TIXKgA%3D%3D%3D) where I included both versions (in different namespaces) and a non-member-function version.
### Ungolfed
**The function arg, `int r[]`, is an array of 0 / non-zero integers that indicate whether a given depth should be swapped, starting with the outer-most level.**
```
#include<algorithm>  // for std::reverse
#include<cstdint>    // for intptr_t.  GNU C defines __intptr_t, so we could use that...
struct m{
    __intptr_t d,l,a[];    // depth = 0 means values, >0 means pointers.
    // l = length
    //__intptr_t a[];  // flexible array member: array contiguous with the struct
    void R(int r[]) {
        if(*r)
            std::reverse(a, a+l);   // *r && std::reverse() doesn't work because it returns void.
        if(d) // recurse if this isn't the bottom depth
            for(int i=0 ; i<l ; i++)  // tree traversal
                ((m*)a[i])->R(r+1);   // with the rest of the depth list
    }
}; // struct m
```
When we recurse, we pass `r+1`, so checking the current depth is always `*r`.
An earlier version just passed `r` unchanged, and checked `r[d]`. With a flexible array member, I needed to store some kind of last-level indicator because `a[]` is not a pointer, it's a true array with no indirection. But with a `intptr_t *a` member, I couldn't just have that be `nullptr` for the leaf level, because I want it to be values.
Reversing the current level before or after the tree traversal shouldn't matter. I didn't try to do it *during*.
I'm not *sure* that `std::reverse` is worth the byte count vs. a manual loop, especially if I can work in calling `R()` on each pointer exactly once somewhere inside that loop. But only if `d!=0`
[Answer]
# Mathematica, 7 bytes
```
Reverse
```
Function. Give it a nested list as the first argument, and the 1-based list of levels/dimensions to reverse as the second argument. [Try it online!](https://tio.run/##bVAxDsJADNt5RUaQbiC50hYh/oBYEUNBBTrAABXL6d5enFyrAuqQIbbjJL5X7a2@V21zrrruQlua7@t3/XzVi023ezaP9nA5hBDYkTjyjrLoKKwc5Y4KR6V2a0e8REHDEhUJDCVnKCg5V4ih5hIFtSwVEfWEqUArWbRBQD4ej5vZuLrfrCwMdXNS/stMMEkVg7X8EuNPyRcfTYxPOSpmpoafmityQ0hBvzY77lNa24p0sfbeNg2pFSbw6fUQ0jFln3GeRrUz2g@sRSHD9ArTcbwNt/Qx6uD31YmRCUyh7gM "Wolfram Language (Mathematica) – Try It Online")
Finally, another challenge where Mathematica has a builtin!
[Answer]
# [Uiua](https://uiua.org) [SBCS](https://tinyurl.com/Uiua-SBCS-Jan-14), 6 bytes
```
∧(⍉⍥⇌)
```
[Try it!](https://uiua.org/pad?src=0_8_0__ZiDihpAg4oinKOKNieKNpeKHjCkKCmYgMV8wXzEgWwogIFtbMSAyIDMgNF0KICAgWzUgNiA3IDhdCiAgIFs5IDEwIDExIDEyXV0KCiAgW1sxMyAxNCAxNSAxNl0KICAgWzE3IDE4IDE5IDIwXQogICBbMjEgMjIgMjMgMjRdXV0KCmYgWzEgMV0gW1s3XV0KZiBbMV0gWzEgMiAzIDQgNSA2IDddCg==)
Takes the array and a mask of which dimensions to reverse like `[1 0 1]`.
```
∧(⍉⍥⇌)
∧(   )  # fold over mask and array, using array as accumulator
   ⍥⇌   # reverse the array either 0 or 1 times
  ⍉     # transpose
```
]