희소 행렬 압축


18

압축 스파 스 행 (CSR, CRS 또는 Yale 형식)을 사용하여 스파 스 행렬을 압축합니다 .

이들은 모두 동일한 압축 형식입니다 (새 Yale 무시).

입력은 임의의 2D 데이터 구조 일 수 있습니다 (리스트 목록 등) : 예

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

출력은 출력을 나타내고 그 세 1D 데이터 구조 (목록 등)이어야 A, IAJA예를 들면,

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

이 과정은 wikipedia에서 설명합니다.

  • 배열 A의 길이는 NNZ이며 M에서 0이 아닌 모든 항목을 왼쪽에서 오른쪽 위에서 아래로 ( "행 주요") 순서로 보유합니다.

  • 배열 IA의 길이는 m + 1입니다.이 순환 정의에 의해 정의됩니다.

    • IA [0] = 0 IA [i] = IA [i-1] + (원래 행렬의 (i-1) 번째 행에있는 0이 아닌 요소 수)

    • 따라서 IA의 첫 번째 m 요소는 인덱스를 M의 각 행에서 0이 아닌 첫 번째 요소의 A에 저장하고 마지막 요소 IA [m]은 A의 요소 수인 NNZ를 저장합니다. 행렬 M의 끝 바로 위에있는 팬텀 행의 첫 번째 요소의 A 인덱스. 원래 행렬의 i 번째 행의 값은 요소 A [IA [i]]에서 A [IA [i + 1] − 1] (양쪽에 포함), 즉 한 행의 시작부터 다음 행의 시작 직전의 마지막 인덱스까지. [5]

    • 세 번째 배열 인 JA는 A의 각 요소에 대한 M의 열 인덱스를 포함하므로 길이는 NNZ입니다.

언어가 실제 데이터 구조를 지원하지 않으면 입력 및 출력이 텍스트 일 ​​수 있습니다.

테스트 사례

입력 1 :

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

출력 1 :

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

입력 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]]

출력 2 :

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

입력 3 :

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

출력 3 :

[ ]
[ 0 0 0 0 ]
[ ]

입력 4 :

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

출력 4 :

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

입력 5 :

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

출력 5 :

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

입력에 실수가 포함될 수 있다고 가정하면 수학 기호 나 지수 표현을 고려할 필요가 없습니다 (예 : 5,000은 5e3으로 입력되지 않습니다). 당신은 처리 할 필요가 없습니다 inf, -inf, NaN또는 기타 '의사 숫자'. 숫자의 다른 표현을 출력 할 수 있습니다 ( 원하는 경우 5,000 5e3으로 출력 될 수 있음).

채점 :

이것은 가장 적은 바이트 수 의 입니다.

리더 보드

다음은 일반 리더 보드와 언어 별 수상자 개요를 생성하는 스택 스 니펫입니다.

답변이 표시되도록하려면 다음 마크 다운 템플릿을 사용하여 헤드 라인으로 답변을 시작하십시오.

# Language Name, N bytes

N제출물의 크기는 어디에 있습니까 ? 당신이 당신의 점수를 향상시킬 경우에, 당신은 할 수 있습니다 를 통해 눈에 띄는에 의해, 헤드 라인에 오래된 점수를 유지한다. 예를 들어 :

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

헤더에 여러 숫자를 포함하려는 경우 (예 : 점수가 두 파일의 합계이거나 인터프리터 플래그 페널티를 별도로 나열하려는 경우) 실제 점수가 헤더 의 마지막 숫자 인지 확인하십시오 .

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

언어 이름을 링크로 만들어 리더 보드 스 니펫에 표시 될 수도 있습니다.

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


마지막 행에 1 기반 인덱스를 사용할 수 있습니까?
Leo

JA의 @Leo? 호
Pureferret

1
가없는 IA[0] = 0완전히 불필요? 을 정의하는 것만 필요 IA[i] = IA[i − 1]...하지만 i-1 < 00을 사용 하면 간단히 IA [0]은 항상 0과 같이 압축 될 수 있습니다. 이 도전이 아닙니다).
Draco18s

우리도 역의 도전을 할 것입니까?
Adám

1
산뜻한! 이전에는 두 형식 중 하나를 실행하지 않았지만 다른 사람이 이전에 알고있는 것을 보게되어 기쁩니다 (이 알고리즘에서 사소한 최적화를 발견하는 사람은 아닙니다).
Draco18s

답변:


6

MATL , 19 바이트

!3#f!Dx0Gg!XsYshDq!

입력은 ;행 구분자로 사용 됩니다.

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 : 1 , 2 , 3 , 4 , 5 .

설명

!     % 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

하스켈, 87 바이트

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

온라인으로 사용해보십시오!

작동 방식 :

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 자 또는 36 33 바이트 *

⎕IO←0제로 기반 인덱싱이 필요 합니다. I / O는 목록의 목록입니다.

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

온라인으로 사용해보십시오!

