คำนวณ Matrix-Vector


14

รับอาร์เรย์จำนวนเต็มอย่างน้อยสององค์ประกอบเอาท์พุทMatrix-Vector (กำหนดไว้ด้านล่าง) ของอาร์เรย์

ในการคำนวณMatrix-Vector ขั้นแรกให้หมุนnอาร์เรย์ขนาดอินพุตเพื่อสร้างเมทริกซ์ขนาดn x nโดยองค์ประกอบแรกของอาร์เรย์จะตามด้วยเส้นทแยงมุมหลัก นี่เป็นส่วนเมทริกซ์ สำหรับเวกเตอร์ให้พลิกอาร์เรย์อินพุตในแนวตั้ง จากนั้นทำการคูณเมทริกซ์ปกติ ผลลัพธ์ของเวกเตอร์เป็นผลลัพธ์

ตัวอย่างเช่น,

a = [1, 2, 3]

ก่อนอื่นให้หมุนอาร์เรย์สองครั้งไปทางขวาเพื่อรับ[3, 1, 2]และ[2, 3, 1]จากนั้นจัดเรียงให้เป็น3x3เมทริกซ์

[[1, 2, 3]
 [3, 1, 2]
 [2, 3, 1]]

จากนั้นพลิกอาร์เรย์ในแนวตั้งเพื่อสร้างเวกเตอร์

[[1, 2, 3]    [[1]
 [3, 1, 2]  x  [2]
 [2, 3, 1]]    [3]]

ดำเนินการคูณเมทริกซ์ปกติ

[[1, 2, 3]    [[1]    [[1+4+9]    [[14]
 [3, 1, 2]  x  [2]  =  [3+2+6]  =  [11]
 [2, 3, 1]]    [3]]    [2+6+3]]    [11]]

และผลลัพธ์คือ[14, 11, 11]หรือ[[14], [11], [11]] (คุณเลือกได้ว่าจะแบนหรือไม่)

ตัวอย่างที่ 2

a = [2, 5, 8, 3]

[[2, 5, 8, 3]    [[2]    [[4+25+64+9]     [[102]
 [3, 2, 5, 8]  x  [5]  =  [6+10+40+24]  =  [80]
 [8, 3, 2, 5]     [8]     [16+15+16+15]    [62]
 [5, 8, 3, 2]]    [3]]    [10+40+24+6]]    [80]]

[102, 80, 62, 80]

กฎระเบียบ

  • อินพุตและเอาต์พุตสามารถสันนิษฐานว่าเหมาะสมกับชนิดจำนวนเต็มดั้งเดิมของภาษาของคุณ
  • สามารถกำหนดอินพุตและเอาต์พุตในรูปแบบที่สะดวกในรูปแบบที่สะดวกใด
  • ยอมรับได้ทั้งโปรแกรมหรือฟังก์ชั่น หากฟังก์ชั่นคุณสามารถส่งคืนผลลัพธ์มากกว่าการพิมพ์
  • หากเป็นไปได้โปรดรวมลิงค์ไปยังสภาพแวดล้อมการทดสอบออนไลน์เพื่อให้ผู้อื่นสามารถลองใช้รหัสของคุณได้!
  • ช่องโหว่มาตรฐานเป็นสิ่งต้องห้าม
  • นี่คือเพื่อให้ใช้กฎการเล่นกอล์ฟตามปกติทั้งหมดและรหัสที่สั้นที่สุด (เป็นไบต์) ชนะ

คำตอบ:


8

เยลลี่ 5 ไบต์

ṙJṚæ.

ลองออนไลน์!

คำอธิบาย

ประการแรก:

ที่อยู่แถวเวกเตอร์และเป็นคอลัมน์vkxเวกเตอร์

นี่แสดงให้เห็นว่าการคูณเมทริกซ์เป็นเพียงจุดระหว่างผลิตภัณฑ์และแถว

จากนั้น v1เป็นจริงvหมุน0ไปทางขวาและมีการหมุนvkvk-1ไปทางขวา ฯลฯ

จากอีกมุมหนึ่ง v1จะvหมุนnไปทางซ้ายและมีการหมุนvnv1ไปทางซ้าย ฯลฯ

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

