Bézouts Identität


11

Einführung in Bézouts Identität

Die GCD von zwei ganzen Zahlen A, B ist die größte positive ganze Zahl, die beide teilt und keinen Rest hinterlässt. Aufgrund der Eigenschaft von Euklid kann nun jede ganze Zahl N wie folgt durch eine andere ganze Zahl M geteilt werden:

                                           Euklidische Teilung

Es gibt Paare u, v, so dass wir schreiben können:

                                           Bézouts Identität

Da es unendlich viele dieser Paare gibt, möchten wir spezielle finden. Es gibt tatsächlich genau (A, B ist nicht Null) zwei solche Paare, die sich erfüllen

                                           Einschränkungen für sinnvolle (u, v) -Paare


z.B                                    Beispiel mit 19 und 17


Herausforderung

Das Ziel dieser Herausforderung ist es, das (geordnete) Koeffizientenpaar (u, v) zu finden, das die obigen Einschränkungen erfüllt und bei dem u positiv sein muss. Dies schränkt die Ausgabe auf ein eindeutiges Paar ein.


Eingang

Wir können annehmen, dass der Eingang positiv ist, auch A wird immer größer als B sein (A> B).


Ausgabe

Die Ausgabe unseres Programms / unserer Funktion muss das in der Herausforderung angegebene (geordnete) Paar sein.


Regeln

Man darf keine eingebauten erweiterten euklidischen Algorithmen verwenden (zB darf man in Mathematica verwenden, GCDaber nicht ExtendedGCD- was für 5,3 sowieso fehlschlagen würde).

Die Antwort kann ein vollständiges Programm (Eingabe über STDIN oder ähnliches und Ausgabe über STDOUT) oder eine Funktion (Rückgabe des Paares) sein.

Neben dem Paar (u, v) darf keine Ausgabe erfolgen, nachgestellte Zeilenumbrüche oder Leerzeichen sind zulässig. (Klammern oder Kommas sind in Ordnung)

Dies ist Code Golf, alle Standardlücken sind verboten und das Programm mit der niedrigsten Byteanzahl gewinnt.


Beispiele

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

Antworten:


1

MATL , 37 40 Bytes

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

Verwendet Release (9.3.1) , das früher als diese Herausforderung ist.

Dies ist ein Brute-Force-Ansatz, daher funktioniert er möglicherweise nicht für große Eingaben.

Probieren Sie es online aus! Der Online-Compiler basiert auf einer neueren Version, liefert jedoch die gleichen Ergebnisse.

Erläuterung

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 Bytes

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

Anwendungsbeispiel: 27998 # 6461-> (3,-13).

Dies ist ein Brute-Force-Ansatz, bei dem alle Kombinationen von uund vdie gültigen Lösungen gefunden werden, die von uder ersten geordnet und ausgewählt wurden. Es dauert einige Zeit, bis es groß ist |v|.


Ich liebe die []!!0Idee =)
Fehler

3

Python 3, 101 106 Bytes

Bearbeiten: Einige von Bruce_Forte vorgeschlagene Verbesserungen und Korrekturen wurden hinzugefügt .

Eine Antwort, die den erweiterten euklidischen Algorithmus verwendet. Es ist allerdings etwas klobig und ich hoffe, dass ich noch mehr Golf spielen kann. Ich könnte in Python 2 konvertieren, um ein Byte für die Ganzzahldivision ( //) zu speichern , bin mir aber nicht sicher, wie der %Moduloperator von Python 2 mit einem negativen zweiten Argument funktioniert, da dies für die richtige Ausgabe von entscheidender Bedeutung ist.

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

Ein anonymer Benutzer wies darauf hin, dass die Variable kin der letzten Zeile Ihrer ungolfed Version undefiniert ist.
Jonathan Frech

@ JonathanFrech Ah, danke!
Sherlock9

1

Mathematica, 80 Bytes

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

Erklärung :

Hier wird in einem NestStil ein erweiterter euklidischer Algorithmus verwendet . Die Methode, mit der die Koeffizienten in Arrays gespeichert werden, ermöglicht die Verwendung Dot.

Eine andere mögliche Darstellung ist einfach die Verwendung eines symbolischen Ausdrucks, wie u a - v bmit {a->19, b->17}. Eine solche Darstellung nutzt die Funktion von Mathematica und ist interessant, in Bytes jedoch viel länger.


Testfälle :

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

1

Ruby, 83 Bytes

Ich denke, es gibt einige Möglichkeiten, diese Lösung zu optimieren und zu spielen, aber ich mag sie bisher. Vielleicht versuche ich als nächstes eine erweiterte euklidische Algorithmuslösung.

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

Wie es funktioniert

Dieser Code beginnt mit einer Schleife uvon ybis zu 0, mit einer inneren Schleife von vvon -x0, innen , die wir jeden überprüfen uund vwenn u*x+v*y == gcd(x, y). Da es auf dem Weg mehrere Übereinstimmungen sein könnte (diese Anwendungen eine sehr erschöpfende Suche), beginnen wir weit von 0 , so dass , wenn wir die letzte der mehr Treffer erhalten, dann ist es die, wo |u|und |v|am nächsten 0 sind.

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 hat für diesen Testfall nicht genügend Speicher. Ich werde so bald wie möglich eine erweiterte euklidische Algorithmuslösung schreiben.
Sherlock9
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.