Символічне матричне множення


26

Існує маса різних способів пояснення множення матриць. Я буду дотримуватися однієї фігури, оскільки я вважаю, що більшість людей тут знайомі (і ця цифра дуже описова). Якщо ви хочете отримати більш детальну інформацію, пропоную вам відвідати статтю у Вікіпедії або пояснення у WolframMathWorld .

Просте пояснення:

Припустимо, у вас є дві матриці - A і B , де A 3 на 2, а B - 2 на 3. Якщо ви виконаєте множення матриць на цих матрицях, або AB , або BA, ви отримаєте результати нижче:

введіть тут опис зображення

Виклик:

Реалізуйте символьне множення матриць у вашій мові. Ви повинні взяти дві матриці в якості вхідних даних, де кожен елемент в матрицях представлений символом ASCII, що не пробілює (кодові точки 33-126). Ви повинні вивести добуток цих матриць.

Правила щодо результатів:

Продукт з двох записів не повинен мати символів між ними. Це ab, чи не a*b, a·b, times(a,b)або що - щось подібне. Це aa, ні a^2.

Сума термінів повинна мати пробіл (ASCII код, точка 32) між ними. Це a b, ні a+b, plus(a,b)чи щось подібне.

Обґрунтування цих двох правил: Всі символи, що не мають пробілу, дозволені як символи в матрицях, тому використання їх як математичних символів було б безладним. Отже, те, що ти можеш нормально написати, як a*b+c*dбуде ab cd.

Ви можете вибрати порядок виконання умов. ab cd, dc abі cd baматематично говорять однаково, тож ви можете вибрати порядок і тут. Порядок не повинен бути послідовним, доки він математично правильний.

Правила щодо форматування матриці:

Матриця може бути введена в будь-якому форматі, який ви хочете, за винятком однієї рядка без обмежувачів між рядками (це тому, що вихід буде повністю зіпсований). Обидві матриці повинні бути введені в одному форматі. Усі наведені нижче приклади є дійсними способами введення та виведення матриці.

"ab;cd"     <- This will look awful, but it's still accepted.

"a,b\nc,d"

[[a,b],[c,d]] 

[a, b]
[c, d]

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

Загальні правила:

  • Ви можете припустити дійсний ввід. Матричне множення завжди буде можливим із заданими розмірами.
  • Буде лише дві матриці.
  • Ви можете припустити, що матриці не порожні
  • Вбудовані функції приймаються (але, ймовірно, трохи громіздкими через вимоги до форматування).
  • Ви, звичайно, можете використовувати знаки втечі, якщо це необхідно ( \'замість ').
  • Будь-який стандартний метод введення та виведення в порядку .

Тестові приклади:

Дві вхідні матриці показані порожнім рядком між ними. Вихід відображається після Output:. Коли є дві матриці виводу, тоді просто показати інші результати, які будуть прийняті.

Тест №1

Inputs:
[a]

[b]

Output:
[ab]
[ba]      <- Also OK

Тест №2

