Danh tính của Bézout


11

Giới thiệu về danh tính của Bézout

GCD của hai số nguyên A, B là số nguyên dương lớn nhất chia cả hai số nguyên không để lại phần dư. Bây giờ vì thuộc tính của Euclid mà mỗi số nguyên N có thể được chia cho một số nguyên M khác như sau:

                                           Phân chia hạt nhân

tồn tại các cặp u, v sao cho chúng ta có thể viết:

                                           Danh tính của Bézout

Vì có vô số cặp đó, chúng tôi muốn tìm những cặp đặc biệt. Thực tế có chính xác (A, B không bằng 0) hai cặp như vậy bão hòa

                                           Các ràng buộc cho ý nghĩa (u, v)


ví dụ                                    Ví dụ với 19 và 17


Thử thách

Mục tiêu của thử thách này là tìm ra cặp hệ số (có thứ tự) (u, v) để bão hòa các ràng buộc trên và trong đó bạn phải tích cực. Điều này thu hẹp đầu ra thành một cặp duy nhất.


Đầu vào

Chúng tôi có thể giả định rằng đầu vào là dương, A cũng sẽ luôn lớn hơn B (A> B).


Đầu ra

Đầu ra của chương trình / chức năng của chúng ta phải là cặp (được đặt hàng) được chỉ định trong thử thách.


Quy tắc

Người ta không được sử dụng các thuật toán Euclide mở rộng tích hợp (ví dụ: trong Mathicala, người ta không được phép sử dụng GCDnhưng không được ExtendedGCD- điều này sẽ thất bại trong 5,3 dù sao).

Câu trả lời có thể là một chương trình đầy đủ (lấy đầu vào qua STDIN hoặc tương tự và đầu ra qua STDOUT) hoặc một hàm (trả về cặp).

Bên cạnh cặp (u, v) sẽ không có bất kỳ đầu ra nào, các dòng mới hoặc dấu cách được phép. (dấu ngoặc hoặc dấu phẩy đều ổn)

Đây là mã golf, tất cả các sơ hở tiêu chuẩn đều bị cấm và chương trình có số byte thấp nhất sẽ thắng.


Ví dụ

(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)

Câu trả lời:


1

MATL , 37 40 byte

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

Sử dụng bản phát hành (9.3.1) , sớm hơn thử thách này.

Đây là một cách tiếp cận vũ phu, vì vậy nó có thể không hoạt động cho các đầu vào lớn.

Hãy thử trực tuyến! Trình biên dịch trực tuyến dựa trên một bản phát hành mới hơn, nhưng tạo ra kết quả tương tự.

Giải trình

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 byte

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

Ví dụ sử dụng: 27998 # 6461-> (3,-13).

Đây là một cách tiếp cận vũ phu tìm thấy tất cả các kết hợp uvđó là các giải pháp hợp lệ được đặt hàng uvà chọn phương án đầu tiên. Điều này mất một thời gian để chạy cho lớn |v|.


Tôi thích []!!0ý tưởng =)
flawr

3

Python 3, 101 106 byte

Chỉnh sửa: Đã thêm một số cải tiến và chỉnh sửa được đề xuất bởi Bruce_Forte .

Một câu trả lời sử dụng thuật toán Euclide mở rộng. Mặc dù đó là một chút lộn xộn ở những nơi, và tôi hy vọng sẽ chơi nó nhiều hơn nữa. Tôi có thể chuyển đổi sang Python 2 để lưu một byte trên phép chia số nguyên ( //) nhưng tôi không chắc cách %toán tử mô đun của Python 2 hoạt động với đối số thứ hai âm, vì điều đó rất quan trọng để có được đầu ra đúng.

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)

Ung dung:

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

Một người dùng ẩn danh đã chỉ ra rằng biến ktrong dòng cuối cùng của phiên bản không được xác định của bạn là không xác định.
Jonathan Frech

@JonathanFrech À, cảm ơn bạn!
Sherlock9

1

Toán học, 80 byte

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

Giải thích :

Thuật toán Euclide mở rộng được sử dụng ở đây, theo một Nestphong cách. Phương thức mà các hệ số được lưu trữ trong mảng làm cho nó có thể sử dụng Dot.

Một đại diện có thể khác chỉ đơn giản là sử dụng biểu thức tượng trưng, ​​như u a - v bvới {a->19, b->17}. Việc biểu diễn như vậy sử dụng tính năng của Mathematica và rất thú vị, nhưng nó dài hơn nhiều bằng byte.


Các trường hợp thử nghiệm :

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

1

Ruby, 83 byte

Tôi nghĩ rằng có một vài cách để tinh chỉnh và đánh golf giải pháp này, nhưng tôi thích nó cho đến nay. Có lẽ tôi sẽ thử một giải pháp thuật toán Euclide mở rộng tiếp theo.

->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}

Làm thế nào nó hoạt động

Mã này bắt đầu với một vòng lặp utừ y0 đến 0, với một vòng lặp bên trong vtừ -x0 đến bên trong, chúng tôi kiểm tra mọi uvnếu u*x+v*y == gcd(x, y). Vì có thể có nhiều trận đấu trên đường đi (điều này sử dụng tìm kiếm rất kỹ lưỡng), chúng tôi bắt đầu từ 0 để khi chúng tôi có trận đấu cuối cùng trong số nhiều trận đấu, đó là trận đấu gần nhất |u||v|gần nhất với 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 hết bộ nhớ cho trường hợp thử nghiệm đó. Tôi sẽ viết ra một giải pháp thuật toán Euclide mở rộng ngay khi tôi có thể.
Sherlock9
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.