การแยกแบบไม่ต่อเนื่องหรือการคูณพหุนาม


19

เนื่องจากรายการจำนวนเต็มสองรายการที่ไม่ว่างเปล่าการส่งของคุณควรคำนวณและส่งกลับค่าการแยกแบบไม่ต่อเนื่องของทั้งสองรายการ ที่น่าสนใจถ้าคุณพิจารณาองค์ประกอบของรายการเป็นค่าสัมประสิทธิ์ของพหุนาม, การบิดของทั้งสองรายการแสดงถึงค่าสัมประสิทธิ์ของผลิตภัณฑ์ของพหุนามทั้งสอง

คำนิยาม

รับรายการA=[a(0),a(1),a(2),...,a(n)]และB=[b(0),b(1),b(2),...,b(m)](การตั้งค่าa(k)=0 for k<0 and k>nและb(k)=0 for k<0 and k>m) จากนั้นสังวัตนาของทั้งสองจะถูกกำหนดเป็นA*B=[c(0),c(1),...,c(m+n)]ที่ไหนc(k) = sum [ a(x)*b(y) for all integers x y such that x+y=k]

กฎระเบียบ

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

ตัวอย่าง

[1,1]*[1] = [1,1]
[1,1]*[1,1] = [1,2,1]
[1,1]*[1,2,1] = [1,3,3,1]
[1,1]*[1,3,3,1] = [1,4,6,4,1]
[1,1]*[1,4,6,4,1] = [1,5,10,10,5,1]

[1,-1]*[1,1,1,1,1] = [1,0,0,0,0,-1]
[80085,1337]*[-24319,406] = [-1947587115,7,542822]

3
สเปคบ่งบอกว่าอินพุตของความยาว n, m ควรสร้างเอาท์พุทความยาว n + m - 1 แต่สิ่งนี้ไม่ได้เก็บไว้ในกรณีทดสอบของคุณ[1,1]*[] = []และไม่สามารถจับ[]*[] = ?ได้ Convolution ไม่ได้ถูกนิยามไว้อย่างดีในรายการที่ว่างเปล่า ฉันคิดว่าคุณควรรับประกันว่ารายการอินพุตนั้นไม่ว่างเปล่า
Anders Kaseorg

1
@AndersKaseorg คุณพูดถูกฉันจะเปลี่ยนมัน
ข้อบกพร่อง

เกี่ยวข้อง: codegolf.stackexchange.com/q/67289/29325
sergiol

คำตอบ:


14

J, 10 8 ไบต์

