贝祖特的身份


11

Bézout身份简介

两个整数A,B的GCD是最大的正整数,该整数将两个整数除而无余数。现在由于欧几里得的性质,每个整数N可以除以另一个整数M,如下所示:

                                           欧几里得除法

存在u,v对,我们可以这样写:

                                           贝祖特的身份

由于这些对的数量是无限的,因此我们想找到特殊的对。实际上恰好有两个这样的对满足(A,B不为零)

                                           有意义(u,v)对的约束


例如                                    19和17的示例


挑战

这项挑战的目标是找到满足上述约束且u必须为正的一对(有序)系数(u,v)。这样会将输出范围缩小到唯一对。


输入值

我们可以假设输入为正,而且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)

Answers:


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主意=)
更加模糊的

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啊,谢谢!
Sherlock19年

1

Mathematica,80个字节

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

说明

扩展欧几里得算法在这里以一种Nest样式使用。将系数存储在数组中的方法可以使用Dot

另一种可能的表示形式就是简单地使用符号表达式,例如u a - v bwith {a->19, b->17}。这种表示形式利用了Mathematica的功能并且很有趣,但是它的字节数要长得多。


测试用例

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

1

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

这个怎么运作

此代码打头的循环uy下降到0,与内环v-x0,这里面我们检查每一个uv如果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达恩 该测试用例的IRB内存不足。我将尽快编写扩展的欧几里得算法解决方案。
Sherlock9年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.