เขียนโปรแกรมที่ตรวจสอบความถูกต้องของErdős – Straus


15

โปรแกรมเขียนซึ่งตรวจสอบแอร์ดิชเตราสส์-การคาดเดา
โปรแกรมควรใช้เป็นอินพุทหนึ่งจำนวนเต็มn( 3 <= n <= 1 000 000) และพิมพ์จำนวนเต็มสามเท่าของตัวตนที่น่าพอใจ4/n = 1/x + 1/y + 1/z, 0 < x < y < z.

รหัสที่สั้นที่สุดชนะ

ตัวอย่างบางส่วน:

3 => {1, 4, 12}
4 => {2, 3, 6}
5 => {2, 4, 20}
1009 => {253, 85096, 1974822872}
999983 => {249996, 249991750069, 62495875102311369754692}
1000000 => {500000, 750000, 1500000}

โปรดทราบว่าโปรแกรมของคุณอาจพิมพ์ผลลัพธ์อื่น ๆ สำหรับตัวเลขเหล่านี้เนื่องจากมีหลายวิธี


โปรแกรมจำเป็นต้องส่งออกทุก ๆ โซลูชันที่เป็นไปได้หรืออันเดียวเท่านั้น ตัวอย่างเช่นมี 2 ความเป็นไปได้สำหรับ n = 5
izlin

1
มีเพียงหนึ่งเดียวก็เพียงพอ
Somnium

2
มันค่อนข้างทำให้เข้าใจผิดว่ากรณีทดสอบเพียงอย่างเดียวของคุณไม่ใช่อินพุตที่ถูกต้องตามข้อกำหนด
Peter Taylor

ฉันจะเปลี่ยนตัวอย่างเพิ่ม durron597
Somnium

ฉันเพิ่มตัวอย่างนั้นเพราะงานวิจัยของฉันแนะนำว่ามันเป็นเรื่องยากโดยเฉพาะอย่างยิ่งที่ต้องทำ คนที่ยากที่สุดคือช่วงเวลาที่สอดคล้องกับ{1, 121, 169, 289, 361, 529}โมดูโล 840
durron597

คำตอบ:


12

Ruby, 119 106 ตัวอักษร

f=->s,c,a{m=s.to_i;c<2?m<s||(p a+[m];exit):(1+m...c*s).map{|k|f[s/(1-s/k),c-1,a+[k]]}}
f[gets.to_r/4,3,[]]

รหัสใช้ขอบเขตที่น้อยที่สุดสำหรับตัวแปรแต่ละตัวเช่นกันสำหรับn/4<x<3n/4 yแม้แต่ตัวอย่างสุดท้ายก็กลับมาทันที (ลองที่นี่ )

ตัวอย่าง:

> 12
[4, 13, 156]

> 123
[31, 3814, 14542782]

> 1234
[309, 190654, 36348757062]

> 40881241801
[10220310451, 139272994276206121600, 22828913614743204775214996005450198400]

วิธีแก้ปัญหาที่ยอดเยี่ยม แต่ขอบเขตค่อนข้างแน่นเนื่องจากโปรแกรมของคุณสำหรับ 1,000,000 ค้นหาโซลูชันที่ดีกว่า (ดูตัวอย่างของฉัน)
Somnium

1
@ user2992539 รหัสของฉันส่งคืนการแก้ปัญหาด้วยพจนานุกรมครั้งแรก (250001 <500000)
Howard

7

Mathematica 62

วิธีการแก้ปัญหาธรรมดาวานิลลานี้ทำงานได้ดี - ส่วนใหญ่

f@n_ := FindInstance[4/n == 1/x + 1/y + 1/z && 0 < x < y < z, {x, y, z}, Integers]

ตัวอย่างและการจับเวลา (ในวินาที)

AbsoluteTiming[f[63]]
AbsoluteTiming[f[123]]
AbsoluteTiming[f[1003]]
AbsoluteTiming[f[3003]]
AbsoluteTiming[f[999999]]
AbsoluteTiming[f[1000000]]