[:+//.*/

การใช้งาน:

ppc =: [:+//.*/    NB. polynomial product coefficients 
80085 1337 ppc _24319 406
_1947587115 7 542822

คำอธิบาย: โปรแกรมใช้เวลาสองรายการสร้างตารางการคูณจากนั้นเพิ่มตัวเลขลงบนเส้นทแยงมุมบวก


วิธีการที่ฉลาดมาก!
Luis Mendo

คุณไม่จำเป็นต้องนับวงเล็บ การแสดงออกภายในพวกเขาประเมินเป็นกริยาเงียบซึ่งสามารถกำหนดให้กับตัวแปร
Dennis

ตัวอย่างที่ดีของคำวิเศษณ์!
ไมล์

6

MATL , 19 ไบต์

PiYdt"TF2&YStpsw]xx

ลองออนไลน์!

คำอธิบาย

สิ่งนี้จะสร้างเมทริกซ์บล็อกแนวทแยงพร้อมทั้งสองอินพุตโดยย้อนกลับเป็นครั้งแรก ตัวอย่างเช่นกับปัจจัยการผลิต[1 4 3 5], [1 3 2]เมทริกซ์คือ

[ 5 3 4 1 0 0 0
  0 0 0 0 1 3 2 ]

การเข้าร่วมแต่ละครั้งจะได้มาจากการเลื่อนตำแหน่งแรกไปทางขวาหนึ่งตำแหน่งคำนวณผลิตภัณฑ์ของแต่ละคอลัมน์และรวมผลลัพธ์ทั้งหมด

โดยหลักการแล้วการเลื่อนควรทำด้วยศูนย์จากด้านซ้าย เท่ากันสามารถใช้การเลื่อนแบบวนได้เนื่องจากเมทริกซ์มีค่าศูนย์ที่รายการที่เหมาะสม

ตัวอย่างเช่นผลลัพธ์แรกได้มาจากเมทริกซ์ที่เลื่อน

[ 0 5 3 4 1 0 0
  0 0 0 0 1 3 2 ]

และเป็นเช่น1*1 == 1นั้น ที่สองได้มาจาก

[ 0 0 5 3 4 1 0
  0 0 0 0 1 3 2 ]

และเป็นเช่น4*1+1*3 == 7นี้ ฯลฯ สิ่งนี้จะต้องทำm+n-1ครั้งที่ไหนmและnมีความยาว รหัสใช้การวนm+nซ้ำพร้อมการวนซ้ำ (ซึ่งบันทึกบางไบต์) และทิ้งผลลัพธ์สุดท้าย

P          % Take first input (numeric vactor) implicitly and reverse it
i          % Take second input (numeric vactor) 
Yd         % Build diagonal matrix with the two vectors
t          % Duplicate
"          % For each column of the matrix
  TF2&YS   %   Circularly shift first row 1 step to the right
  t        %   Duplicate
  p        %   Product of each column
  s        %   Sum all those products
  w        %   Swap top two elements in stack. The shifted matrix is left on top
]          % End for
xx         % Delete matrix and last result. Implicitly display

4

Haskell, 55 49 ไบต์

(a:b)#c=zipWith(+)(0:b#c)$map(a*)c++[]#b
_#c=0<$c

#กำหนดดำเนินการ


1
ผมคิดว่าช่องว่างภายใน[0,0..]สามารถที่จะให้ตรงกับความยาวที่ต้องการช่วยให้กรณีฐานที่ว่างเปล่า(0<$b) _#b=0<$b
xnor

@xnor แน่นอนว่าจะช่วยประหยัด 6 ไบต์
Anders Kaseorg

ตอนนี้ในที่สุดฉันก็เข้าใจคำตอบของคุณฉันต้องบอกว่ามันช่างฉลาดจริงๆ! ฉันประทับใจ!
ข้อบกพร่อง

3

Matlab / Octave ขนาด 41 ไบต์

@(p,q)poly([roots(p);roots(q)])*p(1)*q(1)

สิ่งนี้นิยามฟังก์ชันที่ไม่ระบุชื่อ ansเรียกว่ากำหนดให้ตัวแปรหรือการใช้งาน

ลองได้ที่นี่

คำอธิบาย

วิธีนี้ใช้ประโยชน์จากข้อเท็จจริงที่ว่า

  • ราก (อาจซ้ำ) แสดงลักษณะของพหุนามถึงค่าสัมประสิทธิ์นำของมัน
  • ผลคูณของพหุนามสองอันมีรากของทั้งสอง

รหัสคำนวณรากของพหุนามทั้งสอง (ฟังก์ชั่นroots) และต่อเข้ากับอาเรย์คอลัมน์ จากนั้นจะได้รับค่าสัมประสิทธิ์ของพหุนามผลิตภัณฑ์ที่มีชั้นนำ1(ฟังก์ชั่นpoly) ในที่สุดผลลัพธ์จะถูกคูณด้วยสัมประสิทธิ์นำของพหุนามทั้งสอง


3

อ็อกเทฟ 48 ไบต์

@(p,q)ifft(fft([p q*0]).*fft([q p*0]))(1:end-1)

ลองได้ที่นี่

คำอธิบาย

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

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


Damnit ฉันยังคงห้าม fft แต่ทำได้ดีมาก!
ข้อบกพร่อง

@ flawr ใช่ฉันคิดว่าเราพูดถึงเรื่องนั้น ... ? :-P
Luis Mendo

2

05AB1E , 18 17 ไบต์

รหัส

0Ev²¹g<Å0«y*NFÁ}+

คำอธิบาย

ทฤษฎีที่อยู่เบื้องหลัง:

เพื่อหาบิดลองมาตัวอย่าง,[1, 2, 3] [3, 4, 5]เราวางค่าของอาร์เรย์แรกกลับหัวและในแนวตั้งเช่นนี้

3
2
1

ตอนนี้เราวางอาร์เรย์ที่สองเหมือนบันไดแล้วคูณด้วย:

3 ×       [3  4  5]
2 ×    [3  4  5]
1 × [3  4  5]

ส่งผลให้เป็น:

        9   12   15
    6   8   10
3   4   5

จากนั้นเราจะเพิ่มพวกเขาเข้าไปใน:

        9   12   15
    6   8   10
3   4   5       

3   10  22  22   15

[3, 10, 22, 22, 15]ดังนั้นบิดคือ

รหัสตัวเอง:

เราจะทำตามขั้นตอนนี้เป็นขั้นตอนโดยใช้[1, 2, 3], [3, 4, 5]เป็นกรณีทดสอบ

0Ev²¹g<Å0«y*NFÁ}+

เรากดก่อน0แล้วจึงEประเมินค่าอาร์เรย์แรก เรา map vมากกว่าแต่ละองค์ประกอบโดยใช้

