ตัวตนของBézout


11

รู้เบื้องต้นเกี่ยวกับตัวตนของBézout

GCD ของจำนวนเต็มสองจำนวน A, B เป็นจำนวนเต็มบวกที่ใหญ่ที่สุดซึ่งแบ่งออกเป็นสองส่วนโดยไม่มีเศษเหลือ ตอนนี้เพราะคุณสมบัติของ Euclid ที่แต่ละจำนวนเต็ม N สามารถหารด้วยจำนวนเต็ม M อื่นได้ดังนี้

                                           ส่วนยุคลิด

มีอยู่คู่ u, v เช่นที่เราสามารถเขียน:

                                           ตัวตนของBézout

เนื่องจากมีจำนวนคู่เหล่านั้นไม่ จำกัด เราจึงต้องการหาคนพิเศษ ในความเป็นจริงมีอย่างแน่นอน (A, B ไม่เป็นศูนย์) สองคู่ดังกล่าวที่อิ่ม

                                           ข้อ จำกัด สำหรับคู่ที่มีความหมาย (u, v)


เช่น                                    ตัวอย่างด้วย 19 และ 17


ท้าทาย

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


อินพุต

เราอาจสมมติว่าอินพุตเป็นค่าบวก A จะใหญ่กว่า B เสมอ (A> B)


เอาท์พุต

ผลลัพธ์ของโปรแกรม / ฟังก์ชั่นของเราจะต้องเป็นคู่ (สั่ง) ที่ระบุในการท้าทาย


กฎระเบียบ

เราต้องไม่ใช้อัลกอริธึมแบบขยายแบบยุคลิดในตัว (เช่นใน Mathematica แบบหนึ่งได้รับอนุญาตให้ใช้GCDแต่ไม่ใช่ExtendedGCD- ซึ่งจะล้มเหลวสำหรับ 5,3 anyways)

คำตอบอาจเป็นโปรแกรมเต็มรูปแบบ (รับอินพุตผ่าน STDIN หรือคล้ายกันและส่งออกผ่าน STDOUT) หรือฟังก์ชั่น (คืนทั้งคู่)

ข้างคู่ (u, v) จะไม่มีเอาต์พุตใด ๆ อนุญาตให้ขึ้นบรรทัดใหม่หรือเว้นวรรคได้ (วงเล็บหรือเครื่องหมายจุลภาคไม่เป็นไร)

นี่คือรหัสกอล์ฟห้ามช่องโหว่มาตรฐานทั้งหมดและโปรแกรมที่มีจำนวนไบต์ต่ำสุดชนะ


ตัวอย่าง

(A, B) -> (u, v)
(42, 12) -> (1, -3)
(4096, 84) -> (4, -195)
(5, 3) -> (2, -3)
(1155, 405) -> (20, -57)
(37377, 5204) -> (4365, -31351)
(7792, 7743) -> (7585, -7633)
(38884, 2737) -> (1707, -24251)
(6839, 746) -> (561, -5143)
(41908, 7228) -> (1104, -6401)
(27998, 6461) -> (3, -13)
(23780, 177) -> (20, -2687)
(11235813, 112358) -> (8643, -864301)

คำตอบ:


1

MATL , 37 40ไบต์

ZdXK2Gw/:1G*1GK/t_w2$:XI2G*!+K=2#fIb)

ใช้รีลีส (9.3.1)ซึ่งเร็วกว่าความท้าทายนี้

นี่เป็นวิธีบังคับแบบดุร้ายดังนั้นจึงอาจไม่สามารถทำงานกับอินพุตขนาดใหญ่ได้

ลองออนไลน์! คอมไพเลอร์ออนไลน์ขึ้นอยู่กับรีลีสที่ใหม่กว่า แต่ให้ผลลัพธ์ที่เหมือนกัน

คำอธิบาย

Zd            % implicitly input A and B. Compute their GCD. Call that C
XK            % copy C to clipboard K
2Gw/:         % vector [1, 2, ..., B/C]
1G*           % multiply that vector by A
1GK/t_w2$:    % vector [-A/C, -A/C+1 ..., A/C]
XI            % copy to clipboard I
2G*           % multiply that vector by B
!+            % all pairwise sums of elements from those vectors
K=2#f         % find row and column indices of sum that equals C
Ib)           % index second vector with column (indexing first vector with
              % row is not needed, because that vector is of the form [1, 2, ...])

7

Haskell, 51 ไบต์

a#b=[(u,-v)|v<-[1..],u<-[1..v],gcd a b==u*a-v*b]!!0

ตัวอย่างการใช้งาน: ->27998 # 6461(3,-13)

