Çok boyutlu ters


23

Negatif olmayan tam sayıların N boyutlu ortogonal (düzensiz) bir dizisi ve hangi boyutların tersine döneceğine dair bir gösterge verildiğinde, diziyi döndürür, ancak bu boyutlar boyunca tersine çevirir. Endikasyon, N uzunluklu bir Boolean listesi veya 0 veya 1'den indekslenen ilk N boyutlarının bir alt kümesinin listesi olarak verilebilir.

Lütfen giriş biçimlerinizi belirtin. Kod açıklamaları çok takdir edilmektedir.

Walk-through örneği

2 katlı 3 sıra 4 sütun 3 boyutlu dizi verildi

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

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

ve biri

[true,false,true](Boole listesi)
[0,2](0 dizinli liste)
[1,3](1 dizinli liste)

İlk ve son boyutların sırasını değiştirmemiz gerekir, yani katmanların ve satırların öğelerinin (sütunların) olduğu, ancak her katmanın satırlarının değil. İlk önce (bunu yaptığınız asıl sipariş önemli değil) katmanların sırasını tersine çeviririz:

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

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

ve sonra her satırın elemanlarının sırasını tersine çeviririz:

[[[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 durumları

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


Statik olarak en çok yazılan dillerin en zor kısmının söz konusu tip imzaları golf oynayacağını hissediyorum.
Büyük

@ Οurous Bu diller normalde rasgele dizi verileriyle nasıl ilgileniyor?
Adám

1
gördüğüm gibi "normal" kullanım için üç durum var: dizinin yalnızca bir seviyesinden endişe duymak (örneğin: reversekeyfi dizilerde çalışır, ancak yalnızca birinci seviyeye önem verir), jenerikler veya özyinelemeli sınıflar (işlevselliğe bağlı olarak tip / nesne sınıfları) veya OOP, ancak benzer kullanım durumu). İkinci ikisi genellikle çok daha ayrıntılıdır.
Büyük

Matrisi, her şeyin bellekte bitişik olduğu uygun çok boyutlu diziler yerine, işaretçilere (C ya da asm) işaretçiler dizisi olarak saklayabilir miyiz ? Rasgele sıralanan tüm normal üst düzey / dinamik olarak yazılmış dillerin, sıralı bir şekilde yerleştirilmiş olan dillere, zaten matrislerde değil, listelerde listeler gibi davrandıklarından eminim.
Peter Cordes,

@PeterCordes Tabii, devam et.
Ad'm

Yanıtlar:


8

APL (Dyalog) , 20 9 bayt

⊃{⌽[⍺]⍵}/

Çevrimiçi deneyin!

Nasıl?

/ - azaltmak - girdideki en sağdaki öğeyi (dizi) alın ve işlevi bir sonraki sol öğeyle sol argüman olarak uygulayın

{⌽[⍺]⍵}- left argument( ) boyutunda ters

- ekteki diziyi düzleştir



8

JavaScript (Node.js) , 58 55 53 45 bayt

@Shaggy sayesinde 8 bayt kaydedildi

Endikasyonların bir Boole listesi (indications)(array)olduğu girişi girdi olarak alır .

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

Çevrimiçi deneyin!

Yorumlananlar

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

Sadece kullanarak rbir INPLACE r||-1 çalışmaları gibi görünüyor .
Shaggy

Çalışır f=([r,...b])=>a=>1/r?a.sort(_=>r).map(f(b)):amı? Telefonumda bu yüzden düzgün test edemiyorum.
Shaggy,

@Shaggy Güzel! Bu alışılmadık işlem akışını seviyorum.
Arnauld,


5

Jöle , 8 bayt

”€ẋ”ṚpFv

0 indeksli bir boyut listesi alır.

Çevrimiçi deneyin!

Nasıl çalışır

”€ẋ”Ṛ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
Bu korkunç. Çok hoş!
Adám

5

R , 80 78 77 bayt

[Belirtildiği yerde tersine çevrilmiş bir dizi listesi oluşturarak R'nin çıkarıcısına yapılan çağrıyı oluşturun. Aslında sessizce göz ardı edilen sıfırları içerir. drop=FBoyutlarının R'ın varsayılan düşmesini engellemek için gereklidir. revR'nin dizileri doldurma şeklinden ötürü, boyut ters göstergesine çağrı yapmamız gerekir .

-2 teşekkürler @Giuseppe

Hat içi atama kullanarak -1.

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

Çevrimiçi deneyin!

Aynı uzunlukta aynı sonucu alan bir çeşitlemeyle gelen @JayCe'ye saygın bir söz:

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

Çevrimiçi deneyin!


1
78 bayt çok güzel cevap!
Giuseppe

1
Çok derin cevap. Tamamen anlamam biraz zaman aldı. Kullanmadan kopyalamayı denedim do.call- 83
baytta

Aslında, @JayCe, harika cevabınız da 78 byte'a
J.Doe


4

05AB1E , 23 11 10 bayt

'€s×'R«J.V

Çevrimiçi deneyin.

@ Mr.Xcoder sayesinde -12 bayt .

İlk giriş olan 0 indekslenmiş truthy değerleri (yani [0,2,3]) olarak giriş yapın.

Açıklama:

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

Örneğin: eğer indeksler giriş listesi ise [0,2,3], aşağıdaki dizgeyi yaratacaktır:

R€€R€€€R

Hangisi:

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

Orijinal 23 baytlık cevap:

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

[1,0,1,1]İlk giriş olan Boole listesi (yani ) olarak giriş yapın.

Çevrimiçi deneyin.

Açıklama:

ć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

Örneğin: Boolean giriş listesi ise [1,0,1,1], aşağıdaki dizgeyi yaratacaktır:

εεεR}R} }R

