L'identité de Bézout


11

Introduction à l'identité de Bézout

Le GCD de deux entiers A, B est le plus grand entier positif qui les divise tous les deux sans laisser de reste. Maintenant, à cause de la propriété d'Euclide, chaque entier N peut être divisé par un autre entier M comme suit:

                                           Division euclidienne

il existe des paires u, v telles que nous pouvons écrire:

                                           L'identité de Bézout

Puisqu'il y a une quantité infinie de ces paires, nous aimerions en trouver des spéciales. Il y a en fait exactement (A, B n'étant pas zéro) deux de ces paires qui satifient

                                           Contraintes pour les paires significatives (u, v)


par exemple                                    Exemple avec 19 et 17


Défi

Le but de ce défi est de trouver la paire (ordonnée) de coefficients (u, v) qui satisfait les contraintes ci-dessus et où u doit être positif. Cela réduit la sortie à une paire unique.


Contribution

On peut supposer que l'entrée est positive, aussi A sera toujours plus grand que B (A> B).


Production

La sortie de notre programme / fonction doit être la paire (ordonnée) spécifiée dans le défi.


Règles

Il ne faut pas utiliser d'algorithmes euclidiens étendus intégrés (par exemple, dans Mathematica on est autorisé à utiliser GCDmais pas ExtendedGCD- ce qui échouerait pour 5,3 de toute façon).

La réponse peut être un programme complet (prise d'entrée via STDIN ou similaire et sortie via STDOUT) ou une fonction (retour de la paire).

À côté de la paire (u, v), il ne doit y avoir aucune sortie, les sauts de ligne ou les espaces sont autorisés. (les crochets ou les virgules conviennent)

C'est le golf de code, toutes les failles standard sont interdites et le programme avec le nombre d'octets le plus bas gagne.


Exemples

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

Réponses:


1

MATL , 37 40 octets

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

Utilise la version (9.3.1) , qui est antérieure à ce défi.

Il s'agit d'une approche par force brute, donc elle peut ne pas fonctionner pour les entrées de grande taille.

Essayez-le en ligne! Le compilateur en ligne est basé sur une version plus récente, mais produit les mêmes résultats.

Explication

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 octets

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

Exemple d'utilisation: 27998 # 6461-> (3,-13).

Il s'agit d'une approche par force brute qui trouve toutes les combinaisons de uet vqui sont des solutions valides ordonnées par uet choisit la première. Cela prend un certain temps à courir pour grand |v|.


J'adore l' []!!0idée =)
flawr

3

Python 3, 101 106 octets

Edit: Ajout de quelques améliorations et corrections suggérées par Bruce_Forte .

Une réponse qui utilise l'algorithme euclidien étendu. C'est un peu maladroit par endroits cependant, et j'espère y jouer un peu plus. Je pourrais convertir en Python 2 pour enregistrer un octet sur la division entière ( //) mais je ne sais pas comment l' %opérateur de module de Python 2 fonctionne avec un deuxième argument négatif, car cela est crucial pour obtenir la bonne sortie.

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)

Non golfé:

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

Un utilisateur anonyme a souligné que la variable kdans la dernière ligne de votre version non golfée n'est pas définie.
Jonathan Frech

@JonathanFrech Ah, merci!
Sherlock9

1

Mathematica, 80 octets

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

Explication :

L'algorithme euclidien étendu est utilisé ici, dans un Neststyle. La méthode que les coefficients sont stockés dans des tableaux permet d'utiliser Dot.

Une autre représentation possible consiste simplement à utiliser une expression symbolique, comme u a - v bavec {a->19, b->17}. Une telle représentation utilise la fonctionnalité de Mathematica et est intéressante, mais elle est beaucoup plus longue en octets.


Cas de test :

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

1

Rubis, 83 octets

Je pense qu'il existe plusieurs façons de peaufiner et de jouer au golf cette solution, mais je l'aime jusqu'à présent. Je vais peut-être essayer une solution d'algorithme euclidien étendu ensuite.

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

Comment ça fonctionne

Ce code commence par une boucle de ude ybas à 0, avec une boucle intérieure de vde -xà 0, à l'intérieur de laquelle nous vérifions chaque uet vsi u*x+v*y == gcd(x, y). Puisqu'il pourrait y avoir plusieurs correspondances en cours de route (cela utilise une recherche très exhaustive), nous partons loin de 0 de sorte que lorsque nous obtenons la dernière des multiples correspondances, c'est celle où |u|et |v|sont les plus proches de 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 a manqué de mémoire pour ce cas de test. Je rédigerai une solution d'algorithme euclidien étendu dès que possible.
Sherlock9
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.