Đảo ngược đa chiều


23

Cho một mảng số nguyên không trực giao (không bị rách) của các số nguyên không âm và một dấu hiệu cho biết kích thước nào sẽ đảo ngược, trả về mảng nhưng đảo ngược dọc theo các kích thước đó. Chỉ báo có thể được đưa ra dưới dạng danh sách Boolean có độ dài N hoặc danh sách tập hợp con có kích thước N đầu tiên được lập chỉ mục từ 0 hoặc 1.

Vui lòng cho biết các định dạng đầu vào của bạn. Giải thích mã được nhiều đánh giá cao.

Ví dụ đi qua

Chúng tôi được cung cấp mảng 3D 4 cột 4 hàng

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

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

và một trong

[true,false,true](Danh sách Boolean)
[0,2]( danh sách 0 chỉ mục)
[1,3]( danh sách 1 chỉ mục)

Chúng ta cần đảo ngược thứ tự của các kích thước đầu tiên và cuối cùng, đó là các lớp và các thành phần của các hàng (các cột), nhưng không phải là các hàng của mỗi lớp. Đầu tiên (thứ tự thực tế bạn làm điều này không quan trọng) chúng tôi đảo ngược thứ tự của các lớp:

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

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

và sau đó chúng tôi đảo ngược thứ tự các phần tử của mỗi hàng:

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

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

Các trường hợp thử nghiệm

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


Tôi cảm thấy như phần khó nhất trong hầu hết các ngôn ngữ được gõ tĩnh sẽ là đánh gôn các chữ ký loại liên quan.
Οurous

@ Urous Làm thế nào để những ngôn ngữ đó thường xử lý dữ liệu mảng tùy ý?
Adám

1
Có ba trường hợp sử dụng "bình thường" như tôi thấy: chỉ lo lắng về một cấp độ của mảng (ví dụ: reversehoạt động trên các mảng tùy ý nhưng chỉ quan tâm đến cấp độ đầu tiên), chung chung hoặc các lớp đệ quy (loại lớp / đối tượng tùy thuộc vào chức năng hoặc OOP, nhưng trường hợp sử dụng tương tự). Hai cái sau thường dài dòng hơn nhiều.
urur

Chúng ta có thể lưu trữ ma trận dưới dạng các mảng của con trỏ tới các con trỏ (bằng C hoặc asm), thay vì các mảng đa chiều thích hợp trong đó mọi thứ đều liền kề trong bộ nhớ không? Tôi khá chắc chắn rằng tất cả các ngôn ngữ cấp cao / gõ động bình thường với các danh sách lồng nhau tùy ý đã coi mọi thứ là danh sách danh sách, không phải ma trận, vì vậy tôi sẽ cho rằng nó ổn.
Peter Cordes

@PeterCordes Chắc chắn, hãy tiếp tục.
Adám

Câu trả lời:


8

APL (Dyalog) , 20 9 byte

⊃{⌽[⍺]⍵}/

Hãy thử trực tuyến!

Làm sao?

/ - giảm - lấy phần tử ngoài cùng bên phải trong đầu vào (mảng) và áp dụng hàm với phần tử bên trái tiếp theo làm đối số bên trái

{⌽[⍺]⍵}- đảo ngược trong chiều left argument( )

- làm phẳng mảng kèm theo



8

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

Đã lưu 8 byte nhờ @Shaggy

Đưa đầu vào là (indications)(array), trong đó chỉ dẫn là danh sách Boolean.

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

Hãy thử trực tuyến!

Đã bình luận

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

Chỉ cần sử dụng rtại chỗ r||-1 dường như để làm việc .
Xù xì

Sẽ f=([r,...b])=>a=>1/r?a.sort(_=>r).map(f(b)):alàm việc? Trên điện thoại của tôi vì vậy không thể kiểm tra đúng.
Xù xì

@Shaggy Đẹp! Tôi thích dòng xử lý khá bất thường này.
Arnauld


5

Thạch , 8 byte

”€ẋ”ṚpFv

Có một danh sách các kích thước được lập chỉ mục 0.

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

”€ẋ”Ṛ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
Điều đó thật kinh khủng. Rất đẹp!
Adám

5

R , 80 78 77 byte

