Nén một ma trận thưa thớt


18

Nén một ma trận thưa thớt bằng cách sử dụng hàng thưa nén (định dạng CSR, CRS hoặc Yale) .

Đây là tất cả các hình thức nén (bỏ qua Yale mới).

Đầu vào có thể là bất kỳ cấu trúc dữ liệu 2d nào (danh sách các danh sách, v.v.): vd

[[0 0 0 0],
 [5 8 0 0],
 [0 0 3 0],
 [0 6 0 0]]

Và đầu ra phải là ba cấu trúc dữ liệu 1d (danh sách, v.v.), biểu thị các đầu ra A, IAJA, ví dụ

[5, 8, 3, 6]
[0, 0, 2, 3, 4]
[0, 1, 2, 1,]

Quá trình này được mô tả bởi wikipedia:

  • Mảng A có độ dài NNZ và giữ tất cả các mục nhập khác của M theo thứ tự từ trái sang phải từ trên xuống dưới ("hàng chính").

  • Mảng IA có độ dài m + 1. Nó được định nghĩa bởi định nghĩa đệ quy này:

    • IA [0] = 0 IA [i] = IA [i - 1] + (số phần tử khác không trên hàng thứ (i - 1) trong ma trận gốc)

    • Do đó, các phần tử m đầu tiên của IA lưu chỉ mục vào A của phần tử khác 0 đầu tiên trong mỗi hàng của M và phần tử cuối cùng IA [m] lưu trữ NNZ, số phần tử trong A, cũng có thể được coi là chỉ số trong A của phần tử đầu tiên của một hàng ma ngay bên ngoài phần cuối của ma trận M. Các giá trị của hàng thứ i của ma trận gốc được đọc từ các phần tử A [IA [i]] đến A [IA [i + 1] - 1] (bao gồm cả hai đầu), tức là từ đầu một hàng đến chỉ mục cuối cùng ngay trước khi bắt đầu tiếp theo. [5]

    • Mảng thứ ba, JA, chứa chỉ số cột trong M của mỗi phần tử của A và do đó cũng có độ dài NNZ.

Nếu ngôn ngữ của bạn không hỗ trợ cấu trúc dữ liệu thực tế, đầu vào và đầu ra có thể là văn bản.

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

Đầu vào 1:

[[0 0 0 0],
 [5 8 0 0],
 [0 0 3 0],
 [0 6 0 0]]

Đầu ra 1:

[ 5, 8, 3, 6 ]
[ 0, 0, 2, 3, 4 ]
[ 0, 1, 2, 1, ]

Đầu vào 2

[[10 20 0 0 0 0],
 [0 30 0 40 0 0],
 [0 0 50 60 70 0],
 [0 0 0 0 0 80]]

Đầu ra 2:

[ 10 20 30 40 50 60 70 80 ]
[  0  2  4  7  8 ]
[  0  1  1  3  2  3  4  5 ]

Đầu vào 3:

[[0 0 0],
 [0 0 0],
 [0 0 0]]

Đầu ra 3:

[ ]
[ 0 0 0 0 ]
[ ]

Đầu vào 4:

[[1 1 1],
 [1 1 1],
 [1 1 1]]

Đầu ra 4:

[ 1 1 1 1 1 1 1 1 1 ]
[ 0 3 6 9 ]
[ 0 1 2 0 1 2 0 1 2 ]

Đầu vào 5:

[[0 0 0 0],
 [5 -9 0 0],
 [0 0 0.3 0],
 [0 -400 0 0]]

Đầu ra 5:

[ 5, -9, 0.3, -400 ]
[ 0, 0, 2, 3, 4 ]
[ 0, 1, 2, 1, ]

Giả sử đầu vào có thể chứa bất kỳ số thực nào, bạn không cần xem xét các ký hiệu toán học hoặc biểu diễn theo cấp số nhân (ví dụ: 5.000 sẽ không bao giờ được nhập dưới dạng 5e3). Bạn sẽ không cần phải xử lý inf, -inf, NaNhoặc bất kỳ khác 'giả số'. Bạn có thể xuất một đại diện khác của số (5.000 có thể là đầu ra là 5e3 nếu bạn chọn).

Ghi điểm:

Đây là một , ít byte nhất sẽ thắng.

Bảng xếp hạng

Dưới đây là một Stack Snippet để tạo cả bảng xếp hạng thông thường và tổng quan về người chiến thắng theo ngôn ngữ.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Nếu bạn muốn bao gồm nhiều số trong tiêu đề của mình (ví dụ: vì điểm của bạn là tổng của hai tệp hoặc bạn muốn liệt kê riêng các hình phạt cờ của thông dịch viên), hãy đảm bảo rằng điểm thực tế là số cuối cùng trong tiêu đề:

# Perl, 43 + 2 (-p flag) = 45 bytes

Bạn cũng có thể đặt tên ngôn ngữ thành một liên kết mà sau đó sẽ hiển thị trong đoạn trích bảng xếp hạng:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes


