查找Rationals的点积


31

我在朋友家吃晚饭,他们提出了“素数向量空间”的想法。在此空间中,将正整数表示为向量,以使向量中的第n个元素是第n个素数除以该数目的次数。(请注意,这意味着我们的向量具有无限数量的项。)例如20

2 0 1 0 0 0 ...

因为它的质因子分解是2 * 2 * 5

由于素因数分解是唯一的,所以每个数字都对应一个向量。

我们可以通过成对添加向量来添加向量。这与将它们关联的数字相乘相同。我们还可以进行标量乘法,这类似于将相关数提高为幂。

问题在于该空间实际上不是矢量空间,因为没有逆。如果继续进行加和逆运算并关闭向量空间,我们现在可以将每个正有理数表示为向量。如果我们保留向量加法表示乘法的事实。那么自然数的倒数就是它的倒数。

例如,数字20具有向量

2 0 1 0 0 0 ...

因此,1/20是其倒数

-2 0 -1 0 0 0 ...

如果我们想找到与14/15之类的分数相关的向量,我们将找到14

1 0 0 1 0 0 ...

1/15

0 -1 -1 0 0 0 ...

并通过执行矢量加法将它们相乘

1 -1 -1 1 0 0 ...

现在我们有了向量空间,我们可以通过给它一个内积来修改它以形成一个内积空间。为此,我们窃取了向量空间是经典给出的内积。两个向量的内积定义为其项的成对相乘之和。例如20·14/15 将计算如下

20    =  2  0  1  0  0  0 ...
14/15 =  1 -1 -1  1  0  0 ...
         2  0 -1  0  0  0 ...  -> 1

再举一个例子,产品2 /19·4/19

2/19 = 1 0 0 0 0 0 0 -1 0 0 0 ...
4/19 = 2 0 0 0 0 0 0 -1 0 0 0 ...
       2 0 0 0 0 0 0  1 0 0 0 ... -> 3

您的任务是实现一个执行该点积的程序。它应通过一对正整数(分子和分母)或有理类型(不允许浮点数,因为它们会导致精度和可除性问题)来获取两个正有理数,并且应输出代表两个点积的整数输入。

这是因此答案将以字节计分,而字节数越少越好。

测试用例

4 · 4 = 4
8 · 8 = 9
10 · 10 = 2
12 · 12 = 5
4 · 1/4 = -4
20 · 14/15 = 1
2/19 · 4/19 = 3

向量没有尺寸,向量空间没有尺寸。
乔纳森·弗雷希

5
@JonathanFrech我认为这有点古怪,但我已经进行了更改。
小麦巫师

通常将“自然数”理解为包含0,这在您的系统中未表示。这些不是向量。向量空间在一个字段上,并且在一个圆环上,这将使它成为一个模块。它不是与整数分开的空格,而是具有不同表示形式的相同空格。
累积

6
@累计“自然数”不是一个明确定义的术语,具体取决于您要求的人可能包含零,也可以不包含零。您的回答是正确的,我的问题中的“标量乘法”形成了一个带有一个单面体而不是一个组的G-set,但这是为了使问题变得可口而简化的。我不确定最后一条评论该怎么做,请确保它与整数具有相同的基数,但是操作实际上是定义空间而不是其大小的原因。也许您的意思是我所缺少的更具体的内容。如果是这样,我很乐意继续进行讨论(最好是聊天)。
小麦巫师

2
nit-pick的另一种术语:通常要求向量空间具有来自字段的标量乘法,因此仅使用整数是不够的。那是因为我们希望并行向量是彼此的倍数,而不仅仅是共有多个倍数。例如,$ 4 $和$ 8 $是该空间中的并行“向量”(它们都是(a,0,0,...)的形式),但都不是该空间的标量倍数(即整数幂)。其他。但是,您实际上可以使用的其他术语并不多,一般人都知道。我能做的最好的是“在整数上使用免费模块”。
亚瑟

Answers:


4

MATL,12字节

YF2:&Y)dwd*s

输入是一个数组[num1 den1 num2 den2]

在线尝试!验证所有测试用例

说明

考虑示例输入[20 1 14 15]

YF      % Implicit input: array of 4 numbers. Exponents of prime factorization.
        % Gives a matrix, where each row corresponds to one of the numbers in
        % the input array. Each row may contain zeros for non-present factors
        % STACK: [2 0 1 0
                  0 0 0 0
                  1 0 0 1
                  0 1 1 0]
2:&Y)   % Push a submatrix with the first two rows, then a submatrix with the
        % other two rows
        % STACK: [2 0 1 0
                  0 0 0 0],
                 [1 0 0 1
                  0 1 1 0]
d       % Consecutive difference(s) along each column
        % STACK: [2 0 1 0
                  0 0 0 0],
                 [-1 1 -1 1]
wd      % Swap, and do the same for the other submatrix
        % STACK: [-1 1 -1 1]
                 [-2 0 -1 0]
