การแบ่งส่วนกลับ


21

รับหมายเลขn> 77ให้เขียนโปรแกรมหรือฟังก์ชันที่พบชุดของจำนวนเต็มบวกที่แตกต่างกันอย่างเช่นผลรวมของเซตเท่ากับnและผลรวมของส่วนกลับของชุดเท่ากับ 1

ตัวอย่าง 80:

80 = 2 + 4 + 10 + 15 + 21 + 28 ⟶ 1/2 + 1/4 + 1/10 + 1/15 + 1/21 + 1/28 = 1

โปรแกรมหรือฟังก์ชั่นของคุณจะต้องทำงาน (ในทางทฤษฎี) สำหรับn <2 32ใด ๆและไม่ได้รับการยกเว้นสำหรับข้อผิดพลาดในการปัดเศษทศนิยม โปรดทราบว่ามีวิธีแก้ปัญหาสำหรับn> 77ทั้งหมด


รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

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


3
การสลายตัวดังกล่าวรับประกันได้หรือไม่ ทฤษฎีบทตัวเลขเชิงทฤษฎีใด ๆ ที่รับรองได้?
Luis Mendo

ดูเหมือนว่ามีไว้สำหรับ n> 77 ทั้งหมด (ผมไม่ได้ตรวจสอบทุกรายละเอียด.) ที่ควรจะได้รับในคำอธิบายของความท้าทายของคุณ ...
flawr

1
@ flawr ฉันคิดว่าเขาไม่ได้รวมการอ้างอิงนั้นเพราะให้O(log n)อัลกอริทึม
Peter Taylor

1
แต่ถึงกระนั้นเขาก็ควรที่จะกล่าวว่าชุดนี้มีอยู่สำหรับ n ที่ได้รับ (และผมพบว่ากระดาษในหน้าแรกว่าเมื่อ googling ชื่อ.)
flawr

1
@ flawr ฉันใช้เวลาประมาณ 10 นาทีในการค้นหา ฉันไปถึงมันผ่านหน้าเศษส่วนอียิปต์และคุณนินจาฉันประมาณ 10 วินาที
Peter Taylor

คำตอบ:


3

Mathematica, 54 ไบต์