Các chỉ số dựa trên 1 có thể được sử dụng cho hàng cuối cùng không?
Leo

@Leo cho JA? Số
Pureferret

1
Không IA[0] = 0hoàn toàn không cần thiết? Chỉ cần xác định IA[i] = IA[i − 1]..., nhưng chúng ta chỉ có thể nói rằng nếu i-1 < 0sử dụng 0. Nghĩa là, IA [0] luôn bằng 0, do đó nó có thể được nén ra (vâng, tôi nhận ra rằng đây là một bài phê bình về thuật toán, không phải thử thách này).
Draco18

Chúng ta cũng sẽ có những thách thức nghịch đảo chứ?
Adám

1
Khéo léo! Trước đây tôi không chạy theo định dạng nào, nhưng tôi rất vui khi thấy người khác đã thấy điều đó trước đây (tôi không nên là người phát hiện ra sự tối ưu hóa tầm thường trong các thuật toán cũ này).
Draco18

Câu trả lời:


6

MATL , 19 byte

!3#f!Dx0Gg!XsYshDq!

Đầu vào sử dụng ;như dấu phân cách hàng.

Hãy thử trực tuyến! Hoặc xác minh tất cả các trường hợp kiểm tra: 1 , 2 , 3 , 4 , 5 .

Giải trình

!     % Implicit input. Transpose
3#f   % 3-output version of find: it takes all nonzero values and pushes
      % their column indices, row indices, and values, as column vectors
!     % Transpose into a row vector
D     % Display (and pop) vector of values
x     % Delete vector of row values
0     % Push 0
G     % Push input
g     % Convert to logical: nonzeros become 1
!     % Transpose
Xs    % Sum of columns. Gives a row vector
Ys    % Cumulative sum
h     % Prepend the 0 that's below on the stack
D     % Display (and pop) that vector
q     % Subtract 1 from the vector of row indices
!     % Transpose into a row vector. Implicitly display


3

Haskell, 87 byte

f s|a<-filter(/=0)<$>s=(id=<<a,scanl(+)0$length<$>a,s>>= \t->[i|(i,e)<-zip[0..]t,e/=0])

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

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

a<-filter(/=0)<$>s           -- let a be the list of lists with all 0 removed]
                             -- e.g. [[1,0,0],[0,3,4]] -> [[1],[3,4]]

                             -- return a triple of

id=<<a                       -- a concatenated into a single list -> A 

scanl(+)0$length<$>a         -- partial sums of the length of the sublists of a
                             -- strating with an additional 0 -> IA

s>>=                         -- map the lambda over the sublists of s and concatenate
                             -- into a single list
   \t->[i|(i,e)<-zip[0..]t,e/=0]  -- the indices of the non-zero elements -> JA


2

APL (Dyalog) , 31 28 ký tự hoặc 36 33 byte *

Yêu cầu ⎕IO←0lập chỉ mục dựa trên không. I / O là danh sách các danh sách.

{(∊d)(0,+\≢¨d←⍵~¨0)(∊⍸¨⍵≠0)}

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

{... } chức năng ẩn danh mà lập luận được đại diện bởi

(... )(... )(... ) trả về một danh sách ba điều:

  ⍵≠0 Boolean nơi khác lập luận từ 0
  ⍸¨ɩ ndices những cho mỗi danh sách phụ
  ε nlist (flatten) để kết hợp vào danh sách duy nhất

  ⍵~¨0 loại bỏ số không từ mỗi tiểu danh sách các đối số
  d← cửa hàng như d
  ≢¨  tally mỗi
  +\ tổng tích lũy
  0, thêm vào trước một số không

  ∊dε nlist (flatten) d để kết hợp vào danh sách duy nhất

  


* Để chạy trong Dyalog Classic, chỉ cần thay thế bằng ⎕U2378.


Đẹp, tôi không hiểu định dạng đầu vào mặc dù? f 4 4⍴và sau đó là các giá trị?
Pureferret

@Pureferret Mã xác định hàm f. Input thực sự là một REPL, trong đó kêu gọi ftrên kết quả 4 4⍴…r eshapes dữ liệu vào một ma trận 4 × 4.
Adám

1
Rho cho r eshapes. Tôi hiểu rồi!
Pureferret

1
@Pureferret Tôi đã cập nhật bản Dùng thử trực tuyến! liên kết để hiển thị tốt hơn các trường hợp thử nghiệm.
Adám

2

PHP , 107 byte

<?for($y=[$c=0];$r=$_GET[+$l++];)foreach($r as$k=>$v)!$v?:[$x[]=$v,$z[]=$k,$y[$l]=++$c];var_dump($x,$y,$z);

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

PHP , 109 byte

<?$y=[$c=0];foreach($_GET as$r){foreach($r as$k=>$v)if($v){$x[]=$v;$z[]=$k;$c++;}$y[]=$c;}var_dump($x,$y,$z);

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