ṙJṚæ.   input: z (a list of length n)
ṙJ      [rot(z,1), rot(z,2), ..., rot(z,n)] (to the left)
  Ṛ     [rot(z,n), ..., rot(z,2), rot(z,1)]
   æ.   [rot(z,n).z , ..., rot(z,2).z , rot(z,1).z] (dot product)




3

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

LḶN⁸ṙæ×W€

ลองออนไลน์!

ฟังก์ชั่นที่ส่งกลับอาร์เรย์แนวตั้ง ในฐานะที่เป็นโปรแกรมเต็มรูปแบบจะปรากฏราวกับว่ามันส่งกลับอาร์เรย์แนวนอน หากต้องการคืนอาร์เรย์ในแนวนอนคุณจะต้องทำLḶN⁸ṙ×⁸S€แทน



2

Haskell , 49 ไบต์

f v=sum.zipWith(*)v.fst<$>zip(iterate tail$v++v)v

ลองออนไลน์!

สำหรับการป้อนข้อมูล v=[1,2]

  • iterate tail$v++v ให้ผลผลิตรายการ [[1,2,1,2],[2,1,2],[1,2],[2],[],...]
  • fst<$>zip l vเป็นเช่นเดียวกับtake(length v)lและผลผลิต[[1,2,1,2],[2,1,2]]
  • sum.zipWith(*)v ถูกแมปในแต่ละองค์ประกอบและเพื่อให้ผลิตภัณฑ์แถวเวกเตอร์เมทริกซ์

ฉลาดกว่าคำตอบของฉัน! ฉันชอบfst<$>zip l vมาก
jferard

2

R , 66 62 ไบต์

sapply(length(n<-scan()):1,function(i)c(n[-(1:i)],n[1:i])%*%n)

ลองออนไลน์!


การใช้Map(function(i)c(n[-(1:i)],n[1:i])%*%n,length(n<-scan()):1)สั้นลง 3 ไบต์ มันแค่คืนค่ารายการเมทริกซ์
Giuseppe

และ a สำหรับลูปfor(i in seq(n<-scan()))F=c(c(n[-(1:i)],n[1:i])%*%n,F);F[1:i]คือ 61 ไบต์โดยไม่ส่งคืนรูปแบบเอาต์พุตแปลก ๆ
Giuseppe

2

Mathematica, 35 ไบต์

