[Question]
  [
Compress a sparse matrix using [Compressed sparse row (CSR, CRS or Yale format)](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_.28CSR.2C_CRS_or_Yale_format.29).
These are all the same form of compression (ignore new Yale).
Input may be any 2d data structure (list of lists, etc): e.g
```
[[0 0 0 0],
 [5 8 0 0],
 [0 0 3 0],
 [0 6 0 0]]
```
And the output should be three 1d data structures (list etc), that denote the outputs `A`, `IA` and `JA`, for example
```
[5, 8, 3, 6]
[0, 0, 2, 3, 4]
[0, 1, 2, 1,]
```
The process is described by wikipedia:
> 
> * The array `A` is of length `NNZ` and holds all the nonzero entries of `M` in
> left-to-right top-to-bottom ("row-major") order.
> * The array `IA` is of length `m + 1`. It is defined by this recursive
> definition:
> * `IA[0] = 0`
> 
> 
> `IA[i] = IA[i − 1] + (number of nonzero elements on the (i − 1)-th row in the original matrix)`
> * Thus, the first `m` elements of `IA` store the index into `A` of the first
> nonzero element in each row of `M`, and the last element `IA[m]` stores
> `NNZ`, the number of elements in `A`, which can be also thought of as the
> index in `A` of first element of a phantom row just beyond the end of
> the matrix `M`. The values of the `i`-th row of the original matrix is
> read from the elements `A[IA[i]]` to `A[IA[i + 1] − 1]` (inclusive on both
> ends), i.e. from the start of one row to the last index just before
> the start of the next.[5]
> * The third array, `JA`, contains the column index in `M` of each element of
> `A` and hence is of length `NNZ` as well.
> 
> 
> 
If your language doesn't support actual data structures, input and output may be text.
# Test cases
Input 1:
```
[[0 0 0 0],
 [5 8 0 0],
 [0 0 3 0],
 [0 6 0 0]]
```
Output 1:
```
[ 5, 8, 3, 6 ]
[ 0, 0, 2, 3, 4 ]
[ 0, 1, 2, 1, ]
```
Input 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]]
```
Output 2:
```
[ 10 20 30 40 50 60 70 80 ]
[  0  2  4  7  8 ]
[  0  1  1  3  2  3  4  5 ]
```
Input 3:
```
[[0 0 0],
 [0 0 0],
 [0 0 0]]
```
Output 3:
```
[ ]
[ 0 0 0 0 ]
[ ]
```
Input 4:
```
[[1 1 1],
 [1 1 1],
 [1 1 1]]
```
Output 4:
```
[ 1 1 1 1 1 1 1 1 1 ]
[ 0 3 6 9 ]
[ 0 1 2 0 1 2 0 1 2 ]
```
Input 5:
```
[[0 0 0 0],
 [5 -9 0 0],
 [0 0 0.3 0],
 [0 -400 0 0]]
