多次元反転


23

非負整数のN次元の直交(非不規則)配列と、どの次元を反転させるかの指示が与えられると、配列を返しますが、それらの次元に沿って反転します。指示は、長さNのブールリスト、または0または1からインデックス付けされた最初のN次元のサブセットのリストとして指定できます。

入力形式を明記してください。コードの説明は大歓迎です。

ウォークスルーの例

2層3行4列3Dアレイが与えられます

[[[ 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](0インデックス付きリスト)
[1,3](1インデックス付きリスト)

最初と最後の次元の順序を逆にする必要があります。つまり、各レイヤーの行ではなく、レイヤーと行の要素(列)です。最初に(これを行う実際の順序は重要ではありません)、レイヤーの順序を逆にします。

[[[13,14,15,16],
  [17,18,19,20],
  [21,22,23,24]],

 [[ 1, 2, 3, 4],
  [ 5, 6, 7, 8],
  [ 9,10,11,12]]]

次に、各行の要素の順序を逆にします。

[[[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,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]]]]


静的に型付けされたほとんどの言語で最も難しいのは、関連する型シグネチャをゴルフすることです。
18

@Οurousこれらの言語は通常、任意の配列データをどのように処理しますか?
アダム

1
私が見るように、「通常の」使用には3つのケースがあります:配列の1レベルのみを心配する(例:reverse任意の配列で動作しますが、最初のレベルのみを考慮する)、ジェネリック、または再帰クラス(関数に応じて型/オブジェクトクラスまたはOOP、ただし同様のユースケース)。後者の2つは通常、はるかに冗長です。
18

メモリー内ですべてが連続している適切な多次元配列ではなく、ポインターへのポインターの配列(Cまたはasm)として行列を格納できますか?リストの任意のネストを持つ通常の高レベル/動的に型付けされた言語はすべて、行列ではなくリストのリストとしてすでに物事を処理しているので、私はそれがうまくいくと思います。
ピーター

@PeterCordes確かに、どうぞ。
アダム

回答:




8

JavaScript(Node.js)58 55 53 45バイト

@Shaggyのおかげで8バイト節約

入力を受け取り(indications)(array)、どこの適応症は、ブールリストです。

f=([r,...b])=>a=>1/r?a.sort(_=>r).map(f(b)):a

オンラインでお試しください!

コメント済み

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

rinplaceを使用するだけで動作するr||-1 ようです。
シャギー

だろうf=([r,...b])=>a=>1/r?a.sort(_=>r).map(f(b)):a動作しますか?私の電話では適切にテストできません。
シャギー

@Shaggy Nice!私はこのかなり珍しい処理フローが好きです。
アーナルド


5

ゼリー、8バイト

”€ẋ”ṚpFv

ディメンションの0インデックス付きリストを取得します。

オンラインでお試しください!

使い方

”€ẋ”Ṛ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.

1
それは恐ろしいことです。非常に素晴らしい!
アダム

5

R80 78 77バイト

[指示された場所で逆のシーケンスのリストを作成して、Rの抽出プログラムへの呼び出しを作成します。それらには実際にはゼロが含まれていますが、これは静かに無視されます。これdrop=Fは、Rのデフォルトの次元のドロップを防ぐために必要です。revRが配列を埋める方法のため、ディメンションリバースインジケーターの呼び出しが必要です。

-2ありがとう@Giuseppe

-1インライン割り当てを使用。

function(x,a,d=dim(x))do.call("[",c(list(x),Map(seq,r<-d*rev(a),d-r),drop=F))

オンラインでお試しください!

同じ長さで同じ結果を得るバリエーションを思いついた@JayCeへの名誉ある言及:

function(x,a,d=dim(x))array(x[t(t(expand.grid(Map(seq,r<-d*rev(a),d-r))))],d)

オンラインでお試しください!


1
78バイトの非常に良い答えです!
ジュゼッペ

1
非常に深い答え。完全に理解するのに時間がかかりました。私は使用せずに複製しようとしましたdo.call-それは83バイトで長いですが、参照用のコメントとしてこれをまだここに投稿しています:TIO
JayCe

実は、@ JayCe、あなたのすばらしい答えは78バイト
J.Doe

5

Haskell、120 119バイト

関数fは、N次元のリストとブールのリストを入力として受け取ります

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)

1
かっこは必要ありませんF r
Ørjanヨハンセン

1
テストケースおよびOJの1バイトゴルフとのTIOリンク
Khuldraeseth na'Barya

4

05AB1E23 11 10 バイト

'€s×'R«J.V

オンラインでお試しください。

@ Mr.Xcoderのおかげで-12バイト。

[0,2,3]最初の入力である0インデックスの真理値(つまり)として入力します。

説明:

'€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

たとえば、インデックスinput-listがの[0,2,3]場合、次の文字列が作成されます。

R€€R€€€R

どちらが:

    €€€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

元の23バイトの回答:

ćURvy„ RèJ…εÿ}}„ RXèJ.V

boolean-list(つまり[1,0,1,1])としての入力。これは最初の入力です。

オンラインでお試しください。

説明:

ć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

例:boolean input-listがの場合[1,0,1,1]、次の文字列が作成されます。

εεεR}R} }R

どちらが:

  ε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

1
いい答えですが、... えーと ...この11バイトは機能しますか?
ミスターXcoder

