Identidade de Bézout


11

Introdução à identidade de Bézout

O MDC de dois números inteiros A, B é o maior número inteiro positivo que divide os dois, sem deixar resto. Agora, devido à propriedade de Euclid, cada número inteiro N pode ser dividido por outro número inteiro M, da seguinte maneira:

                                           Divisão euclidiana

existem pares u, v para que possamos escrever:

                                           Identidade de Bézout

Como existe uma quantidade infinita desses pares, gostaríamos de encontrar pares especiais. De fato, existem exatamente (A, B não sendo zero) dois desses pares que saturam

                                           Restrições para pares significativos (u, v)


por exemplo                                    Exemplo com 19 e 17


Desafio

O objetivo deste desafio é encontrar o par (ordenado) de coeficientes (u, v) que satisfazem as restrições acima e onde u deve ser positivo. Isso reduz a saída para um par único.


Entrada

Podemos assumir que a entrada é positiva, também A sempre será maior que B (A> B).


Resultado

A saída do nosso programa / função deve ser o par (pedido) especificado no desafio.


Regras

Não se deve usar algoritmos euclidianos estendidos incorporados (por exemplo, no Mathematica, é permitido o uso, GCDmas não ExtendedGCD- o que falharia em 5,3).

A resposta pode ser um programa completo (recebendo entrada via STDIN ou similar e saída via STDOUT) ou uma função (retornando o par).

Ao lado do par (u, v), não haverá saída, são permitidas novas linhas ou espaços à direita. (colchetes ou vírgulas estão bem)

Isso é código de golfe, todas as brechas padrão são proibidas e o programa com a menor contagem de bytes vence.


Exemplos

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

Respostas:


1

MATL , 37 40 bytes

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

Usa a liberação (9.3.1) , que é anterior a esse desafio.

Essa é uma abordagem de força bruta, portanto, pode não funcionar para entradas grandes.

Experimente online! O compilador online é baseado em uma versão mais recente, mas produz os mesmos resultados.

Explicação

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

Exemplo de uso: 27998 # 6461-> (3,-13).

Essa é uma abordagem de força bruta que encontra todas as combinações de ue vque são soluções válidas ordenadas ue escolhe a primeira. Isso leva algum tempo para ser executado em grande escala |v|.


Eu amo a []!!0idéia =)
flawr

3

Python 3, 101 106 bytes

Edit: Adicionado algumas melhorias e correções sugeridas por Bruce_Forte .

Uma resposta que usa o algoritmo euclidiano estendido. É um pouco desajeitado em alguns lugares, e espero jogar um pouco mais. Eu poderia converter para Python 2 para salvar um byte na divisão inteira ( //), mas não tenho certeza de como o %operador de módulo do Python 2 funciona com um segundo argumento negativo, pois isso é crucial para obter a saída correta.

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

Um usuário anônimo apontou que a variável kna última linha da sua versão não destruída é indefinida.
22618 Jonathan Frech

@JonathanFrech Ah, obrigado!
Sherlock9

1

Mathematica, 80 bytes

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

Explicação :

O algoritmo euclidiano estendido é usado aqui, em um Nestestilo. O método que os coeficientes são armazenados em matrizes torna possível o uso Dot.

Outra representação possível é simplesmente usar expressão simbólica, como u a - v bcom {a->19, b->17}. Essa representação utiliza o recurso do Mathematica e é interessante, mas é muito mais longa em bytes.


Casos de teste :

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

1

Ruby, 83 bytes

Acho que existem algumas maneiras de ajustar e aperfeiçoar essa solução, mas eu gosto até agora. Talvez eu tente outra solução de algoritmo euclidiano estendida.

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

Como funciona

Este código começa com um laço de upartir ypara baixo a 0, com um loop interno de vpartir -xpara 0, dentro do qual nós verificamos cada ue vse u*x+v*y == gcd(x, y). Desde que pode haver várias correspondências ao longo do caminho (isto usa uma pesquisa muito exaustiva), começamos longe de 0 para que quando chegarmos a última das várias correspondências, é aquele onde |u|e |v|estão mais próximos 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. O IRB ficou sem memória para esse caso de teste. Vou escrever uma solução estendida do algoritmo euclidiano o mais rápido possível.
Sherlock9
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.