{} 인수가 로 표시되는 익명 함수

(... )(... )(... ) 세 가지의 목록을 반환 :

  ⍵≠0단일 하위 목록 으로 결합 할  인수가 각 하위 목록 ϵ nlist (flatten)에 대한 인수와 0이
  ⍸¨아닌 부울
  

  ⍵~¨0 인수의 각 서브 제로리스트로부터 제거
  d← 로 저장하는 D
  ≢¨  탈리 각
  +\ 누적 합이
  0, 0을 붙일

  ∊dε NLIST (패턴 화 된) D 단일 목록에 합치

  


* Dyalog 클래식에서 실행하려면 교체 와 함께 ⎕U2378.


그래도 입력 형식을 이해하지 못합니까? f 4 4⍴그런 다음 값은?
Pureferret

@Pureferret 코드는 함수를 정의합니다 f. 입력은 실제로 호출 REPL 인 f결과에 4 4⍴…있는 R은 4 × 4 매트릭스로 데이터를 eshapes.
Adám

1
r을 위한 Rho . 알겠습니다!
Pureferret

1
@Pureferret 온라인으로 사용해보십시오! 테스트 사례를보다 잘 보여줄 수있는 링크.
Adám

2

PHP , 107 바이트

<?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);

온라인으로 사용해보십시오!

PHP , 109 바이트

<?$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);

온라인으로 사용해보십시오!


숫자가 문자열이어야합니까?
Pureferret

1
@Pureferret PHP의 모든 입력은 문자열 또는 문자열 배열입니다. 당신은 출력이 대체하는 int 순전히 바란다 그래서 만약 내가 입력을 주조하지 않은 $x[]=$v$x[]=+$v
요 르그 Hülsermann

2

자바 스크립트 (ES6), 117 바이트

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]

입력은 숫자의 2D 배열이고 출력은의 배열입니다 [A, IA, JA].

설명

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

테스트



1

펄 6 , 84 바이트

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

온라인으로 사용해보십시오!

단일 행렬 인수는입니다 $_.

  • .flatmap(*.grep(+*)) 전체 행렬의 0이 아닌 요소를 선택합니다.
  • [\+] .map(+*.grep(+*))각 행의 요소 수를 삼각형으로 줄입니다 (일부 언어에서는 scan). (0,|...)해당 목록 앞에 0을 추가합니다.
  • .flat.kv행렬의 모든 요소에 대한 색인화 된 목록을 생성합니다. 요소 자체에 의해 복제 된 .flatmap: { $^a % .[0] xx ?$^b }배열의 열 수 ( .[0], 첫 번째 행의 요소 수) 로 각 인덱스의 계수에 대한 평면 맵을 부울로 해석합니다. 즉, 0이 아닌 요소는 한 번 복제되고 0 개의 요소는 0 회 복제됩니다 (즉, 제거됨).

1

Python + SciPy, 79 바이트

내장이 금지되지 않았다고 생각합니다

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

형식으로 입력을 받아들입니다 [[0, 0, 0, 0],[5, 8, 0, 0],[0, 0, 3, 0],[0, 6, 0, 0]]


1

apt , 31 27 바이트

입력을 배열의 배열로 받아서 배열의 배열을 반환합니다.

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

그것을 테스트 (-Q 시각화 목적으로 만 플래그 지정)


설명

배열의 암시 적 입력 U.
[[1,1,1],[1,1,1],[1,1,1]]

Uc f

첫 번째 sub = -array의 경우 잘못된 요소 (예 : 0)를 제거하여 평탄화 ( c) U한 다음 필터링 ( f)합니다.
[1,1,1,1,1,1,1,1,1]

U®         Ã

에 매핑하여 다른 두 개의 하위 배열을 동시에 만들 것 U입니다.

£     Ã

각 요소 (하위 배열)를 매핑합니다. U

X는 현재 하위 배열의 현재 요소 ©이며 논리 AND ( &&)이므로 사실 X이 아닌 경우 (0이 아님) 다음 부분이 실행되지 않습니다.

NpY

Japt에서 N모든 입력을 포함하는 배열이므로 여기에서 사실이라면 현재 요소 의 인덱스 ( )를로 X푸시 합니다 .pYN
[[[1,1,1],[1,1,1],[1,1,1]],0,1,2,0,1,2,0,1,2]

기본 배열의 맵으로 돌아가서 각 요소 ( Z)에 대해 하위 배열의 요소 수 (진실하지 않음)를 얻습니다 (0이 아님).
[3,3,3]

å+

합산하여이 배열을 누적 적으로 줄입니다.
[3,6,9]

iT

i인덱스 0에 ( ) 0을 삽입 하여 두 번째 하위 배열을 완료합니다.
[0,3,6,9]

마지막 하위 배열의 N경우 첫 번째 요소에서 간단히 슬라이스 합니다.
[0,1,2,0,1,2,0,1,2]


방금 다른 예제를 실행했지만 작동합니다
Pureferret
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.