Most@FoldList[RotateRight,#,1^#].#&

ลองออนไลน์!

-9 ไบต์จาก @Not a tree


2
มันสั้นเพื่อใช้คูณเมทริกซ์ Mathematica ของตัวเองMost@FoldList[RotateRight,#,1^#].#&มากกว่าที่จะสร้างมันด้วยตัวคุณเอง: (แต่ใช้กลอุบายที่ดีFoldแทนNest!)
ไม่ใช่ต้นไม้




1

J , 14 ไบต์

+/ .*~#\.1&|.]

ลองออนไลน์!

คำอธิบาย

+/ .*~#\.1&|.]  Input: array M
      #\.       Length of each suffix, forms the range [len(M), ..., 2, 1]
             ]  Identity, get M
         1&|.   For each 'x' in the suffix lengths, rotate left M  by 'x'
+/ .*~          Dot product with M

มันค่อนข้างดี หนึ่งคำถาม. เมื่อคุณทำ1&|.ไม่ได้คุณพันธะ1ที่จะ|.สร้าง monad หรือไม่? แต่คุณใช้ monad นั้นกับ arg ซ้ายและขวาโดยที่ left left จะเป็นตัวกำหนดจำนวนครั้งที่ใช้ เกิดอะไรขึ้นที่นี่?
โยนาห์

@Jonah &มันเป็นรูปแบบพิเศษสำหรับ เมื่อใช้เป็นมันมีประสิทธิภาพu n&f v (n&f)^:u vดูที่ด้านล่างของพันธะเพื่อดูการแยกวิเคราะห์เพิ่มเติม
ระยะทาง

อา TIL เป็นสิ่งที่คุณใช้บ่อยไหม
โยนาห์

@Jonah มันมีประโยชน์สำหรับการเล่นกอล์ฟในหลาย ๆ กรณี ในกรณีนี้มันสามารถทำได้ในจำนวนไบต์ที่เท่ากันโดยใช้อันดับ#\.|."{]แต่ฉันโพสต์สั้นที่สุดที่ฉันมาก่อนก่อนลองทางเลือก
ระยะทาง

1

APL, 17 ไบต์

(↑¯1⌽(⍳≢)⌽¨⊂)+.×⍪

คำอธิบาย:

(↑¯1⌽(⍳≢)⌽¨⊂)+.×⍪

 ↑                      matrix format of
  ¯1⌽                   right rotate by 1 of
     (⍳≢)               the 1..[length N]
         ⌽¨             rotations of
           ⊂            the enclosed input
             +.×        inner product with
                ⍪       1-column matrix of input



1

Husk , 11 ไบต์

mΣ§‡*´ṀKoṫ¢

ลองออนไลน์!

คำอธิบาย

mΣ§‡*´ṀKoṫ¢  Implicit input, e.g. [1,2,3]
          ¢  Cycle: [1,2,3,1,2,3,...
        oṫ   Tails: [[1,2,3,1,2,3...],[2,3,1,2,3...],[3,1,2,3...]...
     ´ṀK     Replace each element of input with input: [[1,2,3],[1,2,3],[1,2,3]]
   ‡*        Vectorized multiplication (truncated with respect to shortest list)
  §          applied to the last two results: [[1,4,9],[2,6,3],[3,2,6]]
mΣ           Sum of each row: [14,11,11]

1

ระดับแปดเสียง - 67 48 ไบต์

ขอบคุณ Luis Mendo สำหรับการโกนรหัสนี้ลง 19 ไบต์!

หมายเหตุ: รหัสนี้สามารถทำงานได้ในระดับแปดเสียงเท่านั้น MATLAB ไม่สนับสนุนการแสดงออกในฟังก์ชั่นที่สามารถสร้างตัวแปรในขณะที่การประเมินการแสดงออกที่สร้างพวกเขาพร้อมกัน

n=numel(a=input(''));a(mod((x=0:n-1)-x',n)+1)*a'

รหัสต้นฉบับใน MATLAB สามารถพบได้ที่นี่ แต่สามารถเรียกใช้ใน MATLAB รุ่นใดก็ได้ รหัสนี้คือ 67 ไบต์:

a=input('');n=numel(a)-1;a(mod(bsxfun(@minus,0:n,(0:n)'),n+1)+1)*a'

คำอธิบาย

  1. a=input('');- รับเวกเตอร์ (แถว) จากผู้ใช้ผ่านอินพุตมาตรฐาน คุณต้องป้อนเวกเตอร์ในรูปแบบอ็อกเทฟ (เช่น[1,2,3] )
  2. n=numel(...); - รับจำนวนองค์ประกอบทั้งหมดในอินพุตเวกเตอร์
  3. x=0:n-1- สร้างเวกเตอร์แถวที่เพิ่มจาก0ขึ้นเป็นn-1ขั้นตอนที่ 1
  4. (x=0:n-1)-x'- ทำการแพร่ภาพเพื่อให้เรามีn x nเมทริกซ์เพื่อให้แต่ละแถวiเป็นองค์ประกอบตั้งแต่ 0 ถึงn-1กับแต่ละองค์ประกอบในแถวiลบด้วยiหักออกจาก
  5. mod(..., n)+1- ตรวจสอบให้แน่ใจว่าค่าใด ๆ ที่เป็นค่าลบล้อมรอบเพื่อnให้แต่ละแถวiมีเวกเตอร์จาก 0 ถึงเปลี่ยนn-1 เป็นวงกลมเป็นซ้ายโดยiองค์ประกอบ เราเพิ่ม 1 เนื่องจาก MATLAB / Octave เริ่มทำดัชนีเวกเตอร์หรือเมทริกซ์ด้วย 1
  6. a(...)- สร้างn x nเมทริกซ์โดยใช้ (4) เราเข้าถึงดัชนีที่ถูกต้องของเวกเตอร์อินพุตที่กำหนดโดยแต่ละค่าจาก (4) จึงบรรลุเมทริกซ์ที่เราต้องการ
  7. (...)*a'- ทำการคูณเมทริกซ์เวกเตอร์โดยการแปลง / พลิกaเป็นเวกเตอร์คอลัมน์ก่อนทำการคูณ

ตัวอย่างรัน

>> n=numel(a=input(''));a(mod((x=0:n-1)-x',n)+1)*a'
[1,2,3]

ans =

         14.00
         11.00
         11.00

>> n=numel(a=input(''));a(mod((x=0:n-1)-x',n)+1)*a'
[2,5,8,3]

ans =

        102.00
         80.00
         62.00
         80.00

ลองออนไลน์!


bsxfunคุณสามารถใช้การขยายตัวโดยปริยายแทน การกำหนดnโดยไม่ต้อง-1บันทึกไม่กี่ไบต์เช่นกัน และถ้าคุณ จำกัด เพื่อคู่คุณสามารถกำหนดaและ0:nตัวแปรในการบินและประหยัดมากขึ้นบาง นอกจากนี้มาที่นี่บ่อยขึ้น !! :-D
Luis Mendo

@ LuisMendo อ่าใช่ ฉันลืมว่าอ็อฟเทฟได้รองรับการขยายโดยนัยแล้ว นอกจากนี้การบันทึกตัวแปรภายในinputฟังก์ชั่นก็เป็นเทคนิคที่ยอดเยี่ยม ฉันไม่คิดว่ามันจะรองรับได้ ฉันเห็นเฉพาะใน C หรือ C ++ จากประสบการณ์ของฉันเอง ขอบคุณ!
rayryeng - Reinstate Monica

1
@LuisMendo ฉันจะทำการเปลี่ยนแปลงที่คุณแนะนำเป็นการแก้ไขในไม่ช้า ฉันยุ่ง แต่ฉันไม่ได้ให้ความสำคัญกับเรื่องนี้เนื่องจากการเข้าร่วมนี้จะไม่มีทางชนะนับไบต์
rayryeng - Reinstate Monica

@LuisMendo เปลี่ยนแปลงแล้ว ขอบคุณมาก :) ต้องเข้าใจรหัสในขณะที่ฉันกำลังเปลี่ยนคำอธิบายข้างต้น
rayryeng - Reinstate Monica

ดีใจที่ฉันสามารถช่วย :-)
Luis Mendo

0

Javascript 79 ไบต์

รับอาร์เรย์อินพุตและเอาต์พุตอาร์เรย์ของเมทริกซ์เวกเตอร์

a=>(b=[...a],a.map(x=>([...b].reduce((m,n,i)=>m+=n*a[i],0,b.push(b.shift())))))

คำอธิบาย

a=>(
    b=[...a],                    // copy the input into b
    a.map(x=>(                   // transform a into a new array
        [...b].reduce(           // copy b into a new array and reduce
            (m,n,i)=>m+=n*a[i],  // memo += the element in the array * the ith
                                 // element in a
            0,                   // start memo at 0
            b.push(b.shift())    // shift the first element in b to the end
                                 // not used by reduce, but performing this op
                                 // here saves a few bytes
        )
    ))
)

0

Clojure, 80 ไบต์

#(map(fn[_ c](apply +(map * c %)))%(iterate(fn[c](into[(last c)](butlast c)))%))

iterateผลิตลำดับอนันต์ แต่แทนที่จะใช้(take (count %) (iterate ...))ที่จะหยุดมันผมใช้เป็นอาร์กิวเมนต์พิเศษเพื่อ%map


0

Perl 5 , 65 + 1 (-a) = 66 ไบต์

@o=@F;for(@o){$r=0;$r+=$_*$F[$i++%@F]for@o;say$r;unshift@F,pop@F}

ลองออนไลน์!

นำเวกเตอร์อินพุตเป็นตัวเลขคั่นด้วยช่องว่าง เอาต์พุตบรรทัดที่แยกตัวเลขที่แสดงถึงเวกเตอร์ผลลัพธ์



0

Lisp ทั่วไป, 78 ไบต์

(lambda(x)(loop as i on(append x x)as y in x collect(reduce'+(mapcar'* i x))))

ลองออนไลน์!

สองครั้งที่อาร์เรย์ (ในกรณีนี้คือรายการ Lisp) และวนซ้ำรายการย่อยด้วยi(ใช้x, ผ่านy, เพื่อหยุดการทำซ้ำ) จากนั้นคำนวณองค์ประกอบถัดไปของผลลัพธ์โดยการรวมผลลัพธ์ของการคูณแต่ละองค์ประกอบของxกับแต่ละองค์ประกอบของi(หยุดอีกครั้งเมื่อรายการที่สั้นกว่าถูกยกเลิก)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.