Hangisi:

  ε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
Güzel cevap, ama ... uhm ... bu 11 baytlık işe yarar mı?
Bay Xcoder

@ Mr.Xcoder Teşekkürler! Bu gerçekten çok daha kolay. Hazırlama ve geri alma yerine her birini ekleyerek 1 bayt daha golf oynayabildik.
Kevin Cruijssen

@ Bay Xcoder Btw, niçin bir wap kullanmadan n kere 'x*tekrar etmeyi deniyor, ama xs'€*
neyle

Eski sürüm oldukça sıkıcı, bir char literal olsa bile, hala bir operatör olarak ayrıştırılmış olması nedeniyle olabilir ? Dürüst olacağından emin değilim. Yeni sürümde, *yine de aynı şekilde davranmaz.
Bay Xcoder

3

JavaScript (Node.js) , 60 bayt

Farklı (özyinelemeli) bir yaklaşım. Arnauld'un cevabını geçmedi ... henüz ...

Girişi olarak alır 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 bayt

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

Burada dene!

Can sıkıcı olarak, boş boyut listesi durumunun ele alınması 2 bayttan daha az sürmüyor ... ssYerine kullanmayı tercih ederim jk.nama | Dönüştürülecek listenin, yerel Pyth sözdiziminde bir dize olarak verilebileceğini varsayar. Testi kolaylaştırmak için Pyth sözdizimine bir dönüştürücü yazdım . OP'nin buna izin vermemeyi seçtiği talihsiz bir durumda, 17 bayt bunu "düzeltir":

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

3

Japt , 15 14 bayt

Arnauld'un çözümünden ilham alınarak .

Göstergeleri ilk giriş, bir 1s ve 0s boolean dizisi olarak alır .

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

Dene


açıklama

                   :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

Temiz , 122 112 bayt

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

Çevrimiçi deneyin!

Damien'ın Haskell'in bir cevabı, Clean'ın golfçü tip sistemini kullanarak cevap veriyor. Gerçekten iki dil arasındaki kapsamlı benzerlikleri gösterir.

Açıklaması:

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