Inputs:
[a, b]
[1, 4] 
[y, {]

[%, 4, 1] 
[a, b, c]

Output:    
[a% ba, a4 bb, a1 bc] 
[1% 4a, 14 4b, 11 4c] 
[y% {a, y4 {b, y1 {c]

Тест №3:

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

[a]
[b]
[c]
[d]

Output:
[1a 2b 3c 4d]
[5a 6b 7c 8d]
[9a 1b 2c 3d]
[4a 5b 6c 7d]

[d4 c3 b2 a1]      <-- Also OK
[d8 c7 b6 a5]
[1b 9a c2 3d]
[a4 b5 d7 6c]

Якщо ваша відповідь на правила, що вимагають ab cdзамість цього, a*b+c*dє: вам слід уникати громіздких форматів вводу / виводу , то я хотів би зазначити, що формати введення та виведення дуже гнучкі. Те, що ви не можете використовувати, *а також +для продуктів і сум, може ускладнити використання простої вбудованої, але я не вважаю це негативним.


Для функції прийнятне прийняття двох двовимірних масивів рядків та повернення 2D масиву рядків?
— Денніс

Так без проблем. Але розміри повинні відповідати, ви не можете перенести другий вхід. Це мало сенс?
— Стюі Гріффін

Так і було, дякую за уточнення. Останнє запитання: Чи можу я також взяти 2D масив символів як вхід і повернути 2D масив рядків?
— Денніс

@Dennis, я писав: "Обидві матриці потрібно вводити в одному форматі". Я забув згадати там вихідну матрицю, тому я просто зберігаю її так. Входи повинні бути в одному форматі, але у вас може бути інший формат виводу. (Мені не дуже подобається це рішення, але я не хочу зараз змінювати речі. Я думаю, є вже одна відповідь, що має різні формати введення та виведення)
— Стюі Гріффін

Якщо ви маєте на увазі відповідь на Ruby, я перевірив, чи працює однаково добре з рядками замість символів.
— Денніс

Відповіді:


9

Haskell , 62 61 байт

e=[]:e
a!b=[unwords.zipWith(++)r<$>foldr(zipWith(:))e b|r<-a]

Спробуйте в Інтернеті! Приклад використання:

Prelude> [["a","b"],["c","e"]] ! [["f","g"],["h","i"]]
[["af bh","ag bi"],["cf eh","cg ei"]]

Я знайшов спосіб отримати transposeфункцію на один байт коротше, ніж використовувати імпорт:

import Data.List;transpose
e=[]:e;foldr(zipWith(:))e

Стара версія з імпортом: (62 байти)

import Data.List
a!b=[unwords.zipWith(++)r<$>transpose b|r<-a]

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

Це досить схоже на мою відповідь на несимволічне матричне множення : a!b=[sum.zipWith(*)r<$>transpose b|r<-a]заміщення множення (*)строковим конкатенацією (++)і за sumдопомогою unwordsякого об'єднує список рядків з пробілом між ними. Імпорт необхідний для transposeфункції, тому в цілому транспозиція другої матриці використовує половину байтів ...


Стара версія без імпорту: (64 байти)

a![]=[];a!b=(unwords.zipWith(++)[h|h:_<-b]<$>a):a![s:t|_:s:t<-b]

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

Імпорт і transposeфункція займає стільки байтів, я намагався вирішити завдання без імпорту. Поки що цей підхід виявився на два байти довше, але, можливо, він буде більш ігорним. Редагувати: інший підхід у верхній частині зараз перевищує імпорт!

Зрозуміння списку [s:t|_:s:t<-b]отримує не порожні хвости списків b, використовуючи лише [t|_:t<-b]для того, щоб хвости були на 4 байти коротшими (навіть перемогли імпортну версію), але додайте порожній рядок, як ["","",""]до матриці, яку, напевно, заборонено.


6

Математика, 36 байт

Inner[#<>#2&,##,StringRiffle@*List]&

Innerє узагальненням Mathematica Dot(тобто звичайного матричного / векторного продукту). Він узагальнює крапковий добуток, дозволяючи вам надати дві функції fі g, які будуть використані замість звичайного множення та додавання відповідно. Ми заміняємо множення на #<>#2&(яке об'єднує два символи в єдиний рядок) і додавання на StringRiffle@*List, яке спочатку загортає всі суми в список, а потім StringRiffleз'єднує їх разом з пробілами.

Можна потенційно скористатися Dotоператором, .а потім перетворити результат, але біда полягає в тому, що такі речі "a"*"a"негайно перетворяться на "a"^2(те ж саме для сум), що буде прикро відбирати знову.


6

Рубін, 61 байт

->a,b{a.map{|x|b.transpose.map{|y|x.zip(y).map(&:join)*' '}}}

Проба зразка:

main(0):007> ->a,b{a.map{|x|b.transpose.map{|y|x.zip(y).map(&:join)*' '}}}[[[?a, ?b], [?1, ?4], [?y, ?{]], [[?%, ?4, ?1], [?a, ?b, ?c]]]
=> [["a% ba", "a4 bb", "a1 bc"], ["1% 4a", "14 4b", "11 4c"], ["y% {a", "y4 {b", "y1 {c"]]
->a,b{
a.map{|x|            # for each row of a
b.transpose.map{|y|  # and for each column of b
x.zip(y)             # match up corresponding elements
.map(&:join)         # join each pair together
*' '                 # join the entire thing on space
}}}

4

Clojure, 53 байти

#(for[a %](for[b(apply map vector %2)](map str a b)))

Запуск з аргументами [["a" "b"]["c" "e"]]та [["f" "g"]["h" "i"]]повернення ((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei"))). Це насправді коротше, ніж числова версія .


3

Діалог APL , 10 байт

Приймає матриці символів як аргументи зліва та справа. Повертає матрицю списків символів. (APL представляє рядки як списки символів.)

{∊⍺' '⍵}.,

СпробуйтеAPL онлайн!

Звичайний внутрішній продукт є в APL +.×, але додавання та множення можуть бути будь-якими функціями, зокрема:

Доповнення було замінено
{ анонімною функцією:
 ∊ сплющений
 ⍺ ' ' ⍵ список, що складається з лівого аргументу, пробілу та правого аргументу⍵
}

Множення було замінено конкатенацією, ,


2

Желе , 7 байт

Z;"þK€€

Це діадичне посилання, яке приймає B і A в якості аргументів (у тому порядку) і повертає AB . Введення та вихід у вигляді двовимірних масивів рядків, які фактично є 3D-масивами символів. Подальший байт можна зберегти, взявши за вхід 2D-масиви символів . Я не впевнений, чи це дозволено.

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

Трохи важко визначити, що робить Jelly під кришкою, коли залучаються струни, оскільки це робить багато бризок перед друком. Ось як Jelly представляє вхід і вихід всередині.

Як це працює

Z;"þK€€  Dyadic link. Left argument: B. Right argument: A

Z        Zip/transpose B.
 ;"þ     Table vectorized concatenation; for each row in B' and each row in A,
         concatenate the corresponding strings.
    K€€  Join the arrays that correspond to the rows of A by spaces.

2

Пролог,> 256 байт

Я використовую {_ | _}, що є findall / 3, _ [_, _], який є деяким arg / 3, і сума (_), яка є деякою сукупністю. Всі вони можуть використовуватися всередині / 2:

*(X, Y, Z) :- functor(Y, matrice, _), L is len(X[1]), L =:= len(Y), !,
   M is len(X), N is len(Y[1]),
   Z is { { sum({ X[J,K] * Y[K,I] | between(1,L,K) })
                                  | between(1,N,I) }
                                  | between(1,M,J) }.

Разом з додатковими визначеннями для вищезгаданих предикатів і нестандартним є / 2, що може повернути більше чисел, його впевненість> 256 байт.


1

JavaScript (ES6), 65 байт

(a,b)=>a.map(c=>b[0].map((_,j)=>c.map((e,i)=>e+b[i][j]).join` `))

Приймає дані як два двовимірних масиви символів і повертає 2D масив рядків. Додайте 10 байт для підтримки введення у вигляді двох 1D масивів рядків.


1

Піт, 14 байт

clQmj;sMCd*QCE

Програма, яка приймає введення двох двовимірних списків символів, розділених новим рядком, і друкує двовимірний список рядків.

Тестовий набір

Як це працює

[Пояснення, що надходить пізніше]


1

Піп , 17 байт

{Y Zb{a._JsMy}Ma}

Це функція, яка бере два вкладені списки (односимвольних) рядків і повертає вкладений список рядків. Спробуйте в Інтернеті! (з двома тестовими випадками).

Пояснення

Аргументи до {}-розмежованої функції присвоюються локальним змінним aдо e. Перший аргумент лямбда-функції представлений символом _.

{               }  Define a function:
   Zb              Zip rows of b, transposing it
 Y                 Yank into global variable y for access in nested function
     {       }Ma   To the rows of a, map this function:
           My       To the rows of y (i.e. columns of b), map this function:
      a._           Concatenate, itemwise, the current row of a and row of y
         Js         Join the resulting list on space
                   The result of the outer map operation is returned
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.