Tạo cuộc gọi đến trình trích xuất của R [ bằng cách tạo một danh sách các chuỗi được đảo ngược ở nơi được chỉ định. Chúng thực sự có chứa số không, được âm thầm bỏ qua. Cácdrop=F này là cần thiết để ngăn chặn việc giảm kích thước mặc định của R. Chúng ta cần revcuộc gọi đến chỉ báo đảo ngược kích thước, vì cách R lấp đầy các mảng.

-2 cảm ơn @Giuseppe

-1 sử dụng gán trong dòng.

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

Hãy thử trực tuyến!

Đề cập đáng trân trọng đến @JayCe, người đã đưa ra một biến thể có cùng kết quả trong cùng một độ dài:

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

Hãy thử trực tuyến!


1
78 byte câu trả lời rất hay!
Giuseppe

1
Câu trả lời rất sâu sắc. Phải mất một thời gian để tôi hiểu nó hoàn toàn. Tôi đã thử sao chép nó mà không sử dụng do.call- nó dài hơn ở mức 83 byte, vẫn đăng bài này ở đây dưới dạng bình luận để tham khảo: TIO
JayCe

Thật ra, @JayCe, câu trả lời tuyệt vời của bạn cũng có thể được đánh tới 78 byte!
J.Doe

5

Haskell, 120 119 byte

hàm f lấy danh sách N chiều và danh sách bool làm đầu vào

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
Bạn không cần dấu ngoặc đơn xung quanh F r.
Ørjan Johansen

1
Liên kết TIO với các trường hợp thử nghiệm và golf 1 byte của OJ.
Khuldraeseth na'Barya

4

05AB1E , 23 11 10 byte

'€s×'R«J.V

Hãy thử trực tuyến.

-12 byte nhờ @ Mr.Xcoder .

Đầu vào là giá trị trung thực được lập chỉ mục 0 (nghĩa là [0,2,3]), là đầu vào đầu tiên.

Giải trình:

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

Ví dụ: nếu danh sách đầu vào là [0,2,3], nó sẽ tạo ra chuỗi sau:

R€€R€€€R

Mà sẽ:

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

Câu trả lời gốc 23 byte:

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

Đầu vào dưới dạng boolean-list (tức là [1,0,1,1]), là đầu vào đầu tiên.

Hãy thử trực tuyến.

Giải trình:

ć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

Ví dụ: Nếu danh sách đầu vào boolean là [1,0,1,1], nó sẽ tạo chuỗi sau:

εεεR}R} }R

Mà sẽ:

  ε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
Câu trả lời hay, nhưng ... uhm ... cái 11 này có hoạt động không?
Ông Xcoder

@ Mr.Xcoder Cảm ơn! Điều đó thực sự dễ dàng hơn nhiều. Và đã có thể chơi thêm 1 byte bằng cách nối thêm từng byte, thay vì trả trước và sau đó đảo ngược.
Kevin Cruijssen

@ Mr.Xcoder Btw, tại sao làm 'x*việc để lặp lại xn số lần mà không sử dụng swap, nhưng nó không hoạt động với '€*? .. EDIT: Chỉ trong di sản mặc dù ..
Kevin Cruijssen

Phiên bản kế thừa khá lỗi, có thể là do thực tế vẫn được phân tích cú pháp như một toán tử mặc dù nó là một chữ char? Không chắc phải trung thực. Trong phiên bản mới, *dù sao cũng không hành xử giống như vậy.
Ông Xcoder

3

JavaScript (Node.js) , 60 byte

Một cách tiếp cận (đệ quy) khác nhau. không đánh bại câu trả lời của Arnauld ... chưa ....

Đưa đầu vào là 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

Bình thường , 15 byte

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

Hãy thử nó ở đây!

Khó chịu, việc xử lý trường hợp danh sách thứ nguyên trống mất không dưới 2 byte ... Tôi muốn sử dụng ssthay cho jk.nnhưng: | Giả sử rằng danh sách cần chuyển đổi có thể được đưa ra theo cú pháp Pyth gốc, dưới dạng một chuỗi. Tôi đã viết một trình chuyển đổi sang cú pháp Pyth để giúp kiểm tra dễ dàng hơn. Trong trường hợp không may là OP chọn không cho phép điều này, một bộ 17 sẽ "sửa" nó:

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

3

Japt , 15 14 byte

Với một số cảm hứng từ giải pháp của Arnauld .

Lấy các chỉ dẫn làm đầu vào đầu tiên, như là một mảng boolean của 1s và 0s.

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

Thử nó


Giải trình

                   :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

Sạch , 122 112 byte

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

Hãy thử trực tuyến!

Một phiên bản của câu trả lời Haskell của Damien sử dụng hệ thống loại golf của Clean. Thực sự cho thấy sự tương đồng sâu rộng giữa hai ngôn ngữ.

Giải thích:

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