```
Output 5:
```
[ 5, -9, 0.3, -400 ]
[ 0, 0, 2, 3, 4 ]
[ 0, 1, 2, 1, ]
```
Assume inputs may contain any real number, you need not consider mathematical symbols or exponential representation (e.g. 5,000 will never be entered as 5e3). You will not need to handle `inf`, `-inf`, `NaN` or any other 'pseudo-numbers'. You may output a different representation of the number (5,000 *may* be output as 5e3 if you so choose).
# Scoring
This is a [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), fewest bytes wins.
  
[Answer]
# [MATL](https://github.com/lmendo/MATL), 19 bytes
```
!3#f!Dx0Gg!XsYshDq!
```
Input uses `;` as row separator.
[Try it online!](https://tio.run/##y00syfn/X9FYOU3RpcLAPV0xojiyOMOlUPH//2gDBTC0VjBVsIAwQHxjCMMMxIkFAA "MATL – Try It Online") Or verify all test cases: [1](https://tio.run/##y00syfn/X9FYOU3RpcLAPV0xojiyOMOlUPH//2gDBTC0VjBVsIAwQHxjCMMMxIkFAA), [2](https://tio.run/##y00syfn/X9FYOU3RpcLAPV0xojiyOMOlUPH//2hDAwUjAwUotAYSxiCWCZxroGBqoGBmoGAO50OghUEsAA), [3](https://tio.run/##y00syfn/X9FYOU3RpcLAPV0xojiyOMOlUPH//2gDBSC0VkCmYgE), [4](https://tio.run/##y00syfn/X9FYOU3RpcLAPV0xojiyOMOlUPH//2hDBSC0VkCmYgE), [5](https://tio.run/##y00syfn/X9FYOU3RpcLAPV0xojiyOMOlUPH//2gDBTC0VjBV0LWEsMACesYQpq6JAZgfCwA).
### Explanation
```
!     % 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
```
[Answer]
# Mathematica, 78 bytes
```
{a=SparseArray@#;a@"NonzeroValues",a@"RowPointers",Join@@a@"ColumnIndices"-1}&
```
See [this answer on mathematica.stackexchange.com](https://mathematica.stackexchange.com/a/83722/6652).
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 24 bytes
```
n0S€0;;\S€,T€Ẏ$’$
Ẏḟ0W;Ç
```
[Try it online!](https://tio.run/##y0rNyan8/z/PIPhR0xoDa@sYEK0TAiQe7upTedQwU4ULyHi4Y75BuPXh9v///0dHG@goQFGsDpdCtKmOggUSFyJljMQ1g8rGAgA "Jelly – Try It Online")
[Answer]
# [APL (Dyalog)](https://www.dyalog.com/), ~~31~~ 28 chars or ~~36~~ 33 bytes\*
Requires `⎕IO←0` for zero based indexing. I/O is list of lists.
```
{(∊d)(0,+\≢¨d←⍵~¨0)(∊⍸¨⍵≠0)}
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///qG@qp/@jtgkG/9OAZLXGo46uFE0NAx3tmEediw6tSAEKPurdWndohYEmSO5R745DK4ACjzoXGGjW/g8qzQPpUldQf9S76lEvUKYTyNB41DYRqEZTXeFR2yR1DZBU31SvYH@/QyvSFEAStUByroJXaXGJQlp@kUJeZnKqQkpmcUFOYiXISAUNAwUw1FTQMFWwgLJAIsZQlhlYjAus1tBAwQiqHiprDGKaGCDpMwVqMVAwRwhAoAXMDGS1CBpqvgIQaqLTXBjuPLTeElm3Hsyth9abGEBUAQA "APL (Dyalog Unicode) – Try It Online")
`{`…`}` anonymous function where the argument is represented by *⍵*
 `(`…`)(`…`)(`…`)` return a list of three things:
  `⍵≠0` Boolean where the argument differs from 0  
  `⍸¨` **ɩ**ndices of those for each sub-list  
  `∊` **ϵ**nlist (flatten) to combine into single list
  `⍵~¨0` remove zeros from each sub-list of the argument  
  `d←` store that as *d*  
  `≢¨` tally each  
  `+\` cumulative sum  
  `0,` prepend a zero
  `∊d` **ϵ**nlist (flatten) *d* to combine into single list
  
---
\* To run in Dyalog Classic, simply replace `⍸` with `⎕U2378`.
[Answer]
## Haskell, 87 bytes
```
f s|a<-filter(/=0)<$>s=(id=<<a,scanl(+)0$length<$>a,s>>= \t->[i|(i,e)<-zip[0..]t,e/=0])
```
[Try it online!](https://tio.run/##bYyxDsIgEIZ3n@KGDhChkhiNA/AiyEAstRcRm8Jk@u6IDYmLueG@fP/dP7n08CGUMkJaneQjhuwXclCCyk4nRXBQUjqWbi4GsqeiCz7e81TDKrVWcM1cG1wJMk8lf@NsRN/bzHztsLQ8HUZQMLx2APOCMUMHIxgj2DaWmRO7NPqaY6Pz5uy/r3b52xbKBw "Haskell – Try It Online")
How it works:
```
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
```
[Answer]
# Python+SciPy, 79 bytes
i guess built-ins were not forbidden
```
from scipy.sparse import*
A=csr_matrix(input())
print A.data,A.indptr,A.indices
```
Accepts input in the format `[[0, 0, 0, 0],[5, 8, 0, 0],[0, 0, 3, 0],[0, 6, 0, 0]]`
[Answer]
# [R](https://www.r-project.org/), 70 bytes
```
function(m,M=t(m))list(M[x<-!!M],diffinv(colSums(x)),which(x,T)[,1]-1)
```
[Try it online!](https://tio.run/##NYzNCoMwEIRfRW@7sIFKf@hBHyGnehMPNiW4YDYQY02fPmpLGfjmm8uEbItaFdkuYiJ7AUe6ieAQJ54j6C7Vqix1Ty@2luUNxk@Pxc2QEGkd2YyQqMWOql5VmC24IQZOYOBEv1zpTn8/f3k7iCTBr82FZH/c6/k5ZouYNw "R – Try It Online")
This is an old, [matrix](/questions/tagged/matrix "show questions tagged 'matrix'") challenge that didn't get an R answer for 3 years! Having to do this in row-major rather than column-major order costs 8 bytes (`,M=t(m))`).
[Answer]
# [Python 3](https://docs.python.org/3/), 96 bytes
```
lambda m:list(map(list,zip(*[[e,i,j] for i,r in enumerate(m) for j,e in enumerate(r) if e!=0])))
```
[Try it online!](https://tio.run/##VY7LCsIwEEX3/Yq4S2QqYx@@oF8Ss4iYYEqThhgX@vO1L4hyGbj3MHMZ/46P3pWDbq5DJ@3tLom9dOYZqZWeTgY@xtMt5woMtILoPhAD4zii3MuqIKOils28BfXPAyNGE7VpUDDGhliQhnC@RygQVgngCOVkq5QRaoQDwjGBRScUIov1XJMKasjPP7e4K1efV7jsiMwH4yLVNBaMpVCPX30B "Python 3 – Try It Online")
[Answer]
# [PHP](https://php.net/), 107 bytes
```
<?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);
```
[Try it online!](https://tio.run/##VY1BCsIwFET3nkLLLFqSRUEUMX67Ei/g7vMppSqFthgihtbLxyiIdjHMMG9gbGPDrrCNnaE8Hk7EnOSJ/pNoTlYxbSbNly8nzfq3EROuN5diJEZNuRg4@jywQqeUmCziS1U3Kdy8uqOlPXy2gC@2jIGF4DWeb281RkYnpBRqMb5y5fnR2xRDBHGTmRBe "PHP – Try It Online")
# [PHP](https://php.net/), 109 bytes
```
<?$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);
```
[Try it online!](https://tio.run/##K8go@G9jX5BRwKUS7@4aYhsdrWSgpIOEY3WilUyBLAsUEZi8MYqIGUJNrPV/lUrbaJVkW4NY67T8otTE5AwNsBUKicUqRZrVcLEikEC2rZ1KmWZmmgaQrFapiI61VSmzVqkC0dnWKsna2ta1KpUgXrJ1bVliUXxKaW6BhkqFjkqljkqVpvX//wA "PHP – Try It Online")
[Answer]
# JavaScript (ES6), 117 bytes
```
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]
```
Input is a 2D array of numbers and output is an array of `[A, IA, JA]`.
## Explained
```
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
```
## Tests
```
let f=
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]
let run=x=>O.innerHTML+=f(x).map(s=>`[${s.join`, `}]`).join`\n`+"\n\n"
run([[0,0,0,0],[5,8,0,0],[0,0,3,0],[0,6,0,0]])
run([[10,20,0,0,0,0],[0,30,0,40,0,0],[0,0,50,60,70,0],[0,0,0,0,0,80]])
run([[0,0,0],[0,0,0],[0,0,0]])
run([[1,1,1],[1,1,1],[1,1,1]])
run([[0,0,0,0],[5,-9,0,0],[0,0,0.3,0],[0,-400,0,0]])
```
```
<pre id=O></pre>
```
[Answer]
# [Japt](https://github.com/ETHproductions/japt), ~~31~~ ~~27~~ 17 [bytes](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
Hopefully this output format is OK.
```
cf pUmè iT å+ Ucð
```
[Try it](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=Y2YgcFVt6CBpVCDlKyBVY/A&input=WwpbMCAwIDAgMF0KWzUgOCAwIDBdClswIDAgMyAwXQpbMCA2IDAgMF0KXS1R)
```
cf pUmè iT å+ Ucð     :Implicit input of 2D array U
c                     :Flat map
 f                    :  Filter
   p                  :Push the following two elements
    Um                :  First element: Map U
      è               :    Count the truthy elements in each
        i             :  Prepend
         T            :    Zero
           å+         :  Cumulatively reduce by addition
              Uc      :  Second element: Flat map U
                ð     :    0-based indices of truthy elements
