Multiplikasi matriks simbolik

26

Ada banyak cara berbeda untuk menjelaskan perkalian matriks. Saya akan tetap dengan satu figur karena saya percaya sebagian besar orang di sini akrab dengannya (dan angka itu sangat deskriptif). Jika Anda ingin informasi lebih rinci, saya sarankan Anda mengunjungi artikel Wikipedia , atau penjelasan tentang WolframMathWorld .

Penjelasan sederhana:

Misalkan Anda memiliki dua matriks, A dan B , di mana A adalah 3-oleh-2, dan B adalah 2-oleh-3. Jika Anda melakukan perkalian matriks pada matriks ini, baik AB , atau BA Anda akan mendapatkan hasil di bawah ini:

masukkan deskripsi gambar di sini

Tantangan:

Terapkan penggandaan matriks simbolik dalam bahasa Anda. Anda harus mengambil dua matriks sebagai input, di mana setiap elemen dalam matriks diwakili oleh karakter ASCII non-spasi putih (kode poin 33-126). Anda harus mengeluarkan produk dari matriks ini.

Aturan tentang output:

Produk dari dua entri tidak boleh memiliki simbol di antaranya. Ini ab, tidak a*b, a·b, times(a,b)atau sesuatu yang serupa. Ini aa, tidak a^2.

Jumlah istilah harus memiliki spasi (ASCII kode titik 32) di antaranya. Ini a b, bukan a+b, plus(a,b)atau sesuatu yang serupa.

Alasan dari kedua aturan tersebut adalah: Semua karakter non-spasi putih diizinkan sebagai simbol dalam matriks, sehingga menggunakannya sebagai simbol matematika akan berantakan. Jadi, apa yang biasanya Anda bisa menulis sebagai a*b+c*dakan ab cd.

Anda dapat memilih urutan persyaratan. ab cd, dc abdan cd basecara matematis sama, sehingga Anda dapat memilih pesanan di sini juga. Urutan tidak perlu konsisten selama itu benar secara matematis.

Aturan tentang pemformatan matriks:

Matriks dapat dimasukkan dalam format apa pun yang Anda suka, kecuali satu string tanpa pembatas di antara baris (ini karena output akan benar-benar kacau). Kedua matriks harus dimasukkan pada format yang sama. Semua contoh di bawah ini adalah cara yang valid untuk memasukkan dan mengeluarkan matriks.

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

"a,b\nc,d"

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

[a, b]
[c, d]

Saya sadar bahwa ini memungkinkan banyak format yang akan terlihat berantakan, tetapi tantangannya adalah tentang mengalikan matriks, bukan memformat output.

Aturan umum:

  • Anda dapat menerima input yang valid. Penggandaan matriks akan selalu dimungkinkan dengan dimensi yang diberikan.
  • Hanya akan ada dua matriks.
  • Anda dapat mengasumsikan bahwa matriks tidak kosong
  • Fungsi bawaan diterima (tapi mungkin agak rumit karena persyaratan pemformatan).
  • Anda tentu saja dapat menggunakan karakter melarikan diri dalam input jika perlu ( \'bukan ').
  • Setiap input dan output metode standar OK .

Kasus uji:

Dua matriks input ditampilkan dengan garis kosong di antaranya. Output ditampilkan setelah Output:. Ketika ada dua matriks keluaran maka itu hanya untuk menunjukkan keluaran lain yang akan diterima.

Uji kasus # 1

Inputs:
[a]

[b]

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

Uji kasus # 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]

Test case # 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]

Jika respons Anda terhadap aturan tentang keharusanab cd alih - alih a*b+c*dadalah: Anda harus menghindari format input / output yang rumit , maka saya ingin mencatat bahwa format input dan output sangat fleksibel. Fakta bahwa Anda tidak dapat menggunakan *dan +untuk produk dan jumlah mungkin membuatnya lebih sulit untuk menggunakan built-in yang sederhana, tapi saya tidak menganggap hal negatif itu.

Stewie Griffin
sumber
Untuk suatu fungsi, apakah mengambil dua array string 2D dan mengembalikan array string 2D dapat diterima?
Dennis
Iya tidak masalah. Tetapi dimensi harus cocok, Anda tidak dapat memiliki input kedua ditransformasikan. Apakah itu masuk akal?
Stewie Griffin
Ya, terima kasih telah mengklarifikasi. Satu pertanyaan terakhir: Bisakah saya juga mengambil array karakter 2D sebagai input dan mengembalikan array string 2D?
Dennis
@ Dennis, saya menulis: "Kedua matriks harus dimasukkan pada format yang sama." Saya lupa menyebutkan matriks keluaran di sana, jadi saya akan tetap seperti ini. Input harus dalam format yang sama tetapi Anda mungkin memiliki format output yang berbeda. (Saya tidak terlalu suka solusi itu, tetapi saya tidak ingin mengubah hal-hal sekarang, saya pikir sudah ada satu jawaban yang memiliki format input dan output yang berbeda)
Stewie Griffin
Jika Anda maksud jawaban Ruby, saya memeriksa dan yang satu berfungsi dengan baik dengan string, bukan karakter.
Dennis

Jawaban:

9

Haskell , 62 61 byte

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

Cobalah online! Contoh penggunaan:

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

Saya menemukan cara untuk mendapatkan transposefungsi dalam satu byte lebih pendek daripada menggunakan impor:

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

Versi lama dengan impor: (62 byte)

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

Cobalah online!