Select[IntegerPartitions@#,Unequal@@#&&Tr[1/#]==1&,1]&

ประมาณว่าไม่มีประสิทธิภาพเท่าที่ได้รับ แต่จะแก้ไขได้n = 78ในประมาณ 9 วินาที

ผลลัพธ์จะถูกส่งคืนเป็นรายการที่อยู่ในรายการเดี่ยวเช่น:

{{45, 12, 9, 5, 4, 3}}

ฉันสงสัยว่ามันใช้งานได้กับ n ที่มีขนาดใหญ่มาก
njpipeorgan

@njpipeorgan ให้หน่วยความจำและเวลาเพียงพอใช่
Martin Ender

ฉันพบการประมาณความยาวของ IntegerPartition [n] ซึ่งอยู่ที่คำสั่งของ exp (sqrt (n)), ~ 10 ^ 10 ^ 4.5 สำหรับ n = 2 ^ 30 ฉันไม่เชื่อจริง ๆ ว่า mathematica (หรือแม้แต่สถาปัตยกรรมใด ๆ ) ก็สามารถเก็บอาร์เรย์ได้
njpipeorgan

@njpipeorgan ความท้าทายระบุอย่างชัดเจนว่าอัลกอริทึมต้องทำงานได้ถึง 2 ^ 32 ในทางทฤษฎีไม่ใช่ในทางปฏิบัติ (ตามปกติจะถือว่าเป็นรหัสสำหรับกอล์ฟ )
Martin Ender

4

Python 3, 7306 1995 Bytes

โซลูชันนี้ทำงานในความซับซ้อนของ log (n) (เท่าที่ฉันสามารถบอกได้)

def i(s,t):
 for n in s[::-1]:t=t.replace(*n)
 return [[]]*78+[list(bytearray.fromhex(a))for a in t.split(",")]
def f(n):
 g,h=lambda c,n:c+[[[2],[3,7,78,91]][n[len(c)]%2]+[i*2for i in c[-1]]],lambda n:[]if n<78 else h((n-[2,179][n%2])//2)+[n]
 v=h(n);c=[i([['g',',03040'],['h',',,0306080'],['i',',020'],['j','b0c1'],['k','21'],['l','60'],['m','30'],['n','141'],['o','k24'],['p',',g'],['q','618'],['r','0c0'],['s','1e'],['t',',0ml'],['u','283c'],['v','e0f1'],['w','2a38'],['x','80'],['y','a0'],['z','01'],['A','50'],['B','24'],['C','i40'],['D','plb1'],['E','gl'],['F','48'],['G','bre1'],['H','28'],['I','6k'],['J','416s'],['K',',040Al'],['L','90'],['M','2a'],['N','54'],['O','k6o'],['P','3c'],['Q','il'],['R','18'],['S','px'],['T','im'],['U','70'],['V','b1'],['W','23'],['X','pj'],['Y','hj'],['Z','0n']],'020lxycHTaRHCyf1517CyfneC91k51cCLdneQU912MCyf0dBiALyf2dClfPEyfneT9s2dELdneEjIgmLydHg5rd14BKLardsE3n8sQ9rd1517Q9rdneplmdRBgUmcRMC5sPEyf102bgA6sPE91z2miAj41IQmc0dRBQUen7spl31z82bT9RFT3wE7neMgmyf0dRBgUmaHMELc1b36EUdBMQLyfs2d,C710M2bgLardRHT3BFQ9rf0dPQ7rdBMQm9Rs2d,0mAl9100d142bE710M2bQmc0fRPtxarfn8sEc1k4sBTfnePExcwtxarf1k8BExcuT3kkT91663C51964,0mAl71k4BMELe12NTcRwQjOT820ltmarf1z8mExeRNCqBFtmyjIHKLa100ds2bQU91bM36garf1k4sBTcRBFgxarfwE91keB2dtUxcn8sME9nbs36gm9rduC5R78,0mAUyf0d14BME91kbB36QLc12AB2dgyjqkHEUeMNT9157eQU9RMFT8s78C8neuixLc1zk4AtUxc1z8Mmt8re0fn8sWhLyc1bH36pl8neu,Kxycsw,iAxc1420l,K8ren8NS9n81bs36hc0vz8WmYzqkmhyv2WBHhyVOHXkJoSjIwSjIuSvz4WASVZIAXZ6skmSj6oFXzOmplvcsW46D61csk46plv8WBFDqoF,tarvk8WBH,tyjkqoHhGqkN,tmvZ8sWmhVZqskmpc0vZ8WAXZqkAplbnImASbn6skwSbn6skuSVOwSVOupGONSbn6soFpyVkJk5aSj6sk78YJkuDkIP5aYOuhvzk4WBAhVzk416oA,tyjkJ265a,,0mxyjk41q53sYzIHmPXkqowXkqouhyVqoHFYz6omFhb0e1zqkmNSyVIP78YJ20klpyVOHwYk620olpc0vz8WBmFXzqomFpG61ckH38PhyjIP78Yz620kmlDkImLDzINUhGIuNDzIA78hb0e1ZIANYkqk366chG6oFNXkJkP5ahVZ6somFSb0e1620kNlhVk41qomADzIFLXkqso78pGqoFNXzkImP5a,tyjk620oHlhG620kNlXzqskm78,tjZqskHmPYqouFD6sku78YzqkNU,tjZqsomF')[v[0]]]
 for o in range(len(v)-1):c=g(c,v)
 return c[-1]

คุณสามารถทดสอบที่f(2**32 - 1)ทำงานเกือบจะทันที

ฉันใช้บทความนี้ในวิธีการคำนวณ ด้วยวิธีนี้มีข้อมูลจำนวนมากสำหรับค่าที่กำหนดไว้ล่วงหน้าสำหรับ n จาก 78 เป็น 334 โดยไม่มีตัวเลขสม่ำเสมอหลังจาก 168 ฉันต้องการเปลี่ยนข้อมูลนี้เป็นสิ่งเล็ก ๆ และฉันไม่รู้อัลกอริธึมการบีบอัดที่ดีดังนั้นฉันจึง ทำเอง

วิธีที่ฉันบีบอัดคือการมีรายการสตริงแทนที่กฎ ฉันสร้างวิธีการที่พบสตริงแทนที่กฎซึ่งจะลดเนื้อหาส่วนใหญ่โดยคำนึงถึงการกำหนดกฎ จากนั้นฉันใช้สิ่งนี้ซ้ำ ๆ จนกระทั่งฉันไม่สามารถสร้างกฎได้อีก (ฉันใช้อักขระ gz และ AZ) สตริงที่ฉันทำเพื่อแทนที่ด้วยเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาคของค่าฐานสิบหกสำหรับแต่ละตัวเลข ในการมองย้อนกลับการแปลงให้เป็นค่าเลขฐานสิบหกอาจไม่ใช่ตัวเลือกที่ฉลาดที่สุดมันอาจจะสั้นกว่าถ้าปล่อยให้เป็นทศนิยมเนื่องจากการมีเลขฐานสิบหกจะบันทึกเฉพาะตัวเลข 3 หลักเท่านั้น แต่จะเพิ่ม 0 สำหรับตัวเลขหลักเดียว

บรรทัดที่ฉันตั้งค่า c คุณสามารถดูรายการกฎการแทนที่และข้อความที่มันทำงานอยู่ กฎจะต้องนำไปใช้ในการย้อนกลับเช่นกันเพราะกฎบางอย่างรวมถึงตัวละครที่สร้างขึ้นจากกฎอื่น ๆ

นอกจากนี้ยังมีสถานที่มากมายในรหัสนี้ที่ฉันอาจตัดลงในไวยากรณ์เช่นเปลี่ยนรายการของรายการเป็นรายการเดียวแล้วใช้วิธีการอื่นในการเข้าถึงกฎเพื่อแทนที่ข้อความด้วย


1
n=218ผล[2]ที่คาดว่าจะได้หรือไม่
อย่างเป็นทางการเมื่อ

1
ไม่ฉันจะเห็นสาเหตุที่เกิดขึ้นในภายหลัง ขอโทษด้วย. อาจเป็นข้อผิดพลาดในข้อมูลที่ฉันบีบอัดในตอนแรก
คาเมรอน Aavik

1

Haskell, 93 ไบต์

import Data.List
import Data.Ratio
p n=[x|x<-subsequences[2..n],sum x==n,1==sum(map(1%)x)]!!0

ช้ามาก1แต่ทำงานในหน่วยความจำคงที่ วิธีแก้ปัญหาเล็กน้อย: ตรวจสอบลำดับทั้งหมดของ[2..n]ผลรวมและผลรวมของส่วนกลับ

การส่งคืนโซลูชันทั้งหมดแทนที่จะเป็นหนึ่งจะมีขนาดสั้นลง 3 ไบต์: เพียงลบ!!0(ระวัง: เวลาที่ใช้ทำงานจะปิดแผนภูมิเสมอ)


1เวลาทำงานขึ้นอยู่กับว่าผลลัพธ์ปรากฏเร็วแค่ไหนในรายการส่วนประกอบ ความเกียจคร้านของ Haskell จะหยุดการค้นหาหากพบคู่แรก เมื่อรวบรวมp 89(ผลลัพธ์[3,4,6,9,18,21,28]:) จะทำงานบนแล็ปท็อป (อายุ 4 ปี) ของฉันใน 35s ค่าอื่น ๆ แม้แต่น้อยอาจใช้เวลาหลายชั่วโมง


0

Julia, 77 ไบต์

n->collect(filter(i->i==∪(i)&&sum(j->Rational(1,j),i)==1,partitions(n)))[1]

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

partitionsเราได้รับพาร์ทิชันของจำนวนเต็มโดยใช้ จากนั้นเราจะกรองชุดพาร์ติชั่นให้กับผู้ที่มีองค์ประกอบเฉพาะซึ่งมีผลรวมกลับเป็น 1 เพื่อให้แน่ใจว่าไม่มีข้อผิดพลาดในการปัดเศษเกิดขึ้นเราใช้Rationalประเภทของ Julia เพื่อสร้างส่วนกลับ filterส่งคืนตัววนซ้ำดังนั้นเราต้องcollectใส่มันเข้าไปในอาร์เรย์ นี้ทำให้เรามีอาร์เรย์ของอาร์เรย์ (ให้มีเพียงองค์ประกอบหนึ่ง) [1]เพื่อให้เราสามารถได้รับครั้งแรกที่ใช้

ตอนนี้เมื่อฉันพูดไม่มีประสิทธิภาพฉันหมายถึงมัน ใช้งานสิ่งนี้สำหรับn = 80 ใช้เวลา 39.113 วินาทีในคอมพิวเตอร์ของฉันและจัดสรรหน่วยความจำ 13.759 GB

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