การคูณเมทริกซ์สัญลักษณ์


26

มีหลายวิธีในการอธิบายการคูณเมทริกซ์ ฉันจะยึดติดกับร่างเดียวเพราะฉันเชื่อว่าคนส่วนใหญ่ที่นี่คุ้นเคยกับมัน (และตัวเลขนั้นอธิบายได้ดีมาก) หากท่านต้องการข้อมูลรายละเอียดเพิ่มเติมผมขอแนะนำให้คุณไปที่วิกิพีเดียบทความหรือคำอธิบายในWolframMathWorld

คำอธิบายง่ายๆ:

สมมติว่าคุณมีเมทริกซ์สองตัวคือAและBโดยที่Aคือ 3-by-2 และBคือ 2-by-3 หากคุณทำการคูณเมทริกซ์เหล่านี้กับเมทริกซ์ABหรือBAคุณจะได้ผลลัพธ์ด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่

ท้าทาย:

ใช้การคูณเมทริกซ์สัญลักษณ์ในภาษาของคุณ คุณจะต้องใช้เมทริกซ์สองตัวเป็นอินพุตซึ่งแต่ละองค์ประกอบในเมทริกซ์จะถูกแทนด้วยอักขระ ASCII ที่ไม่ใช่ whitespace (รหัสคะแนน 33-126) คุณต้องเอาท์พุทผลิตภัณฑ์ของเมทริกซ์เหล่านี้

กฎเกี่ยวกับผลลัพธ์:

ผลิตภัณฑ์ของสองรายการจะต้องไม่มีสัญลักษณ์ใด ๆ ในระหว่าง มันabไม่ได้a*b, a·b, times(a,b)หรือสิ่งที่คล้ายกัน มันไม่ได้aaa^2

ผลรวมของเงื่อนไขควรมีช่องว่าง (รหัส ASCII จุด 32) ในระหว่าง มันa bไม่a+b, plus(a,b)หรือสิ่งที่คล้ายกัน

เหตุผลสำหรับกฎทั้งสองนี้คือ: อนุญาตให้ใช้อักขระที่ไม่ใช่ white space ทั้งหมดเป็นสัญลักษณ์ในเมทริกซ์ดังนั้นการใช้มันเป็นสัญลักษณ์ทางคณิตศาสตร์จะยุ่งเหยิง ดังนั้นสิ่งที่คุณตามปกติสามารถเขียนเป็นจะเป็นa*b+c*dab 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]

ฉันทราบว่านี่ช่วยให้รูปแบบจำนวนมากที่ดูยุ่งเหยิง แต่ความท้าทายนั้นเกี่ยวกับการคูณเมทริกซ์ไม่ใช่การจัดรูปแบบเอาต์พุต

กฎทั่วไป:

  • คุณอาจจะถือว่าอินพุตที่ถูกต้อง การคูณเมทริกซ์จะเป็นไปได้เสมอกับขนาดที่กำหนด
  • จะมีเพียงสองเมทริกซ์
  • คุณอาจคิดว่าเมทริกซ์นั้นไม่ว่างเปล่า
  • ฟังก์ชั่นในตัวได้รับการยอมรับ (แต่อาจยุ่งยากเล็กน้อยเนื่องจากข้อกำหนดการจัดรูปแบบ)
  • แน่นอนคุณอาจใช้อักขระเลี่ยงในอินพุตถ้าจำเป็น ( \'แทน')
  • ใด ๆinput และ output วิธีมาตรฐานคือตกลง

กรณีทดสอบ:

เมทริกซ์อินพุตสองรายการถูกแสดงด้วยบรรทัดว่างในระหว่าง 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เป็น: คุณควรหลีกเลี่ยงรูปแบบอินพุต / เอาท์พุตที่ยุ่งยากดังนั้นฉันต้องการทราบว่ารูปแบบอินพุตและเอาต์พุตมีความยืดหยุ่นมาก ความจริงที่ว่าคุณไม่สามารถใช้งานได้*และ+สำหรับผลิตภัณฑ์และผลรวมอาจทำให้ยากต่อการใช้งานบิวท์อินเรียบง่าย แต่ฉันไม่คิดว่าสิ่งที่เป็นลบ


สำหรับฟังก์ชั่นการรับสาย 2 อาร์เรย์สองชุดและคืนค่าอาร์เรย์ 2D ที่ยอมรับได้หรือไม่
Dennis

ใช่ไม่มีปัญหา. แต่ขนาดต้องตรงกันคุณไม่สามารถย้ายอินพุตที่สองได้ มันสมเหตุสมผลไหม
Stewie Griffin

มันขอบคุณสำหรับการชี้แจง คำถามสุดท้ายหนึ่งข้อ: ฉันสามารถนำตัวละคร 2D เป็นตัวป้อนข้อมูลและส่งกลับอาร์เรย์แบบสตริงได้หรือไม่
Dennis

@Dennis ฉันเขียนว่า: "ทั้งเมทริกซ์ต้องถูกป้อนในรูปแบบเดียวกัน" ฉันลืมที่จะพูดถึงเมทริกซ์เอาต์พุตที่นั่นดังนั้นฉันจะเก็บมันไว้อย่างนี้ อินพุตต้องอยู่ในรูปแบบเดียวกัน แต่คุณอาจมีรูปแบบเอาต์พุตอื่น (ฉันไม่ชอบโซลูชันนั้น แต่ฉันไม่ต้องการเปลี่ยนสิ่งตอนนี้ฉันคิดว่ามีคำตอบหนึ่งคำตอบที่มีรูปแบบอินพุตและเอาต์พุตที่แตกต่างกัน)
Stewie Griffin