(denenmemiş ama bence doğru. derleyici asm çıktısı beklediğim gibi görünüyor.

GNU C ++ (taşınabilir) 148 bayt

#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 = işaretçi ve boş olmayan bir işlev UB'ye düşüyor) 120 bayt

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

Bu bir derinlik sayacı, uzunluk, {tamsayı veya işaretçiler} dizisidir. Bu ikili olmayan ağacın ( depth==0) alt seviyesinde , dizisi intptr_tbir tam sayı dizisidir. Daha yüksek seviyelerde struct m*saklanır intptr_t. Geçiş bir alçı alır.

R()Ters fonksiyon bu bir arg ilan tasarrufu sağlar, çünkü bir üye fonksiyonudur ve bir çok kaydeder p->örtülü genel yapı üyelerine referans sözdizimi thisişaretçi.

Tek GNU uzantısı, C ++ 'da GNU uzantısı olarak desteklenen değişken boyutlu bir yapı oluşturmak için C99 esnek dizi üyesidir . *aAyrı olarak ayrılmış bir diziye işaret eden bir üye kullanabilirdim ve bunun düz ISO C ++ olması gerekirdi. (Ve bu aslında başka bir değişiklik gerektirmeden bir bayt kazandıracak). Bunu bir asm versiyonu için bir mockup / referans uygulaması olarak yazdım.


Kısa versiyon sadece bunun yerine dönüş olarak intilan ediyor . Bu iki bilgisayar korsanlığı ilişkisi yoktur; bu sadece "en az bir uygulama üzerinde çalışıyor" versiyonu.R()intvoid

intGcc7 veya daha eski sürümlerle derlediğiniz veya optimizasyonları devre dışı bıraktığınız sürece , 32 bitlik hedeflerde ( bir işaretçiyi tutabilir) iyi çalışması gerekir . ( gcc8 -O3yürütmenin bir voidişlevsizin altına ulaşamayacağını varsayar, çünkü bu UB olacaktır.) x86 gcc -m32 -O3, hem sürümleri (farklı ad alanlarında) dahil ettiğim Godbolt'ta hem de üye olmayan bir sürümde olduğu gibi, gcc7 ile iyi çalışmalıdır .

Ungolfed

Arg işlevi, int r[]belirli bir derinliğin en dıştaki seviyeden başlayarak değiştirilip değiştirilmeyeceğini gösteren 0 / sıfır olmayan bir tamsayı dizisidir.

#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

Tekrarlandığımızda geçiyoruz, r+1bu yüzden mevcut derinliği kontrol etmek her zaman *r.

Daha eski bir sürüm henüz rdeğişmeden geçti ve kontrol edildi r[d]. Esnek bir dizi üyesiyle, bir tür son seviye göstergesini saklamam gerekiyordu, çünkü a[]bir işaretçi değil, dolaysız olarak gerçek bir dizi. Ancak bir intptr_t *aüye ile, sadece nullptryaprak seviyesi için olamazdı , çünkü değer olmasını istiyorum.

Ağaç geçişinden önce veya sonra mevcut seviyenin tersine çevrilmesi önemli olmamalıdır. Sırasında yapmayı denemedim .

Ben değilim emin olduğunu std::reverseben çağırmadan çalışabilir, özellikle değerinde manuel döngü vs bayt sayısıdır R()yalnızca bir kez bir yere bu döngü içinde her tanıtıcısı üzerinde. Ama sadeced!=0


Whoa, etkileyici.
Ad'm

@ Adám: teşekkürler, yazdıktan sonra şaşırtıcı bir şekilde doğal ve golf oynadı. X86 makine kodunda neler yapabileceğimi merak ediyorum: P
Peter Cordes

1

Mathematica, 7 bayt

Reverse

İşlev. İlk argüman olarak iç içe geçmiş bir liste ve ikinci argüman olarak tersine çevirilecek 1-temelli seviye / boyut listesi verin. Çevrimiçi deneyin!

Sonunda, Mathematica'nın yerleşik olduğu başka bir zorluk!


Katmanlar ters ? TIO bağlantısı belki?
Ad

@ Adám Yani, tersine çevrilecek boyutların listesi , genellikle Mathematica'da düzeyler olarak adlandırılır .
LegionMammal978 5:18
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.