Ini sangat mirip dengan jawaban saya untuk non-simbolis perkalian matriks : a!b=[sum.zipWith(*)r<$>transpose b|r<-a], mengganti perkalian (*)dengan penggabungan string (++)dan sumdengan unwordsyang merangkai daftar string dengan ruang di antara. Impor diperlukan untuk transposefungsi, jadi semuanya transposisi dari matriks kedua menggunakan setengah dari byte ...


Versi lama tanpa impor: (64 byte)

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

Cobalah online!

Dengan impor dan transposefungsi yang mengambil banyak byte, saya mencoba menyelesaikan tugas tanpa impor. Sejauh ini pendekatan ini ternyata dua byte lebih lama, tetapi mungkin lebih golf. Sunting: Pendekatan lain di atas sekarang mengalahkan impor!

Pemahaman daftar [s:t|_:s:t<-b]mendapatkan ekor yang tidak kosong dari daftar b, menggunakan hanya [t|_:t<-b]untuk mendapatkan ekor akan menjadi 4 byte lebih pendek (bahkan mengalahkan versi impor) tetapi menambahkan baris kosong seperti ["","",""]ke matriks yang saya kira tidak diperbolehkan.

Laikoni
sumber
6

Mathematica, 36 byte

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

Inneradalah generalisasi dari Mathematica Dot(yaitu produk matriks / vektor biasa). Ini generalisasi produk titik dengan membiarkan Anda memberikan dua fungsi fdan g, yang akan digunakan sebagai pengganti perkalian dan penambahan yang biasa, masing-masing. Kami mengganti perkalian dengan #<>#2&(yang menggabungkan dua karakter menjadi string tunggal) dan tambahan dengan StringRiffle@*List, yang pertama membungkus semua puncak dalam daftar, dan kemudian StringRifflebergabung bersama-sama dengan spasi.

Seseorang bisa berpotensi menggunakan Dotoperator .dan kemudian mentransformasikan hasilnya, tetapi masalahnya adalah hal-hal seperti "a"*"a"akan segera ditransformasikan menjadi "a"^2(sama dengan jumlah), yang akan menjengkelkan jika harus dipisahkan lagi.

Martin Ender
sumber
6

Ruby, 61 byte

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

Contoh dijalankan:

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
}}}
Gagang pintu
sumber
4

Clojure, 53 byte

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

Berjalan dengan argumen [["a" "b"]["c" "e"]]dan [["f" "g"]["h" "i"]]kembali ((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei"))). Ini sebenarnya lebih pendek dari versi numerik .

NikoNyrh
sumber
3

Dyalog APL , 10 byte

Mengambil matriks karakter sebagai argumen kiri dan kanan. Mengembalikan matriks daftar karakter. (APL mewakili string sebagai daftar karakter.)

{∊⍺' '⍵}.,

TryAPL online!

Produk dalam normal ada di APL +.×, tetapi penambahan dan perkalian dapat berupa fungsi apa pun, khususnya:

Penambahan telah digantikan oleh
{ fungsi anonim:  daftar
 rata yang
⍺ ' ' ⍵terdiri dari argumen kiri, spasi, dan argumen kanan
}

Perkalian telah digantikan oleh penggabungan, ,

Adám
sumber
2

Jelly , 7 byte

Z;"þK€€

Ini adalah tautan diadik yang menggunakan B dan A sebagai argumen (dalam urutan itu) dan mengembalikan AB . Input dan output dalam bentuk array string 2D, yang sebenarnya adalah array karakter 3D. Byte lebih lanjut dapat disimpan dengan mengambil array karakter 2D sebagai input Saya tidak yakin apakah itu diizinkan.

Cobalah online!

Agak sulit untuk menentukan apa yang dilakukan Jelly di balik tudung ketika dawai terlibat, karena ia banyak melakukan percat sebelum dicetak. Ini adalah bagaimana Jelly mewakili input dan output secara internal.

Bagaimana itu bekerja

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.
Dennis
sumber
2

Prolog,> 256 Bytes

Saya menggunakan {_ | _} yang merupakan findall / 3, _ [_, _] yang merupakan beberapa arg / 3, dan jumlah (_) yang merupakan agregat. Mereka semua dapat digunakan di dalam adalah / 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) }.

Bersama dengan definisi tambahan untuk predikat yang disebutkan di atas dan non-standar adalah / 2 yang dapat mengembalikan lebih dari angka, pasti> 256 byte.

Nomor Transfinit
sumber
1

JavaScript (ES6), 65 byte

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

Mengambil input sebagai dua array karakter 2D dan mengembalikan array string 2D. Tambahkan 10 byte untuk mendukung input sebagai dua array string 1D.

Neil
sumber
1

Pyth, 14 byte

clQmj;sMCd*QCE

Sebuah program yang mengambil input dari dua daftar karakter dua dimensi yang dipisahkan oleh baris baru dan mencetak daftar string dua dimensi.

Suite uji

Bagaimana itu bekerja

[Penjelasan datang nanti]

TheBikingViking
sumber
1

Pip , 17 byte

{Y Zb{a._JsMy}Ma}

Ini adalah fungsi yang mengambil dua daftar string (karakter tunggal) bersarang dan mengembalikan daftar string yang bersarang. Cobalah online! (dengan dua kasus uji).

Penjelasan

Argumen ke {}fungsi -delimited ditugaskan ke variabel lokal auntuk e. Argumen pertama dari fungsi lambda diwakili oleh _.

{               }  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
DLosc
sumber