แบ่งพาร์ติชั่นรายการ!


10

ในความท้าทายนี้คุณจะต้องแบ่งพาร์ติชันรายการโดยที่พาร์ติชั่นมีขนาดสูงสุดขนาดขั้นต่ำและขนาดที่ต้องการ ฉันจะใช้สัญลักษณ์(min,pref,max) เพื่อระบุขนาดในการท้าทายนี้

สำหรับผู้ที่ไม่คุ้นเคยกับการแบ่งพาร์ติชันรายการต่อไปนี้ได้รับการแบ่งพาร์ติชันออกเป็น 3 ส่วน:
[0..9] -> [[0,1,2],[3,4,5],[6,7,8]]

[0..10], (2,4,5) -> [[0,1,2,3],[4,5,6],[7,8,9]]เมื่อรายการที่ไม่เท่ากันหารคุณต้องพาร์ทิชันที่จะใกล้เคียงกับขนาดที่ต้องการเป็นไปได้: การแบ่งพาร์ติชั่นนี้ทำได้ดีกว่า[[0,1,2,3],[4,5,6,7],[8,9]]แม้ว่าจะมีความยาวที่ต้องการมากกว่าก็ตาม อย่างเป็นทางการเราต้องลดผลรวมของ(partitionLength-preferredSize)^2แต่ละพาร์ติชันให้น้อยที่สุด

ลำดับของความยาวพาร์ติชั่นไม่สำคัญ: สำหรับไม่ว่า[0..5], (2,3,3)จะเป็น[[0,1,2],[3,4]]หรือใช้[[0,1],[2,3,4]]งานได้ [0..7], (4,4,5) -> []ถ้าพาร์ติชันไม่มีความเป็นไปได้กลับอาร์เรย์ที่ว่างเปล่า

คุณสามารถสันนิษฐานได้ว่า1<=min<=pref<=maxและอาร์เรย์ที่ส่งถึงคุณนั้นเป็นอาร์เรย์จำนวนเต็มที่ไม่ว่างเปล่า อาร์เรย์จะเป็นอาร์กิวเมนต์แรกเสมอ คุณสามารถยอมรับ min, max, และ pref ในลำดับใดก็ได้และเป็น tuple หรือเป็นอาร์กิวเมนต์ที่แยกกัน

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

กรณีทดสอบ:

[1], (1,3,4)         -> [[1]]
[100], (1,2,3)       -> [[100]]
[1,2], (1,1,2)       -> [[1],[2]]
[1,2], (1,2,2)       -> [[1,2]]
[1,2], (1,3,3)       -> [[1,2]]
[1,2,3], (1,2,3)     -> [[1,2],[3]] or [[1,2,3]]
[1,2,3,4], (1,3,4)   -> [[1,2,3,4]]
[1,2,3,4,5], (3,3,4) -> []
[1,2,3,4,5], (2,2,2) -> []
[1,2,3,4,5], (3,3,5) -> [[1,2,3,4,5]]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49], (2,6,6) -> [[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29],[30,31,32,33,34],[35,36,37,38,39],[40,41,42,43,44],[45,46,47,48,49]]

นี่คือดังนั้นควรตั้งเป้าหมายให้น้อยที่สุดในภาษาที่คุณโปรดปราน!


สัญกรณ์ที่คุณกำลังใช้[a..b]รวมaและไม่รวมbถูกต้องหรือไม่
Alex A.

รวม B พิเศษ
Nathan Merrill

โปรดทราบว่าการตีความ a ของคุณไม่เหมือนกับพาร์ติชันจากทฤษฎีเซต ...
ตลอดไป

แต่มันเป็นอย่างมีประสิทธิภาพเทียบเท่ากับจำนวนเต็มแบ่งพาร์ทิชัน
Nathan Merrill

เกิดอะไรขึ้นถ้าไม่มีวิธีแก้ปัญหา?
feersum

คำตอบ:


2

Haskell, 152

_%0=[]
s%k|(a,b)<-splitAt(div(z s)k)s=a:b%(k-1)
z=length
f s n p x=snd$minimum$(z s*p^2,[]):[(sum[(z x-p)^2|x<-s%k],s%k)|k<-[-div(-z s)x..div(z s)n]]

ในพาร์ติชันใด ๆ หากมีสองรายการที่มีความยาวแตกต่างกันสองรายการขึ้นไปมันจะเป็นประโยชน์ในการลดขนาดรายการที่ใหญ่กว่าและขยายรายการที่เล็กกว่าเสมอ ดังนั้นเราจึงต้องพิจารณาพาร์ติชันที่มีขนาดรายการเพียงสองขนาดเท่านั้นซึ่งทำให้การคำนวณง่ายขึ้น

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

จากนั้นจะค้นหาค่าต่ำสุดโดยรวมและส่งคืน

การใช้งาน: อินพุตเช่นf [1,2,3,4,5] 1 3 4( fเป็นฟังก์ชั่นที่แก้ปัญหาความท้าทาย)

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

_%0=[]
s%k|(a,b)<-splitAt(div(length s)k)s=a:b%(k-1)
f s n p x|l<-length s=(s%)$snd$minimum$(l*p^2,0):[(k*j^2+mod l k*(1-2*j),k)|k<-[1..div l n],k*x>=l,j<-[p-div l k]]

1

CJam, 70

q~:S;_,[0L]a{_S2=e<),S0=>f{[__S1=-_*\]@@-j.+}[esL]a+:e<}j1={/(\e_}/;]p

ลองออนไลน์

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

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