ถ้าคุณหมายถึงคำตอบ Ruby ฉันตรวจสอบและใช้งานได้ดีกับสตริงแทนที่จะเป็นตัวอักษร
Dennis

คำตอบ:


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ฟังก์ชั่นที่ใช้ไบต์มากฉันพยายามแก้ไขงานโดยไม่นำเข้า จนถึงตอนนี้วิธีการนี้กลับกลายเป็นสองไบต์นานกว่า แต่มันอาจจะเล่นกอล์ฟได้มากกว่า แก้ไข: วิธีการอื่นที่ด้านบนตอนนี้เต้นนำเข้า!

list comprehension [s:t|_:s:t<-b]รับ tail ที่ไม่ว่างเปล่าของรายการbโดยใช้[t|_:t<-b]เพื่อให้ tails สั้นลง 4 ไบต์ (แม้จะตีเวอร์ชันการนำเข้า) แต่จะผนวกแถวว่างเหมือนกับ["","",""]matrix ซึ่งฉันคิดว่าไม่ได้รับอนุญาต


6

Mathematica ขนาด 36 ไบต์

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

Innerเป็นลักษณะทั่วไปของ Mathematica Dot(เช่นผลิตภัณฑ์เมทริกซ์ / เวกเตอร์ทั่วไป) มันทำให้ผลิตภัณฑ์ดอททั่วไปโดยให้คุณจัดเตรียมสองฟังก์ชันfและgซึ่งจะใช้แทนการคูณและการบวกตามปกติ เรากำลังแทนที่การคูณด้วย#<>#2&(ซึ่งรวมอักขระทั้งสองตัวเป็นสตริงเดียว) และการเพิ่มด้วยStringRiffle@*Listซึ่งจะสรุปการสรุปทั้งหมดในรายการก่อนแล้วจึงStringRiffleรวมเข้าด้วยกันด้วยช่องว่าง

อาจมีคนใช้Dotโอเปอเรเตอร์.แล้วแปลงผลลัพธ์ แต่ปัญหาคือสิ่งต่าง ๆ"a"*"a"จะเปลี่ยนเป็นทันที"a"^2(เหมือนกันสำหรับผลรวม) ซึ่งน่ารำคาญที่จะเลือกอีกครั้ง


6

Ruby, 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

Dyalog APL ขนาด 10 ไบต์

ใช้เมทริกซ์ของอักขระเป็นอาร์กิวเมนต์ซ้ายและขวา ส่งคืนเมทริกซ์ของรายการอักขระ (APL แสดงสตริงเป็นรายการของอักขระ)

{∊⍺' '⍵}.,

ลองใช้ออนไลน์!

ผลิตภัณฑ์ภายในปกติอยู่ใน APL +.×แต่การเพิ่มและการคูณสามารถเป็นฟังก์ชันใด ๆ โดยเฉพาะอย่างยิ่ง:

นอกจากนี้ยังถูกแทนที่ด้วย
{ ฟังก์ชันที่ไม่ระบุชื่อ:  รายการแบบ
 แบน
⍺ ' ' ⍵ประกอบด้วยอาร์กิวเมนต์ซ้ายช่องว่างและอาร์กิวเมนต์ที่ถูกต้อง
}

การคูณถูกแทนที่ด้วยการต่อข้อมูล ,


2

เยลลี่ขนาด 7 ไบต์

Z;"þK€€

นี้เป็นลิงค์ dyadic ที่ใช้Bและเป็นข้อโต้แย้ง (ตามลำดับ) และผลตอบแทนAB อินพุตและเอาต์พุตอยู่ในรูปแบบของอาร์เรย์ 2 มิติของสตริงซึ่งจริงๆแล้วเป็นอาร์เรย์ 3 มิติของอักขระ ไบต์เพิ่มเติมสามารถบันทึกได้โดยการใช้อาร์เรย์ของตัวอักขระ 2 มิติเป็นอินพุต ฉันไม่แน่ใจว่าได้รับอนุญาตหรือไม่

ลองออนไลน์!

เป็นการยากที่จะตัดสินว่า 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

Prolog,> 256 Bytes

ฉันกำลังใช้ {_ | _} ซึ่งเป็น findall / 3, _ [_, _] ซึ่งเป็นอาร์กิวเมนต์บางอย่าง / 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` `))

รับอินพุตเป็นสองอาร์เรย์ของตัวละครและส่งกลับอาร์เรย์แบบสองมิติของสตริง เพิ่ม 10 ไบต์เพื่อสนับสนุนอินพุตเป็นสองอาร์เรย์ 1D ของสตริง


1

Pyth, 14 ไบต์

clQmj;sMCd*QCE

โปรแกรมที่รับอินพุตของรายการอักขระสองมิติที่คั่นด้วยบรรทัดใหม่สองรายการและพิมพ์รายการสตริงสองมิติ

ชุดทดสอบ

มันทำงานอย่างไร

[คำอธิบายมาในภายหลัง]


1

Pip , 17 ไบต์

{Y Zb{a._JsMy}Ma}

นี่คือฟังก์ชั่นที่รับสองรายการซ้อนกันของสตริง (อักขระเดียว) และส่งกลับรายการซ้อนของสตริง ลองออนไลน์! (มีสองกรณีทดสอบ)

คำอธิบาย

มีปากเสียงกับ{}ฟังก์ชั่น -delimited ได้รับมอบหมายให้ตัวแปรท้องถิ่นเพื่อ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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.