Điều này có cần các số là chuỗi không?
Pureferret

1
@Pureferret Bất kỳ đầu vào nào trong PHP là một chuỗi hoặc một chuỗi các chuỗi. Tôi chưa bỏ đầu vào vì vậy nếu bạn muốn đầu ra hoàn toàn thay thế $x[]=$v bằng$x[]=+$v
Jörg Hülsermann

2

JavaScript (ES6), 117 byte

a=>[a.map((b,i)=>(b=b.filter((x,c)=>x&&o.push(c)),m[i+1]=m[i]+b.length,b),m=[0],o=[]).reduce((x,y)=>x.concat(y)),m,o]

Đầu vào là một mảng 2D của các số và đầu ra là một mảng của [A, IA, JA].

Giải thích

a=>[
    a.map((b,i) => (                                // map each matrix row
            b = b.filter((x,c) => x                 // filter to only non-zero elements
                && o.push(c)                        // and add this index to JA
            )
            m[i+1] = m[i] + b.length,               // set next value of IA
            b                                       // and return filtered row
        ),
        m=[0],o=[]                          // initialize IA (m) and JA (o)
    ).reduce((x,y) => x.concat(y)),                 // flatten the non-zero matrix
m,o]                                                // append IA and JA

Xét nghiệm



1

Perl 6 , 84 byte

{.flatmap(*.grep(+*)),(0,|[\+] .map(+*.grep(+*))),.flat.kv.flatmap:{$^a%.[0]xx?$^b}}

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

Đối số ma trận đơn là trong $_.

  • .flatmap(*.grep(+*)) chọn các phần tử khác không của toàn bộ ma trận.
  • [\+] .map(+*.grep(+*))là mức giảm tam giác của số lượng phần tử trong mỗi hàng (mà một số ngôn ngữ gọi scan). (0,|...)chuẩn bị một số không vào danh sách đó.
  • .flat.kvtạo ra một danh sách được lập chỉ mục của tất cả các yếu tố của ma trận. .flatmap: { $^a % .[0] xx ?$^b }ánh xạ phẳng qua mô-đun của từng chỉ số theo số lượng cột trong mảng ( .[0], số phần tử trong hàng đầu tiên), được sao chép bởi chính phần tử, được hiểu là boolean. Nghĩa là, các phần tử khác 0 được sao chép một lần và các phần tử zero được sao chép 0 lần (nghĩa là loại bỏ).

1

Python + SciPy, 79 byte

tôi đoán tích hợp không bị cấm

from scipy.sparse import*
A=csr_matrix(input())
print A.data,A.indptr,A.indices

Chấp nhận đầu vào ở định dạng [[0, 0, 0, 0],[5, 8, 0, 0],[0, 0, 3, 0],[0, 6, 0, 0]]


1

Japt , 31 27 byte

Lấy đầu vào là một mảng của mảng và trả về một mảng của mảng.

[Uc f U®£X©NpYÃZèÃå+ iT NÅ]

Kiểm tra nó ( -Qcờ cho mục đích trực quan hóa)


Giải trình

Đầu vào ngầm định của mảng U.
[[1,1,1],[1,1,1],[1,1,1]]

Uc f

Đối với sub = -array đầu tiên, chúng ta làm phẳng ( c) Uvà sau đó lọc ( f) nó, loại bỏ bất kỳ phần tử falsey nào (tức là 0s)
[1,1,1,1,1,1,1,1,1]

U®         Ã

Chúng tôi sẽ xây dựng 2 mảng con khác cùng một lúc, bằng cách ánh xạ qua U.

£     Ã

Chúng tôi ánh xạ qua từng phần tử (mảng con) trong U

Xlà phần tử hiện tại của mảng con hiện tại và ©là logic AND ( &&) vì vậy, nếu Xkhông trung thực (không phải bằng 0) thì phần tiếp theo sẽ không được thực thi.

NpY

Trong Japt, Nlà một mảng chứa tất cả các đầu vào vì vậy ở đây, nếu Xlà sự thật, chúng ta đẩy ( p) chỉ mục ( Y) của phần tử hiện tại sang N.
[[[1,1,1],[1,1,1],[1,1,1]],0,1,2,0,1,2,0,1,2]

Quay lại bản đồ của mảng chính và, với mỗi phần tử ( Z), chúng ta có được số lượng phần tử trong mảng phụ đó là trung thực (không phải bằng 0).
[3,3,3]

å+

Tích lũy giảm mảng này bằng cách tính tổng.
[3,6,9]

iT

Chèn ( i) 0 vào chỉ mục 0 để hoàn thành mảng con thứ hai.
[0,3,6,9]

Đối với mảng con cuối cùng, chúng ta chỉ cần cắt Ntừ phần tử thứ nhất.
[0,1,2,0,1,2,0,1,2]


Tôi chỉ chạy các ví dụ khác và nó hoạt động
Pureferret
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.