```
[Answer]
# [Python 2](https://docs.python.org/2/), 115 bytes
```
lambda m:zip(*[[v,i]for k in m for i,v in enumerate(k)if v])+[reduce(lambda a,b:a+[len(b)-b.count(0)+a[-1]],m,[0])]
```
[Try it online!](https://tio.run/##TYzLDoIwEEX3fsUsWxnIiOIr8UvqLAqU2EALIYVEfx5FSTB3c@48TvcMj9anU3W7T412eanBXV@2E1ulRrRctT3UYD04mNHiOBfjB2d6HYyopa1gZBmp3pRDYcQi0ZhfdaQa40Uu4zwp2sEHQTLSKt4xo0NFLHkKKdxAqR1hSriEPzvcz3hYO2FGeCQ8rYNfzsS8CdlXswoyjC9/v5TsF44P9LvhTddbH6ASIZUrZ3J6Aw "Python 2 – Try It Online")
Output is `[A, JA, IA]`
[Answer]
# [Perl 6](http://perl6.org/), 84 bytes
```
{.flatmap(*.grep(+*)),(0,|[\+] .map(+*.grep(+*))),.flat.kv.flatmap:{$^a%.[0]xx?$^b}}
```
[Try it online!](https://tio.run/##TYvtCoIwGIVv5fww2dwYbx9apNmFmMIC148UhkYo5rUv7APG8@fwPBxbd03i2hGhwclNyjT60WrLInXrastExLlkJF/FRZRQSxFe4vJzUPfn/3icgkqvVEHlMJyD6jrPLkWvRxjGsjVhQ/iRS2SE7bJ3niDEhISw98yXA@Wcp@4N "Perl 6 – Try It Online")
The single matrix argument is in `$_`.
* `.flatmap(*.grep(+*))` selects the nonzero elements of the entire matrix.
* `[\+] .map(+*.grep(+*))` is the triangular reduction of the number of elements in each row (which some languages call `scan`). `(0,|...)` prepends a zero to that list.
* `.flat.kv` produces an indexed list of all elements of the matrix. `.flatmap: { $^a % .[0] xx ?$^b }` flat-maps over the modulus of each index by the number of columns in the array (`.[0]`, the number of elements in the first row), replicated by the element itself, interpreted as a boolean. That is, nonzero elements are replicated once, and zero elements are replicated zero times (ie, removed).
[Answer]
# [Julia](http://julialang.org/), ~~66~~ 63 bytes
```
using SparseArrays
n*a=getfield(sparse(a'),n)
!a=5a,3a.-1,4a.-1
```
`SparseArrays` is a standard library that stores with CSC instead of CSR (column instead of row or something), that's why we need to transpose (`a'`).
-6 bytes if 1-indexing was allowed
overloads `*` with `getfield` to save a few bytes
[Try it online!](https://tio.run/##jVHLboMwELz7Kza5FFfGsmNo4MCh39Aj5WAlTuQKOYhHlXw99QMotD3Ua63WM@udtfdjqLXk93EcOm2u8NbItlOvbSsfHTLPsriq/qJVfY46z0TyCROD0U4WqSRC0piTxPnxMphTr28GetX1kTYE1L2hlGIEdt2GHgrYaeNPZ901tXzYrMA2rTZ9baL9u9lvEBrZi9scX6mAT3WikVXAWxYjZc4I@R5QWTLwViEoU8jm0GFiDl88WhFUQkogIyCIxfyZEbcPHkoWiHvI@grhRYgzOExic2Hh4oStRVMrx@C4QoJlUwOhivDXltyMBWmbBwewjcAR7FsWjPstPCk8nzoSbz9hEfwOfIXwqskCsnqVrczdhR@BzXPd/rKpmLAfmM8Hbvta@wr/PZ0433RHlwHFCWObGcU5cTwJzL8mhccv "Julia 1.0 – Try It Online")
[Answer]
# Scala, 82 bytes
```
x=>x.flatMap(_.zipWithIndex).filter(_._1!=0).unzip->x.scanLeft(0)(_+_.count(_!=0))
```
[Try it in Scastie!](https://scastie.scala-lang.org/bOf3LO1ERQSNkIt1fl43Zg)
Returns `((A, JA), IA)`
Explanation:
```
x =>     //The sparse matrix to be smooshed
x.flatMap(      //Do the following operation to each row, then flatten the result
  _.zipWithIndex //Zip each element with its column (makes tuples)
).filter(      //Keep the tuples where
  _._1!=0      //the first element isn't 0
).unzip        //Unzip into a tuple of two lists, A and JA
->             //Make that the first element of another 2-tuple with IA:
x.scanLeft(0)(  //Starting with 0
  _+_.count(_!=0)  //Add the number of nonzero elements in each row
)               //Keep the intermediate results, giving us IA
```
]