Стиснути розріджену матрицю


18

Стисніть розріджену матрицю за допомогою стисненого розрідженого рядка (формат CSR, CRS або Yale) .

Це все ті ж форми стиснення (ігноруйте новий Єльський).

Вхідним може бути будь-яка 2d структура даних (список списків тощо): напр

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

І вихід повинен бути трьома 1d структурами даних (список тощо), що позначають виходи A, IAі JA, наприклад

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

Процес описаний у wikipedia:

  • Масив A має довжину NNZ і містить усі ненульові записи M у порядку "зліва направо зверху вниз" (рядок-мажор ").

  • ІА масиву має довжину m + 1. Це визначається цим рекурсивним визначенням:

    • IA [0] = 0 IA [i] = IA [i - 1] + (кількість ненульових елементів у (i - 1) -му рядку в початковій матриці)

    • Таким чином, перші m елементів IA зберігають індекс у A першого першого ненульового елемента у кожному рядку M, а останній елемент IA [m] зберігає NNZ, кількість елементів у A, яке також можна вважати як індекс в A першого елемента фантомного ряду трохи за кінцем матриці M. Значення i-го рядка вихідної матриці зчитуються з елементів A [IA [i]] до A [IA [i + 1] - 1] (включно з обох кінців), тобто від початку одного рядка до останнього індексу безпосередньо перед початком наступного. [5]

    • Третій масив, JA, містить індекс стовпців у M кожного елемента A і, отже, також має довжину 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, ]

Припустимо, що вхідні дані можуть містити будь-яке дійсне число, вам не потрібно враховувати математичні символи або експоненціальне представлення (наприклад, 5000 ніколи не буде введено як 5e3). Вам не потрібно обробляти inf, -inf, NaNабо будь-які інші «псевдо-номера». Ви можете вивести інше представлення числа (5,000 може бути виведено як 5e3, якщо ви захочете).

Оцінка:

Це , виграє найменше байтів.

Табло лідерів

Ось фрагмент стека для створення як звичайного табло, так і огляду переможців за мовою.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

# 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? №
Pureferret

1
Не IA[0] = 0зовсім зайве? Потрібно лише визначитись IA[i] = IA[i − 1]..., але ми можемо просто констатувати, що якщо i-1 < 0використовувати 0. Тобто, IA [0] завжди дорівнює 0, для цього його можна стиснути (так, я розумію, що це критика алгоритму, не цей виклик).
Draco18s більше не довіряє SE

Чи будемо мати і зворотний виклик?
Adám

1
Акуратно! Раніше не працював у жодному з форматів, але я радий бачити, що хтось ще бачив це раніше (я не повинен бути такою людиною, яка бачить тривіальну оптимізацію в алгоритмах цієї старої).
Draco18s більше не довіряє SE

Відповіді:


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

Haskell, 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 Булева, де аргумент відрізняється від 0
  ⍸¨d ndices аргументів для кожного підсписку
  ϵ NLIST (сплюснути) об'єднати в один список

  ⍵~¨0 видалити нулі з кожного суб-лист аргументу
  d← магазину , який , як д
  ≢¨  бирки кожній
  +\ сукупна суми
  0, Prepend нуля

  ∊dϵ nlist (згладити) d для об'єднання в один список

  


* Для запуску в Dyalog Classic просто замініть на ⎕U2378.


Добре, я не розумію формат введення? f 4 4⍴а потім значення?
Pureferret

@Pureferret Код визначає функцію f. Вхід - це дійсно REPL, який викликає fрезультат, 4 4⍴…який r формує дані в матрицю 4 × 4.
Adám

1
Rho для r eshapes. Я розумію!
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 - це рядок або масив рядків. Я не вводив дані, тому якщо ви хочете, щоб результат був чисто замінений $x[]=$v на$x[]=+$v
Йорг Гюльсерманн

2

JavaScript (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]

Вхід - це двовимірний масив чисел, а вихід - масив [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

Perl 6 , 84 байти

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

Спробуйте в Інтернеті!

Аргумент єдиної матриці знаходиться в $_.

  • .flatmap(*.grep(+*)) вибирає ненульові елементи всієї матриці.
  • [\+] .map(+*.grep(+*))це трикутне зменшення кількості елементів у кожному рядку (який деякі мови називають scan). (0,|...)призначає нуль до цього списку.
  • .flat.kvвиробляє індексований перелік усіх елементів матриці. .flatmap: { $^a % .[0] xx ?$^b }плоскі карти по модулю кожного індексу за кількістю стовпців у масиві ( .[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

Япт , 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 ми згладжуємо ( c), Uа потім фільтруємо його ( f), видаляючи будь-які елементи фальси (тобто 0s)
[1,1,1,1,1,1,1,1,1]

U®         Ã

Ми збираємося будувати інші 2 підмасиви одночасно, відображаючи карти U.

£     Ã

Зображуємо кожен елемент (підмасив) в U

Xє поточним елементом поточного підмасива і ©є логічним AND ( &&), тому, якщо Xне є truthy (не нульовим), наступна частина не буде виконана.

NpY

У Japt N- це масив, що містить усі входи, тому тут, якщо Xє truthy, ми натискаємо ( p) index ( Y) поточного елемента наN .
[[[1,1,1],[1,1,1],[1,1,1]],0,1,2,0,1,2,0,1,2]

Повертаємось до карти основного масиву, і для кожного елемента ( Z) ми отримуємо кількість елементів у цьому підмасиві, які є truthy (не нульовим).
[3,3,3]

å+

Кумулятивно зменшити цей масив шляхом підсумовування.
[3,6,9]

iT

Вставте ( i) 0 в індексі 0, щоб завершити другий підмасив.
[0,3,6,9]

Для остаточного масиву ми просто відрізаємо Nвід 1-го елемента.
[0,1,2,0,1,2,0,1,2]


Хоча я просто запустив інші приклади, і це працює
Pureferret
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.