(chưa được kiểm tra nhưng tôi nghĩ chính xác. Đầu ra asm của trình biên dịch trông giống như những gì tôi mong đợi. Sẽ cập nhật nếu / khi tôi tìm thấy thời gian để viết một khai thác thử nghiệm tạo và in cấu trúc dữ liệu này.)

GNU C ++ (di động) 148 byte

#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 = con trỏ và rơi ra một hàm không trống UB) 120 byte

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

Đây là cấu trúc của bộ đếm độ sâu, chiều dài, mảng của {số nguyên hoặc con trỏ}. Ở cấp độ dưới cùng của cây không nhị phân ( depth==0) này, mảng của intptr_tlà một mảng các số nguyên. Ở cấp độ cao hơn, nó struct m*được lưu trữ trongintptr_t . Traversal mất một diễn viên.

Hàm R()đảo ngược là một hàm thành viên vì nó lưu khai báo một đối số và lưu rất nhiều p->cú pháp để tham chiếu các thành viên cấu trúc so với thiscon trỏ ẩn .

Phần mở rộng GNU duy nhất là thành viên mảng linh hoạt C99 để tạo cấu trúc có kích thước thay đổi , được hỗ trợ trong C ++ dưới dạng phần mở rộng GNU. Tôi có thể đã sử dụng một *athành viên trỏ đến một mảng được phân bổ riêng và đây có phải là ISO C ++ đơn giản. (Và điều đó thực sự sẽ tiết kiệm một byte mà không yêu cầu bất kỳ thay đổi nào khác). Tôi đã viết điều này như là một triển khai mockup / tài liệu tham khảo cho một phiên bản asm.


Phiên bản ngắn hơn intcũng chỉ tuyên bố R()là trở lại intthay vìvoid . Hai bit của tin tặc không liên quan; đây chỉ là phiên bản "hoạt động trên ít nhất một lần thực hiện".

Nó sẽ hoạt động tốt trên các mục tiêu 32 bit (nơi intcó thể giữ một con trỏ), miễn là bạn biên dịch với gcc7 trở lên hoặc vô hiệu hóa tối ưu hóa. ( gcc8 -O3giả sử rằng việc thực thi không thể chạm đến đáy của voidhàm không phải vì đó là UB.) x86 gcc -m32 -O3sẽ hoạt động tốt với gcc7, như trên Godbolt nơi tôi bao gồm cả hai phiên bản (trong các không gian tên khác nhau) và phiên bản không có chức năng thành viên .

Bị đánh cắp

Hàm arg, int r[]là một mảng gồm các số nguyên 0 / khác không cho biết liệu độ sâu đã cho có nên được hoán đổi hay không, bắt đầu từ mức ngoài cùng.

#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

Khi chúng tôi tái diễn, chúng tôi vượt qua r+1, vì vậy kiểm tra độ sâu hiện tại luôn luôn *r.

Một phiên bản trước đó chỉ được thông qua rkhông thay đổi, và kiểm tra r[d]. Với một thành viên mảng linh hoạt, tôi cần lưu trữ một số loại chỉ báo cấp độ cuối cùng vì a[]không phải là một con trỏ, đó là một mảng thực sự không có sự gián tiếp. Nhưng với một intptr_t *athành viên, tôi không thể chỉ nullptrdành cho cấp độ lá, vì tôi muốn nó là giá trị.

Đảo ngược mức hiện tại trước hoặc sau khi cây đi ngang không quan trọng. Tôi đã không cố gắng để làm điều đó trong .

Tôi không chắc rằng nó std::reversecó giá trị đếm byte so với vòng lặp thủ công, đặc biệt là nếu tôi có thể thực hiện việc gọi R()trên mỗi con trỏ chính xác một lần ở đâu đó bên trong vòng lặp đó. Nhưng chỉ khid!=0


Whoa, ấn tượng.
Adám

@ Adám: cảm ơn, nó đã chơi golf một cách đáng ngạc nhiên một cách tự nhiên và tốt sau khi tôi viết nó. Tôi tò mò muốn xem những gì tôi có thể làm trong mã máy x86: P
Peter Cordes

1

Toán học, 7 byte

Reverse

Chức năng. Cung cấp cho nó một danh sách lồng nhau làm đối số đầu tiên và danh sách các mức / kích thước dựa trên 1 để đảo ngược làm đối số thứ hai. Hãy thử trực tuyến!

Cuối cùng, một thử thách khác trong đó Mathicala có nội dung!


Lớp nào để đảo ngược ? Liên kết TIO có thể?
Adám

@ Adám Đó là, danh sách các kích thước để đảo ngược, thường được gọi là các cấp độ trong Mathicala.
LegionMammal978
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.