Найти скалярное произведение Rationals

31

Я был в доме друга на обед, и они предложили идею "векторного пространства Prime-factor". В этом пространстве положительные целые числа выражаются в виде вектора, так что 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-множество с моноидом, а не с группой, но это было упрощено с целью сделать вопрос приемлемым. Я не уверен, что делать с вашим последним комментарием, уверен, что он имеет ту же мощность, что и целые числа, но действие - это то, что определяет пробел, а не его размер. Возможно, вы имеете в виду нечто более конкретное, чего мне не хватает. Если это так, я был бы рад продолжить эту дискуссию (в чате может быть лучше).
Волшебник Пшеницы
2
Еще одна терминология: выбор векторных пространств, как правило, требует скалярного умножения из поля, поэтому простого использования целых чисел недостаточно. Это потому, что мы хотим, чтобы параллельные векторы были кратны друг другу, а не просто имели несколько общих множителей. Например, $ 4 $ и $ 8 $ являются параллельными «векторами» в этом пространстве (они оба имеют форму (a, 0, 0, ...)), но также не является скалярным кратным (т. Е. Целочисленной степенью) Другие. Однако на самом деле не так много других терминов, которые можно было бы использовать людям. «Бесплатный модуль над целыми числами» - лучшее, что я могу сделать.
Артур

Ответы:

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
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в общую сумму t. Добавление 1j**ifor i=0,1,2,3выполняет каждую комбинацию увеличения или уменьшения действительной или мнимой части для четырех входных чисел.

Bubbler сохранил 2 байта, объединяя начальные значения p=t=2.

XNOR
источник
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].

Спасибо за Арно, за исправление пропавшего 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
3
Вы можете заменить returnс print, и вы можете также сохранить отступ пространство , если вы пишете в качестве программы вместо функции.
Матмандан
@mathmandan Спасибо за информацию. Выглядит полезным для других моих представлений Py2, хотя и не уверен для Py3 (это требует дополнительного, eval()если только сам ввод функции не является строкой).
барботер
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].

Laikoni
источник