@ Mr.Xcoderありがとう!それは確かにはるかに簡単です。そして、先頭に追加してから元に戻すのではなく、それぞれを追加することでさらに1バイトをゴルフすることができました。
ケビンクルイッセン

@ Mr.Xcoderはところで、なぜ'x*繰り返しに作業をx使用せずに倍のN量sWAPを、それが持つ仕事をしません'€*... EDIT:?のみ。..しかし、従来で
ケビンCruijssen

レガシーバージョンは非常にバグが多く、文字リテラルであるにもかかわらず演算子としてまだ解析されているという事実による可能性がありますか?正直であることは確かではありません。*それにもかかわらず、新しいバージョンでは、同じように動作しません。
Mr. Xcoder

3

JavaScript(Node.js)、60バイト

別の(再帰的)アプローチ。Arnauldの答えに勝るものはありません...まだ....

入力を次のように取ります 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]))


3

Pyth、15バイト

.v+jk.n*\_*L\ME

ここで試してみてください!

面倒なことに、空の次元リストのケースを処理するのに2バイト以上かかります...ではなくss、代わりに使用しますjk.n:| 変換されるリストは、ネイティブのPyth構文で文字列として指定できると想定しています。私が書いたPyth構文にコンバータを簡単にテストを作成します。残念ながら、OPがこれを許可しないことを選択した場合、17バイトで「修正」されます。

.v+jk.n*\_*L\ME\E

3

Japt15 14バイト

Arnauldのソリューションからインスピレーションを得て。

指示を最初の入力として、1sおよび0sのブール配列として受け取ります。

Ê?Vn@ÎãßUÅX:V

それを試してみてください


説明

                   :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

3

クリーン122 112バイト

import StdEnv
class$r::[Bool]->r->r
instance$r where$_=id
instance$[r]| $r where$[a:y]=if(a)reverse id o map($y)

オンラインでお試しください!

Cleanのゴルファー型システムを使用したDamienのHaskell回答のバージョン。2つの言語の広範な類似点を実際に示しています。

説明:

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


1

(テストされていませんが、正しいと思います。コンパイラのasm出力は期待どおりです。このデータ構造を作成および印刷するテストハーネスを作成する時間がある場合は更新されます。)

GNU C ++(ポータブル)148バイト

#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および非void関数UBから外れます)120バイト

#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));}};

これは、深さカウンター、長さ、{整数またはポインター}の配列の構造です。この非バイナリツリー(depth==0)の最下位レベルでintptr_tは、配列は整数の配列です。より高いレベルでは、にstruct m*保存されintptr_tます。トラバーサルがキャストします。

R()逆関数は、それが引数を宣言節約するため、メンバ関数である、と多くの節約p->暗黙の対構造体のメンバを参照するための構文をthisポインタ。

唯一のGNU拡張機能は、可変サイズのstructを作成するC99柔軟な配列メンバーです。これは、C ++でGNU拡張機能としてサポートされています。*a個別に割り当てられた配列を指すメンバーを使用して、これを単純なISO C ++にすることもできます。(そして、それは実際に他の変更を必要とせずにバイトを保存します)。これをasmバージョンのモックアップ/リファレンス実装として作成しました。


を使用した短いバージョンでは、の代わりにとして返すことintも宣言しR()ています。これらの2つのハッカーは無関係です。これは単なる「少なくとも1つの実装で動作する」バージョンです。intvoid

intgcc7以前でコンパイルするか、最適化を無効にする限り、32ビットターゲット(ポインターを保持できる場所)で正常に動作するはずです。(gcc8 -O3実行が非の底に到達することができないことを前提としvoidているが、UBになるので機能。)のx86はgcc -m32 -O3、gcc7と罰金を動作するはずGodbolt上のように、私はバージョン(異なる名前空間内)及び非メンバ関数バージョンの両方が含まれ。

非ゴルフ

関数argはint r[]、最も外側のレベルから開始して、指定された深さを交換するかどうかを示す0 /非ゼロ整数の配列です。

#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

再帰するとき、を渡すr+1ので、現在の深さのチェックは常に*rです。

以前のバージョンはrそのまま渡され、チェックされましたr[d]。柔軟な配列メンバーでa[]は、ポインターではなく、間接性のない真の配列であるため、何らかの最終レベルのインジケーターを格納する必要がありました。しかし、intptr_t *aメンバーの場合nullptr、リーフレベルの値だけを取得することはできません。値にしたいからです。

ツリートラバーサルの前または後に現在のレベルを反転することは重要ではありません。私はそれを行うにしようとしなかった時に

特に、そのループ内のどこかで各ポインターを1回だけ呼び出すことで作業できる場合は、バイトカウントと手動ループの価値があるかどうstd::reverseはわかりませんR()。ただし、d!=0


おっと、印象的。
アダム

@Adám:おかげで、それを書いた後、驚くほど自然に、そして十分にゴルフが落ちました。私は、私は、x86のマシンコードに何ができるかを見るために好奇心が強い:P
ピーター・コルド

1

Mathematica、7バイト

Reverse

関数。最初の引数としてネストされたリストを指定し、2番目の引数として反転するレベル/ディメンションの1ベースのリストを指定します。オンラインでお試しください!

最後に、Mathematicaが組み込まれている別の課題!


逆転する層?たぶんTIOリンク?
アダム

@Adámつまり、逆にする次元のリストで、一般にMathematica ではレベルと呼ばれます
LegionMammal978
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.