{0.313671, {{x -> 16, y -> 1009, z -> 1017072}}}
{0.213965, {{x -> 31, y -> 3814, z -> 14542782}}}
{0.212016, {{x -> 251, y -> 251754, z -> 63379824762}}}
{0.431834, {{x -> 751, y -> 2255254, z -> 5086168349262}}
{1.500332, {{x -> 250000, y - > 249999750052, z -> 1201920673328124750000}}
{1.126821, {{x -> 375000, y -> 1125000, z -> 2250000}}


แต่มันไม่ได้เป็นทางออกที่สมบูรณ์ มีตัวเลขบางอย่างที่ไม่สามารถแก้ได้ ตัวอย่างเช่น,

AbsoluteTiming[f[30037]]
AbsoluteTiming[f[130037]]

{2.066699, FindInstance [4/30037 == 1 / x + 1 / y + 1 / z && 0 <x <y <z, {x, y, z}, จำนวนเต็ม]}
{1.981802, FindInstance [4/130037 = = 1 / x + 1 / y + 1 / z && 0 <x <y <z, {x, y, z}, Integers]}


เครื่องมือที่เหมาะสมสำหรับงานที่เหมาะสม +1
William Barbosa

3
@WilliamBarbosa ฉันเถียงว่าFindInstanceไม่ได้เป็นเครื่องมือที่เหมาะสมเพราะมันไม่สามารถรับประกันได้ผล ...
ฮาวเวิร์ด

2
@Howard ฉันกำลังพูดถึง Mathematica จริง ๆ แล้ว
William Barbosa

Reduceดูเหมือนว่าจะแก้คดีปากแข็งแม้ว่ามันจะต้องใช้เวลา เช่น 15 นาทีเพื่อหาคำตอบ 82 รายการสำหรับ n = 10037
DavidC

3

ค#

Disclamer: นี่ไม่ใช่คำตอบที่จริงจัง

นี่เป็นเพียงการทำลายความเป็นไปได้ทั้งหมดจาก 1 เป็น 1 << 30 มันใหญ่มากช้าฉันไม่รู้ด้วยซ้ำว่ามันทำงานได้ถูกต้องหรือไม่ แต่มันก็เป็นไปตามสเป็คที่แท้จริงเพราะมันตรวจสอบสภาพทุกครั้งดังนั้นมันดีมาก ฉันไม่ได้ทดสอบสิ่งนี้เพราะ ideone มีการ จำกัด เวลา 5 วินาทีสำหรับโปรแกรมดังนั้นสิ่งนี้จะไม่เสร็จสิ้นการดำเนินการ

(ในกรณีที่มีคนสงสัยว่า: นี่คือความยาว308 ไบต์ที่ใหญ่มาก)

static double[]f(double n)
{
    for(double x=1;x<1<<30;x++)
    {
        for(double y=1;y<1<<30;y++)
        {
            for(double z=1;z<1<<30;z++)
            {
                if(4/n==1/x+1/y+1/z)
                    return new[]{x,y,z};
            }
        }
    }
    return null;
}

อัปเดต: แก้ไขมันเพื่อให้ใช้งานได้จริง


2
ไม่ทำงาน (คำใบ้: การหารจำนวนเต็ม)
Howard

มีแนวโน้มว่ามันจะไม่ทำงานเนื่องจากข้อผิดพลาดในการปัดเศษ
Somnium

@ user2992539 มันใช้งานได้สำหรับฉันฉันทดสอบด้วย5อินพุตและให้ผลลัพธ์ที่ถูกต้อง ( 2, 4, 20)
Christoph Böhmwalder

@HackerCow มันอาจไม่ทำงานสำหรับจำนวนเต็มขนาดใหญ่
Somnium

1
@HackerCow คุณสามารถประหยัดเวลาได้อย่างแน่นอนโดยเริ่มจาก y = x + 1 และ z = y + 1 มันอาจจะเร็วกว่าที่จะใช้การตรวจสอบที่เทียบเท่า 4xyz = n (xy + yz + xz) แม้ว่าฉันจะยอมรับว่านั่นเป็นนิพจน์ที่ยาวกว่าและยังมีปัญหาการปัดเศษ
เล่นแร่แปรธาตุ

3

Python 2 , 171 ไบต์

from sympy import*
def f(n):
 for d in xrange(1,n*n):
  for p in divisors(4*d+n*n):
   q=(4*d+n*n)/p;x=(n+p)/4;y=(n+q)/4
   if (n+p)%4+(n+q)%4+n*x*y%d<1:return x,y,n*x*y/d

ลองออนไลน์!

คำตอบแรกนั้นเร็วพอที่จะทดสอบอย่างละเอียดถี่ถ้วน นี้สามารถที่จะหาทางแก้ปัญหาสำหรับทุก 3 ≤ n ≤ 1000000 ในเวลาประมาณ 24 นาทีรวมสำหรับค่าเฉลี่ยประมาณ 1.4 มิลลิวินาทีในแต่ละ

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

Rewrite 4 / n = 1 / x + 1 / Y + 1 / Zเป็นZ = n · x · Y / dที่d = 4 · x · Y - n · x - n · Y จากนั้นเราสามารถแยก 4 · d + n 2 = (4 · x - n ) · (4 · y - n ) ซึ่งให้วิธีที่เร็วกว่ามากในการค้นหาxและyตราบใดที่dเล็ก. ได้รับx < Y < Zอย่างน้อยเราสามารถพิสูจน์d <3 · n 2 /4 (จึงผูกพันในวงด้านนอก) แม้ว่าในทางปฏิบัติก็มีแนวโน้มที่จะมีขนาดเล็ก-95 มาก% ของเวลาที่เราสามารถใช้d = 1, 2 หรือ 3 กรณีที่แย่ที่สุดคือn = 769129 ซึ่งd ที่เล็กที่สุดคือ 1754 (กรณีนี้ใช้เวลาประมาณ 1 วินาที)


1

Mathematica, 99 ไบต์

f[n_]:=(x=1;(w=While)[1>0,y=1;w[y<=x,z=1;w[z<=y,If[4/n==1/x+1/y+1/z,Return@{x,y,z}];++z];++y];++x])

มันเป็นสัตว์เดียรัจฉานที่ไร้เดียงสา ฉันจะไปถึงล้านคนอย่างแน่นอน n = 100ใช้เวลาครึ่งวินาที แต่n = 300ใช้เวลา 12 วินาที


1

Golflua 75

อ่านnจากข้อความแจ้งเตือน (หลังจากการเรียกใช้งานในเทอร์มินัล) แต่โดยทั่วไปจะทำซ้ำตามวิธีแก้ปัญหาของงานอดิเรกของ Calvin :

n=I.r()z=1@1~@y=1,z-1~@x=1,y-1?4*x*y*z==n*(y*z+x*z+x*y)w(n,x,y,z)~$$$z=z+1$

รุ่น Lua ที่ไม่ได้รับการยกย่องด้านบนคือ

n=io.read()
z=1
while 1 do
   for y=1,z-1 do
      for x=1,y-1 do
         if 4*x*y*z==n*(y*z+x*z+x*y) then
            print(n,x,y,z)
            return
         end
      end
   end
   z=z+1
end

ตัวอย่าง:

n=6     -->     3      4     12
n=12    -->     6     10     15
n=100   -->    60     75    100
n=1600  -->  1176   1200   1225

1

Python, 117

n=input();r=range;z=0
while 1:
 z+=1
 for y in r(z):
  for x in r(y):
    if 4*x*y*z==n*(y*z+x*z+x*y):print x,y,z;exit()

ตัวอย่าง:

16 --> 10 12 15

ไม่มีอะไรพิเศษเกินไป


1
ทำไมคุณถึงกำหนดฟังก์ชั่นถ้าคุณจะเรียกมันครั้งเดียวเท่านั้น?
isaacg

@isaacg มันต้องหยุดอย่างใด แต่การใช้exit()แทนจะทำให้สั้นลง
งานอดิเรกของ Calvin

0

C # - 134

ฉันโพสต์คำตอบไว้ที่นี่ก่อนหน้านี้ แต่มันก็ไม่ได้ร้ายแรงขนาดนั้น เมื่อมันเกิดขึ้นฉันมักจะเบื่อมากดังนั้นฉันจึงตีกอล์ฟนิดหน่อย

มันคำนวณตัวอย่างทั้งหมดทางเทคนิคอย่างถูกต้อง (ฉันไม่ได้ลองสองครั้งสุดท้ายเพราะอีกครั้ง ideone inforces จำกัด เวลา 5 วินาที) แต่คนแรกให้ผลลัพธ์ที่ถูกต้อง (ไม่จำเป็นต้องเป็นผลลัพธ์ที่คุณคำนวณ แต่ถูกต้อง) มันแปลก outputs จำนวนการออกคำสั่ง (ฉันมีเงื่อนงำทำไม) และจะให้10, 5, 2สำหรับ5(ซึ่งเป็นคำตอบที่ถูกต้องตามวิกิพีเดีย)

134 ไบต์สำหรับตอนนี้ฉันอาจจะตีกอล์ฟขึ้นอีกสักหน่อย

float[]f(float n){float x=1,y,z;for(;x<1<<30;x++)for(y=1;y<x;y++)for(z=1;z<y;z++)if(4/n==1/x+1/y+1/z)return new[]{x,y,z};return null;}

0

Haskell - 150 ตัวอักษร

main = getLine >>= \n -> (return $ head $ [(x,y,z) | x <- [1..y], y <- [1..z], z <- [1..], (4/n') == (1/x) + (1/y) + (1/z)]) where n' = read n

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

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