ดังนั้นสำหรับแต่ละองค์ประกอบเราดันอาร์เรย์ที่สองด้วย²และจากนั้นความยาวของอาร์เรย์แรกที่ใช้¹gและลดค่านี้ลง 1 (กับ<) เราแปลงสิ่งนี้เป็นรายการศูนย์ด้วย(ความยาวอาร์เรย์ที่ 1 - 1)ศูนย์โดยใช้Å0และผนวกสิ่งนี้ลงในรายการของเรา ตอนนี้สแต็กของเราจะมีลักษณะเช่นนี้สำหรับรายการแรกในรายการอินพุต:

[3, 4, 5, 0, 0]

y*เราคูณอาร์เรย์นี้กับรายการในปัจจุบันทำได้ด้วย หลังจากนั้นเราจะผลักดันNซึ่งบ่งชี้ว่าดัชนีของรายการปัจจุบัน (ศูนย์จัดทำดัชนี) และหมุนอาร์เรย์ที่หลาย ๆ FÁ}ครั้งเพื่อให้ถูกต้องโดยใช้ สุดท้ายเราเพิ่มสิ่งนี้ในค่าเริ่มต้นของเรา ( 0) ดังนั้นสิ่งที่ทำโดยทั่วไปคือต่อไปนี้:

[0, 0, 9, 12, 15] +
[0, 6, 8, 10, 0] +
[3, 4, 5, 0, 0] =

[3, 10, 22, 22, 15]

ซึ่งจะถูกพิมพ์โดยนัยแล้ว ใช้การเข้ารหัสCP-1252 ลองออนไลน์! .


2

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

0;+
×'Ṛç/

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

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

×'Ṛç/  Main link. Arguments: p, q (lists)

×'     Spawned multiplication; multiply each item of p with each item of q.
  Ṛ    Reverse the rows of the result.
   ç/  Reduce the rows by the helper link.


0;+    Helper link. Arguments: p, q (lists)

0;     Prepend a 0 to p.
  +    Perform vectorized addition of the result and q.

อะไรเจลลี่ที่ยาวกว่าJ‽นั้นเป็นไปไม่ได้โดยนิยาม
อดัม

2

แกลบ , 5 ไบต์

mΣ∂Ṫ*

ลองออนไลน์!

บันทึก:เมื่อส่งรายการ zero-polynomial / empty คุณต้องระบุประเภท (เช่น[]:LN)!

คำอธิบาย

mΣ∂Ṫ*  -- implicit inputs xs ys, for example: [1,-1] [1,1]
   Ṫ*  -- compute the outer product xsᵀ·ys: [[1,1],[-1,-1]]
  ∂    -- diagonals: [[1],[1,-1],[-1]]
mΣ     -- map sum: [1,0,1]

2

Matlab, 33 ไบต์

@(x,y)sum(spdiags(flip(x').*y),1)

ลองออนไลน์!

สร้างเมทริกซ์ของผลิตภัณฑ์องค์ประกอบที่ชาญฉลาดทั้งหมดของอินพุทจากนั้นผลรวมตามแนวทแยงมุม ,1ที่กองกำลังสิ้นสุด MATLAB ผลรวมตามทิศทางที่ถูกต้องเมื่อหนึ่งของเวกเตอร์การป้อนข้อมูลที่มีความยาว 1

ใน Octave spdiagsไม่ทำงานสำหรับเวกเตอร์ทำให้เกิดข้อผิดพลาดเมื่อหนึ่งในอินพุตมีความยาว 1 Matlab 2016b หรือใหม่กว่านั้นจำเป็นสำหรับการขยายอย่างชัดเจนของผลิตภัณฑ์องค์ประกอบที่ชาญฉลาด


วิธีการที่ดี !!
Luis Mendo

1

Ruby, 83 ไบต์

ดึงเกือบโดยตรงจากคำตอบที่ฉันได้ก่อนหน้านี้เกี่ยวกับการขยายตัวของรากลงไปในพหุนามหนึ่ง

->a,b{q=a.map{|c|r=b.map{|e|e*c};b=[0]+b;r}
q.pop.zip(*q).map{|e|(e-[p]).reduce:+}}


1

JavaScript (ES6), 64 ไบต์

(a,b)=>a.map((n,i)=>b.map((m,j)=>r[j+=i]=m*n+(r[j]||0)),r=[])&&r

ส่งคืนอาเรย์ที่ว่างเปล่าหากอินพุตว่างเปล่า ขึ้นอยู่กับคำตอบของฉันPolynomialception



1

Clojure 104 ไบต์

#(vals(apply merge-with +(sorted-map)(for[i(range(count %))j(range(count %2))]{(+ i j)(*(% i)(%2 j))})))

การผสานเพื่อsorted-mapรับประกันว่าค่าจะถูกส่งกลับในลำดับที่ถูกต้อง ฉันหวังว่าจะมีอีกสองสามกรณีทดสอบ

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