*       % Element-wise product
        % STACK: [2 0 -1 0]
s       % Sum. Implicit display
        % STACK: 1

4

C(gcc),99 + 32 = 131字节

  • 使用需要32个字节的编译器标志-D=F(v,V,e)for(;v%p<1;V+=e)v/=p;
T,p,A,C;f(a,b,c,d){T=0;for(p=2;a+b+c+d>4;p++){A=C=0;F(a,A,1)F(b,A,~0)F(c,C,1)F(d,C,~0)T+=A*C;}a=T;}

在线尝试!


我认为最好明确指定使用附加标志-D=F(v,V,e)for(;v%p<1;V+=e)v/=p;(32个字节)(因此99 + 32 = 131);否则,仅靠代码是没有意义的。
Bubbler '18


3

Python 2,110个字节

l=input()
p=t=2
while~-max(l):r=i=0;exec"while l[i]%p<1:l[i]/=p;r+=1j**i\ni+=1\n"*4;t+=r*r;p+=1
print t.imag/2

在线尝试!

接受类似的输入[num1, num2, den1, den2]。使用复数r存储p两个有理数的素项,并 在总和内(r*r).imag/2提取其r.real*r.imag乘积t1j**i对于i=0,1,2,3四个输入数字,将for 进行递增或递减的实部或虚部的每种组合。

冒泡者保存了2个字节并结合了初始值p=t=2


1
p=t=2而不是p=2;t=0因为t.real仍然会被忽略(TIO)。
Bubbler

@Bubbler不错,补充!
xnor


1

JavaScript(Node.js)104 ... 100 94字节

F=(A,i=2)=>A.some(x=>x>1)&&([a,b,c,d]=A.map(G=(x,j)=>x%i?0:1+G(A[j]/=i,j)),a-b)*(c-d)+F(A,i+1)

在线尝试!

将数字作为[Num1,Den1,Num2,Den2]的数组传递。

感谢Arnauld修复了丢失的内容F=,没有多余的字节,少了2个字节。

解释与取消

function F(A, i = 2) {                 // Main function, recursing from i = 2
 if (A.some(function(x) {              // If not all numbers became 1:
  return x > 1;
 })) {
  var B = A.map(G = function(x, j) {   // A recursion to calculate the multiplicity
   if (x % i)
    return 0;
   else
    return 1 + G(A[j] /= i, j);        // ...and strip off all powers of i
  });
  return (B[0] - B[1]) * (B[2] - B[3]) // Product at i
   + F(A, i + 1);                      // Proceed to next factor. All composite factors 
 }                                     // will be skipped effectively
 else 
  return 0;                            // Implied in the short-circuit &&
}

1

J,19个字节

1#.*/@,:&([:-/_&q:)

在线尝试!

说明:

二进位动词,参数在左手边和右手边

         &(        ) - for both arguments (which are lists of 2 integers)
               _&q:  - decompose each number to a list of prime exponents
           [:-/      - and find the difference of these lists
       ,:            - laminate the resulting lists for both args (to have the same length)
   */@               - multiply them
1#.                  - add up 

1

Stax,11 个字节

ä÷ß½♂←√:=Ü]

运行并调试

同一程序的相应ascii表示法是这样的。

{|nmMFE-~-,*+

基本上,它得到每个部分的质因子分解指数。它取每个对的差,然后取乘积,最后求和所有结果。


1

Python 2中133个 127字节

a=input();s=0;p=2;P=lambda n,i=0:n%p and(n,i)or P(n/p,i+1)
while~-max(a):a,(w,x,y,z)=zip(*map(P,a));s+=(w-x)*(y-z);p+=1
print s

在线尝试!

xnor的提交中窃取了循环条件。

感谢@mathmandan提出的将功能更改为程序的建议(是的,确实节省了一些字节)。

过时的,错误的解决方案(124字节):

lambda w,x,y,z:sum((P(w,p)-P(x,p))*(P(y,p)-P(z,p))for p in[2]+range(3,w+x+y+z,2))
P=lambda n,p,i=1:n%p and i or P(n/p,p,i+1)

不会p测试9等非素数的值吗?
xnor

糟糕,我会尽快修复。
Bubbler '18

3
您可以替换return使用print,而且还可以节省缩进空间,如果你写的程序,而不是功能。
mathmandan '18

@mathmandan感谢您的信息。看起来对我的其他Py2提交很有用,但是不确定Py3(这需要额外的费用,eval()除非函数输入本身是字符串)。
Bubbler

1

Haskell,153个字节

(2%)
n%m|all(<2)m=0|(k,[a,b,c,d])<-unzip[(,)=<<div x.max 1.(n*)$until((>0).mod x.(n^))(+1)1-1|x<-m]=(a-b)*(c-d)+[i|i<-[n..],all((>0).rem i)[2..i-1]]!!1%k

在线尝试!示例用法为20 · 14/15(2%) [20,1,14,15]

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.