Ідентичність Безута


11

Вступ до особистості Безута

GCD двох цілих чисел A, B - це найбільше додатне ціле число, яке ділить їх обоє, не залишаючи залишку. Через властивість Евкліда кожне ціле число N може бути розділене іншим цілим числом M таким чином:

                                           Евклідовий поділ

існують пари u, v такі, що ми можемо записати:

                                           Ідентичність Безута

Оскільки цих пар є нескінченна, ми хочемо знайти спеціальні. Насправді є точно (A, B не дорівнює нулю) дві такі пари, які насичують

                                           Обмеження для значущих (u, v) -пар


напр                                    Приклад з 19 і 17


Виклик

Мета цього виклику - знайти (упорядковану) пару коефіцієнтів (u, v), які задовольняють вищевказані обмеження і де u має бути позитивним. Це звужує вихід до унікальної пари.


Вхідні дані

Можна вважати, що вхід позитивний, також A завжди буде більше B (A> B).


Вихідні дані

Висновок нашої програми / функції повинен бути (упорядкованою) парою, вказаною в виклику.


Правила

Не слід використовувати вбудовані розширені евклідові алгоритми (наприклад, в Mathematica дозволено використовувати один, GCDале ні ExtendedGCD- який би не зміг для 5,3 у будь-якому випадку).

Відповідь може бути повною програмою (прийняття вводу через 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ідея =)
flawr

3

Python 3, 101 106 байт

Редагування: Додано деякі покращення та виправлення, запропоновані Bruce_Forte .

Відповідь, що використовує розширений алгоритм Евкліда. Це місця дещо незграбно, і я сподіваюся, що ще трохи пограти. Я міг би перетворити на 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)

Безголівки:

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в останньому рядку вашої нереалізованої версії не визначена.
Джонатан Фрех

@JonathanFrech Ах, дякую!
Sherlock9

1

Математика, 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

Рубін, 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від -xдо 0, всередині якого ми перевіряємо кожен 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 не вистачало пам'яті для цього тестового випадку. Я напишу розширене рішення Евклідового алгоритму, як тільки зможу.
Шерлок9
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.