Zigzagify một ma trận


43

Là một phần của thuật toán nén của nó, tiêu chuẩn JPEG sẽ hủy một ma trận thành một vectơ dọc theo các antidiagonals theo hướng xen kẽ:

nhập mô tả hình ảnh ở đây

Nhiệm vụ của bạn là lấy một ma trận (không nhất thiết phải là hình vuông) và trả lại nó ở dạng không được kiểm soát. Ví dụ:

[1 2 3 4
 5 6 7 8
 9 1 2 3]

nên nhường

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

Quy tắc

Bạn có thể giả sử rằng các phần tử ma trận là số nguyên dương nhỏ hơn 10.

Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN (hoặc thay thế gần nhất), đối số dòng lệnh hoặc đối số hàm và xuất kết quả qua tham số STDOUT (hoặc thay thế gần nhất), tham số trả về hàm hoặc tham số hàm (out).

Ma trận đầu vào có thể được đưa ra trong bất kỳ định dạng chuỗi hoặc danh sách lồng nhau thuận tiện, rõ ràng, hoặc dưới dạng danh sách phẳng cùng với cả hai kích thước ma trận. (Hoặc, tất nhiên, là một loại ma trận nếu ngôn ngữ của bạn có những thứ đó.)

Vectơ đầu ra có thể ở bất kỳ định dạng chuỗi hoặc danh sách phẳng hoặc thuận tiện, rõ ràng.

Luật tiêu chuẩn được áp dụng.

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

[[1]]                                               => [1]
[[1 2] [3 1]]                                       => [1 2 3 1]
[[1 2 3 1]]                                         => [1 2 3 1]
[[1 2 3] [5 6 4] [9 7 8] [1 2 3]]                   => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 3 4] [5 6 7 8] [9 1 2 3]]                     => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 6 3 1 2] [5 9 4 7 8 3]]                       => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 5 9 6 3 4 7 1 2 8 3]]                         => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1] [2] [5] [9] [6] [3] [4] [7] [1] [2] [8] [3]]   => [1 2 5 9 6 3 4 7 1 2 8 3]

Những thách thức liên quan


1
Đầu vào có thể là một ma trận thực tế trong J không? Hoặc nó sẽ cần phải được chuyển từ các danh sách lồng nhau thành một ma trận như là một phần của hàm?
Gareth

4
Nếu chúng ta lấy ma trận làm mảng 2D, chúng ta vẫn có thể lấy kích thước làm đầu vào chứ?
xnor

1
@Gareth có, bạn có thể lấy một loại ma trận làm đầu vào.
Martin Ender

1
@xnor Hmmm, cái đó khó hơn một chút. Tôi cảm thấy như lấy lượng thông tin dư thừa đó đi một chút vào tiền xử lý đầu vào.
Martin Ender

Danh sách phẳng có thể theo thứ tự chính cột nếu đó là thứ tự bản địa của ngôn ngữ?
Luis Mendo

Câu trả lời:


27

J, 31 30 14 12 11 byte