นี่เป็นวิธีการบังคับที่ดุร้ายซึ่งค้นหาชุดค่าผสมทั้งหมดuและvเป็นโซลูชันที่ถูกต้องซึ่งได้รับคำสั่งจากuและเลือกชุดแรก |v|นี้ใช้เวลาในการทำงานขนาดใหญ่


ฉันชอบ[]!!0ความคิด =)
ข้อบกพร่อง

3

Python 3, 101 106 ไบต์

แก้ไข:เพิ่มการปรับปรุงบางและการแก้ไขปัญหาโดยBruce_Forte

คำตอบที่ใช้อัลกอริทึมแบบยุคลิดแบบขยาย แม้ว่ามันจะค่อนข้าง clunky ในสถานที่และฉันหวังว่าจะได้เล่นกอล์ฟอีก ฉันสามารถแปลงเป็น Python 2 เพื่อบันทึกไบต์บนการหารจำนวนเต็ม ( //) แต่ฉันไม่แน่ใจว่า%ตัวดำเนินการโมดูลัสของ Python 2 ทำงานอย่างไรกับอาร์กิวเมนต์ที่สองที่เป็นค่าลบเนื่องจากเป็นสิ่งสำคัญในการทำให้เอาต์พุตถูกต้อง

def e(a,b):
 r=b;x=a;s=z=0;t=y=1
 while r:q=x/r;x,r=r,x%r;y,s=s,y-q*s;z,t=t,z-q*t
 return y%(b/x),z%(-a/x)

Ungolfed:

def e(a, b):
    r = b
    x = a    # becomes gcd(a, b)
    s = 0
    y = 1    # the coefficient of a
    t = 1
    z = 0    # the coefficient of b
    while r:
        q = x / r
        x, r = r, x % r
        y, s = s, y - q * s
        z, t = t, z - q * t
    return y % (b / x), z % (-a / x) # modulus in this way so that y is positive and z is negative

ผู้ใช้ที่ไม่ระบุชื่อชี้ให้เห็นว่าตัวแปรkในบรรทัดสุดท้ายของเวอร์ชันที่ไม่ได้รับการแก้ไขนั้นไม่ได้กำหนดไว้
Jonathan Frech

@JonathanFrech Ah ขอบคุณ!
Sherlock9

1

Mathematica, 80 ไบต์

f@l_:=Mod@@NestWhile[{Last@#,{1,-Quotient@@(#.l)}.#}&,{{1,0},{0,1}},Last@#.l>0&]

คำอธิบาย :

อัลกอริทึมแบบยุคลิดแบบขยายใช้ที่นี่ในNestสไตล์ วิธีการที่สัมประสิทธิ์ถูกเก็บไว้ในอาร์เรย์ทำให้สามารถใช้งานDotได้

อีกประการหนึ่งการแสดงที่เป็นไปได้เป็นเพียงการใช้การแสดงออกเชิงสัญลักษณ์เช่นกับu a - v b {a->19, b->17}การเป็นตัวแทนดังกล่าวใช้ประโยชน์จากคุณสมบัติของ Mathematica และน่าสนใจ แต่มันมีความยาวเป็นไบต์


กรณีทดสอบ :

f[{5, 3}]              (* {2, -3} *)
f[{42, 12}]            (* {1, -3} *)
f[{11235813, 112358}]  (* {8643, -864301} *)

1

Ruby, 83 ไบต์

ฉันคิดว่ามีวิธีไม่กี่วิธีในการปรับแต่งและเล่นกอล์ฟโซลูชันนี้ แต่ฉันชอบมันมาก บางทีฉันอาจจะลองใช้วิธีแก้ปัญหาอัลกอริทึมแบบยุคลิดต่อไป

->x,y{a=b=0;y.downto(0).map{|u|(-x..0).map{|v|a,b=u,v if u*x+v*y==x.gcd(y)}};p a,b}

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

รหัสนี้เริ่มต้นด้วยวงของuจากyลงไปที่ 0 มีห่วงด้านในของvจาก-x0 ภายในที่เราตรวจสอบทุกuและถ้าv u*x+v*y == gcd(x, y)เนื่องจากอาจจะมีหลายแมตช์พร้อมกัน (ใช้นี้ค้นหาหมดจดมาก) เราเริ่มห่างไกลจาก 0 เพื่อที่ว่าเมื่อเราได้รับสุดท้ายของหลายแมตช์ก็เป็นหนึ่งที่|u|และ|v|มีความใกล้เคียงกับ 0

def bezout(x,y)
  a=b=0
  y.downto(0).each do |u|
    (-x..0).each do |v|
      if u*x + v*y == x.gcd(y)
        a,b=u,v
      end
    end
  end
  p a,b
end

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