[:;<@|.`</.

Ych . Quá lớn.

Lấy một ma trận làm đầu vào.

Giải trình

J có một lợi thế ở đây. Có một lệnh gọi là oblique ( /.) lần lượt lấy các dòng xiên và áp dụng một động từ cho chúng. Trong trường hợp này, tôi đang sử dụng một gerund để áp dụng luân phiên hai động từ: <( hộp ) và <@|.( đảo ngược và hộp). Sau đó, nó chỉ là vấn đề bỏ hộp mọi thứ bằng cách sử dụng ;( raze ).


26
J là ngôn ngữ duy nhất khiến tôi cảm thấy mình cần bằng cấp cao về tiếng Anh để hiểu nó.
Alex A.

2
@AlexA. btw, từ "lệnh" nên là "trạng từ".
Adám

11

Pyth, 24 23 21 20 19 18 17 byte

ssm_W=!Td.T+LaYkQ

Phiên bản 17 byte thay thế: ssuL_G=!T.T+LaYkQ

                Q  input
           +L      prepend to each subarray...
             aYk   (Y += ''). Y is initialized to [], so this prepends [''] to
                     the first subarray, ['', ''] to the second, etc.
                   ['' 1  2  3  4
                    '' '' 5  6  7  8
                    '' '' '' 9  1  2  3]
         .T        transpose, giving us
                   ['' '' ''
                    1  '' ''
                    2  5  ''
                    3  6  9
                    4  7  1
                    8  2
                    3]
  m_W=!Td          black magic
 s                 join subarrays together
s                  join *everything* on empty string (which means ''s used for
                     padding disappear)

Cảm ơn @FryAmTheEggman cho một byte, @Jakube cho 2 byte và @isaacg cho một byte!

Giải thích về "ma thuật đen" được ám chỉ ở trên: m_W=!Tdvề cơ bản đảo ngược mọi phân đoạn khác. Nó thực hiện điều này bằng cách ánh xạ _W=!Tqua từng phân đoạn; Wlà ứng dụng có điều kiện, vì vậy nó _s (đảo ngược) tất cả các phân đoạn trong đó =!Tlà đúng. Tlà một biến được ưu tiên thành mười (trung thực) và =!Tcó nghĩa (T = !T). Vì vậy, nó thay đổi giá trị của một biến bắt đầu trung thực và trả về giá trị mới, điều đó có nghĩa là nó sẽ xen kẽ giữa trả lại sai, trung thực, giả, trung thực ... (tín dụng cho Jakube cho ý tưởng này)

Bộ thử nghiệm ở đây .


11

Thạch, 24 19 15 13 11 byte

pS€żị"¥pỤị⁵

Lấy số lượng hàng, số cột và danh sách phẳng dưới dạng đối số dòng lệnh riêng biệt.

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

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

pS€żị"¥pỤị⁵  Main link. Argument: m (rows), n (columns), A (list, flat)

p            Compute the Cartesian product [1, ..., m] × [1, ..., n]. This yields
             the indices of the matrix M, i.e., [[1, 1], [1, 2], ..., [m, n]].
 S€          Compute the sums of all index pairs.
       p     Yield the Cartesian product.
      ¥      Dyadic chain. Arguments: Sums, Cartesian product.
    ị"       For each index pair in the Cartesian product, retrieve the coordinate
             at the index of its sum, i.e., map [i, j] to i if i + j is odd and to
             j if i + j is even.
   ż         Zip the sums with the retrieved indices.
       Ụ     Sort [1, ..., mn] by the corresponding item in the resulting list.
        ị⁵   Retrieve the corresponding items from A.

Tsk. Tôi không chắc bây giờ tôi có thể làm cho tôi ngắn hơn không. : -S
Gareth

Điều đó không có nghĩa là tôi sẽ không thử mặc dù ...
Gareth

Tại sao Jelly chưa được thừa hưởng xiên? Tôi có thể đề xuất glyphs APL ? Hoặc có thể Scandinavia øǿ?
Adám

7

MATL , 28 27 byte

tZyZ}:w:!+-1y^7MGn/*-X:K#S)

Chuyển thể từ câu trả lời của tôi ở đây . Ý tưởng chung là tạo ra một mảng 2D có cùng kích thước với đầu vào, chứa đầy các giá trị tăng theo cùng thứ tự với đường dẫn zig-zag. Sau đó, phiên bản tuyến tính (làm phẳng) của mảng đó được sắp xếp và các chỉ số của sắp xếp đó được giữ lại. Đó là những chỉ số cần được áp dụng cho đầu vào để tạo đường dẫn zig-zag.

Đầu vào ở dạng

[1 2 3; 5 6 4; 9 7 8; 1 2 3]

Giải trình

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

t       % input 2D array. Duplicate
ZyZ}    % get size as length-2 vector. Split into two numbers: r, c
:       % range [1,2,...,c] as a row vector
w:!     % swap, range [1;2;...;r] as a column vector
+       % add with broadcast. Gives a 2D array
-1      % push -1
y^      % duplicate previous 2D array. Compute -1 raised to that
7M      % push [1;2;...;r] again
Gn/     % divide by input matrix size, that is, r*c
*       % multiply
-       % subtract
X:      % linearize 2D array into column array
K#S     % sort and push the indices of the sorting. Gives a column vector
)       % index input matrix with that column vector

4

Matlab, 134 byte

Tôi chỉ cố gắng hết sức để rút ngắn mã của mình trong Matlab, giống như điện báo.

function V=z(M)
[m,n]=size(M);
a=(1:m)'*ones(1,n);
b=ones(m,1)*(1:n);
A=a+b-1;
B=a-b;
C=(A.^2+(-1).^A.*B+1);
[~,I]=sort(C(:));
V=M(:);
V=V(I)';

Ghi chú:

  1. Mlà một m×nma trận.
  2. abcả hai ma trận có cùng kích thước M, mỗi hàng abao gồm các số bằng số hàng của nó, trong khi mỗi cột bbằng với số cột của nó. Do đó, a+ blà một ma trận có phần tử bằng tổng của hàng và số cột của nó, nghĩa là , matrix(p,q)=p+q.
  3. Như vậy , A(p,q)=p+q-1; và B(p,q)=p-q.
  4. Cđược toán học nêu như phương trình dưới đây. Ma trận tăng dần ngoằn ngoèo với phương trình, một ma trận tăng dần ngoằn ngoèo có thể được thực hiện như hình dưới đây.
C =
     1     2     6     7
     3     5     8    14
     4     9    13    18
    10    12    19    25
  1. Cchỉ ra thứ tự các phần tử của M trong kết quả zigzagified. Sau đó, [~,I]=sort(C(:));trả về thứ tự, nghĩa là I, do đó, V=V(I)'là kết quả.

Vâng, tôi vừa tìm thấy nó, bây giờ tôi cập nhật nó.
Guoyang Qin

@AlexA. Cảm ơn bạn, Alex. Vì tôi chưa quen với điều này và tôi muốn rút ngắn nó càng ngắn càng tốt nhưng hãy biến nó thành một đoạn trích. Bây giờ tôi đã sửa mã của mình.
Guoyang Qin

Có vẻ tốt. Bài đăng đầu tiên rất hay! :)
Alex A.

3

JavaScript (SpiderMonkey 30+), 99 byte

x=>[for(y of[...x,...x[0]].keys())for(z of Array(y+1).keys())if(a=x[y%2?z:y-z])if(b=a[y%2?y-z:z])b]

Đã thử nghiệm trong Firefox 44. Lấy đầu vào dưới dạng mảng 2D.


3

Python 2, 84 byte

lambda N,w,h:[N[i*w+s-i]for s in range(w+h+1)for i in range(h)[::s%2*2-1]if-1<s-i<w]

Porting câu trả lời Tên mẫu của . Có một mảng phẳng với chiều rộng và chiều cao cho trước. xsot đã lưu một byte.


88 byte:

lambda M,w,h:[M[i]for i in sorted(range(w*h),key=lambda i:(i/w+i%w,-i*(-1)**(i/w+i%w)))]

Có một mảng phẳng với chiều rộng và chiều cao cho trước. Sắp xếp các tọa độ 2D tương ứng (i/w,i%w)theo thứ tự ngoằn ngoèo của tổng tăng để có các đường chéo, liên kết bằng cách tăng hoặc giảm giá trị hàng, dựa trên việc cột cộng hàng là số lẻ hay chẵn.


Rằng nếu điều kiện có thể được rút ngắn hơn nữa.
xsot

@xsot Bắt đẹp.
xnor

3

Haskell, 79 78 73 byte

(m#h)w=[m!!(y*w+x-y)|x<-[0..h+w],y<-g!!x$[0..x],y<h,x-y<w]
g=reverse:id:g

Đầu vào là một danh sách phẳng với số lượng hàng và cột, ví dụ ( [1,2,6,3,1,2,5,9,4,7,8,3] # 2) 6-> [1,2,5,9,6,3,4,7,1,2,8,3].

Cách thức hoạt động: đi qua tọa độ x và y của ma trận ( hhàng, wcột) theo hai vòng lặp lồng nhau:

  | 0 1 2 3 4 5 6 7 8    outer loop               Index is y*w+x-y, i.e.
--+------------------    x from 0 to h+w          the elements are accessed
0 | 1 2 6 3 1 2                                   in the following order:
1 | 5 9 4 7 8 3
2 |                                               1 2 4 6  8 10 
3 |                                               3 5 7 9 11 12
4 |
5 |
6 |
7 | inner loop:
8 | y from 0 to x

tức là từ trên / phải xuống / trái, bỏ qua các chỉ số bị ràng buộc ( yxphải thỏa mãn y<hx-y<w). Khi xlà chẵn, thứ tự của vòng lặp bên trong được đảo ngược: yđi từ xđến 0. Tôi làm điều này bằng cách chọn một chức năng sửa đổi cho phạm vi y [0..x]là thành xphần thứ của [reverse,id,reverse,id,...].

Chỉnh sửa: @xnor sắp xếp lại các vòng lặp và lưu 5 byte. Cảm ơn!


Tôi nghĩ bạn có thể làm g=id:reverse:g.
xnor

Các parens trên đa số (y-x)*wcó thể được cắt bằng cách chuyển vấn đề : (m#h)w=[m!!(x*w+y-x)|y<-[0..h+w],x<-g!!y$[0..y],x<h,y-x<w] g=reverse:id:g. Dịch sang Python giúp tiết kiệm 3 ký tự so với những gì tôi có.
xnor

1

Python 2 + NumPy, 122 byte

Tôi thừa nhận nó. Tôi đã làm việc trước. Thật không may, phương pháp tương tự này không thể dễ dàng sửa đổi để giải quyết 2 thách thức liên quan khác ...

import numpy
def f(m):w=len(m);print sum([list(m[::-1,:].diagonal(i)[::(i+w+1)%2*-2+1])for i in range(-w,w+len(m[0]))],[])

Lấy một mảng numpy làm đầu vào. Xuất ra một danh sách.

Dùng thử trực tuyến

Giải trình:

def f(m):
    w=len(m)    # the height of the matrix, (at one point I thought it was the width)
    # get the anti-diagonals of the matrix. Reverse them if odd by mapping odd to -1
    d=[list(m[::-1,:].diagonal(i)[::(i+w+1)%2*-2+1])for i in range(-w,w+len(m[0]))]
            # w+len(m[0]) accounts for the width of the matrix. Works if it's too large.
    print sum(d,[]) # join the lists

Một lambda có cùng chiều dài:

import numpy
lambda m:sum([list(m[::-1,:].diagonal(i)[::(i+len(m)+1)%2*-2+1])for i in range(-len(m),len(m)+len(m[0]))],[])

1

Python 3, 131 118 115 107 byte

Dựa trên cùng một hoàng tử như câu trả lời của tôi về thử thách của Deusovi

Tôi giả sử chúng ta không thể có số 0 trong matrice đầu vào

e=enumerate
lambda s:[k for j,i in e(zip(*[([0]*n+i+[0]*len(s))for n,i in e(s)]))for k in i[::j%2*2-1]if k]

Giải trình

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

            pad with 0      transpose    remove 0    reverse line           concatenate 
                                                     with even index
1 2 3       1 2 3 0 0        1 0 0        1            1                
4 5 6   --> 0 4 5 6 0    --> 2 4 0    --> 2 4     -->  2 4              -->  1 2 4 7 5 3 6 8 9
7 8 9       0 0 7 8 9        3 5 7        3 5 7        7 5 3             
                             0 6 8        6 8          6 8               
                             0 0 9        9            9

Các kết quả

>>> [print([i,f(i)]) for i in [[[1]], [[1, 2], [3, 1]], [[1, 2, 3, 1]], [[1, 2, 3], [5, 6, 4], [9, 7, 8], [1, 2, 3]], [[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]], [[1, 2, 6, 3, 1, 2], [5, 9, 4, 7, 8, 3]], [[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]], [[1], [2], [5], [9], [6], [3], [4], [7], [1], [2], [8], [3]]]]
# [input,                                                          output]
[[[1]],                                                            [1]]
[[[1, 2], [3, 1]],                                                 [1, 2, 3, 1]]
[[[1, 2, 3, 1]],                                                   [1, 2, 3, 1]]
[[[1, 2, 3], [5, 6, 4], [9, 7, 8], [1, 2, 3]],                     [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]],                       [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 6, 3, 1, 2], [5, 9, 4, 7, 8, 3]],                         [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]],                           [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1], [2], [5], [9], [6], [3], [4], [7], [1], [2], [8], [3]],     [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]

Nên reverse even lineđược reverse odd linesthay thế?
nwp

Chỉ số @nwp bắt đầu lúc 0 ^^
Erwan

Ah, bạn đang nói về số dòng, không phải độ dài của dòng. Tôi xin lỗi, xin lỗi.
nwp

@nwp np, btw Tôi đã thay đổi nó để tránh nhầm lẫn
Erwan
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.