Вычислить матрицу-вектор


14

Учитывая целочисленный массив по крайней мере из двух элементов, выведите Matrix-Vector (определенный ниже) массива.

Чтобы вычислить Matrix-Vector , сначала поверните массив nввода размера, чтобы создать матрицу размера.n x n , , причем первый элемент массива следует за главной диагональю. Это формирует матричную часть. Для вектора переверните входной массив по вертикали. Затем выполните нормальное матричное умножение. Выходной вектор является результатом.

Например,

a = [1, 2, 3]

Сначала поверните массив два раза вправо, чтобы получить, [3, 1, 2]а [2, 3, 1]затем сложите их, чтобы сформировать 3x3матрицу

[[1, 2, 3]
 [3, 1, 2]
 [2, 3, 1]]

Затем переверните массив вертикально, чтобы сформировать вектор

[[1, 2, 3]    [[1]
 [3, 1, 2]  x  [2]
 [2, 3, 1]]    [3]]

Выполнить обычное матричное умножение

[[1, 2, 3]    [[1]    [[1+4+9]    [[14]
 [3, 1, 2]  x  [2]  =  [3+2+6]  =  [11]
 [2, 3, 1]]    [3]]    [2+6+3]]    [11]]

И вывод - [14, 11, 11]или [[14], [11], [11]](на ваш выбор, является ли он плоским или нет).

Пример № 2

a = [2, 5, 8, 3]

[[2, 5, 8, 3]    [[2]    [[4+25+64+9]     [[102]
 [3, 2, 5, 8]  x  [5]  =  [6+10+40+24]  =  [80]
 [8, 3, 2, 5]     [8]     [16+15+16+15]    [62]
 [5, 8, 3, 2]]    [3]]    [10+40+24+6]]    [80]]

[102, 80, 62, 80]

правила

  • Можно предположить, что ввод и вывод соответствуют целочисленному типу вашего языка.
  • Вход и выход могут быть предоставлены в любом удобном формате .
  • Либо полная программа или функция приемлемы. Если функция, вы можете вернуть вывод, а не распечатать его.
  • Если возможно, укажите ссылку на среду онлайн-тестирования, чтобы другие люди могли опробовать ваш код!
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

Ответы:


8

Желе , 5 байт

ṙJṚæ.

Попробуйте онлайн!

объяснение

В первую очередь:

где есть строки векторов и является столбец вектор.vkx

Это показывает, что умножение матриц - это просто точечный продукт между строками и столбцами.

Затем, на самом деле поворачивается вправо, и будет вращатьсяv1v0vkvk-1 вправо, и т.д.

С другой стороны, это поворачивается влево, и это поворачивается влево, и т.д.v1vnvnv1

Как это устроено

ṙJṚæ.   input: z (a list of length n)
ṙJ      [rot(z,1), rot(z,2), ..., rot(z,n)] (to the left)
  Ṛ     [rot(z,n), ..., rot(z,2), rot(z,1)]
   æ.   [rot(z,n).z , ..., rot(z,2).z , rot(z,1).z] (dot product)




3

Желе , 9 байт

LḶN⁸ṙæ×W€

Попробуйте онлайн!

Функция, которая возвращает вертикальный массив. Как полная программа, она выглядит так, как будто она возвращает горизонтальный массив. Чтобы вернуть горизонтальный массив, вы должны сделать LḶN⁸ṙ×⁸S€вместо этого.



2

Haskell , 49 байтов

f v=sum.zipWith(*)v.fst<$>zip(iterate tail$v++v)v

Попробуйте онлайн!

Для входа v=[1,2]

  • iterate tail$v++v выдает список [[1,2,1,2],[2,1,2],[1,2],[2],[],...]
  • fst<$>zip l vтак же, как take(length v)lи дает[[1,2,1,2],[2,1,2]]
  • sum.zipWith(*)v отображается на каждый элемент и дает векторное матричное произведение.

Намного умнее моего ответа! Мне fst<$>zip l vочень нравится
Джерард

2

R , 66 62 байт

sapply(length(n<-scan()):1,function(i)c(n[-(1:i)],n[1:i])%*%n)

Попробуйте онлайн!


использование Map(function(i)c(n[-(1:i)],n[1:i])%*%n,length(n<-scan()):1)на 3 байта короче; он просто возвращает список матриц.
Джузеппе

и цикл for for(i in seq(n<-scan()))F=c(c(n[-(1:i)],n[1:i])%*%n,F);F[1:i]составляет 61 байт без возврата странного формата вывода.
Джузеппе





1

J , 14 байт

+/ .*~#\.1&|.]

Попробуйте онлайн!

объяснение

+/ .*~#\.1&|.]  Input: array M
      #\.       Length of each suffix, forms the range [len(M), ..., 2, 1]
             ]  Identity, get M
         1&|.   For each 'x' in the suffix lengths, rotate left M  by 'x'
+/ .*~          Dot product with M

Это довольно мило. Один вопрос. Когда вы не 1&|.связаны 1с |.созданием монады? но затем вы используете эту монаду как с левым, так и с правым аргументом, причем левый определяет, сколько раз он был применен. Что тут происходит?
Иона

@Jonah Это специальная форма для &. Когда используется как u n&f v, он выполняет (n&f)^:u v. Смотрите дно связи, чтобы увидеть больше разборов этого.
миль

ах, пока. Вы часто этим пользуетесь?
Иона

@Jonah Во многих случаях это полезно для игры в гольф. В этом случае это можно было бы сделать за равное количество байтов с использованием ранга #\.|."{], но я опубликовал самое короткое, которое придумал, прежде чем пробовать альтернативы.
миль

1

APL, 17 байт

(↑¯1⌽(⍳≢)⌽¨⊂)+.×⍪

Объяснение:

(↑¯1⌽(⍳≢)⌽¨⊂)+.×⍪

 ↑                      matrix format of
  ¯1⌽                   right rotate by 1 of
     (⍳≢)               the 1..[length N]
         ⌽¨             rotations of
           ⊂            the enclosed input
             +.×        inner product with
                ⍪       1-column matrix of input



1

Шелуха , 11 байт

mΣ§‡*´ṀKoṫ¢

Попробуйте онлайн!

объяснение

mΣ§‡*´ṀKoṫ¢  Implicit input, e.g. [1,2,3]
          ¢  Cycle: [1,2,3,1,2,3,...
        oṫ   Tails: [[1,2,3,1,2,3...],[2,3,1,2,3...],[3,1,2,3...]...
     ´ṀK     Replace each element of input with input: [[1,2,3],[1,2,3],[1,2,3]]
   ‡*        Vectorized multiplication (truncated with respect to shortest list)
  §          applied to the last two results: [[1,4,9],[2,6,3],[3,2,6]]
mΣ           Sum of each row: [14,11,11]

1

Октава - 67 48 байт

Спасибо Луису Мендо за сокращение этого кода на 19 байт!

Примечание: этот код может работать только в октаве. MATLAB не поддерживает выражения внутри функций, которые могут создавать переменные, одновременно оценивая выражения, которые их создают.

n=numel(a=input(''));a(mod((x=0:n-1)-x',n)+1)*a'

Оригинальный код в MATLAB можно найти здесь, но можно запустить в любой версии MATLAB. Этот код составляет 67 байт:

a=input('');n=numel(a)-1;a(mod(bsxfun(@minus,0:n,(0:n)'),n+1)+1)*a'

объяснение

  1. a=input('');- Получает (строки) вектор от пользователя через стандартный ввод. Вы должны ввести вектор в форме октавы (т.е. [1,2,3]).
  2. n=numel(...); - Получает общее количество элементов во входном векторе.
  3. x=0:n-1- Создает вектор строки, который увеличивается от 0доn-1 с шагом 1.
  4. (x=0:n-1)-x'- Выполняет вещание так, чтобы у нас была n x nматрица, чтобы каждая строка iпредставляла собой элементы от 0 до n-1каждого элемента в строке, iвычитаемой изi .
  5. mod(..., n)+1- Гарантирует, что любые отрицательные значения обернуты nтак, чтобы каждая строка iсодержала вектор от 0 до n-1 кругового смещения влево наi элементы. Мы добавляем 1, когда MATLAB / Octave начинает индексировать векторы или матрицы с 1.
  6. a(...)- Создает n x nматрицу, где используя (4), мы получаем правильные индексы входного вектора, продиктованного каждым значением из (4), таким образом, получая матрицу, которая нам нужна.
  7. (...)*a'- Выполняет умножение вектора матрицы путем транспонирования / переворачивания, aчтобы стать вектором столбца перед выполнением умножения.

Примеры запусков

>> n=numel(a=input(''));a(mod((x=0:n-1)-x',n)+1)*a'
[1,2,3]

ans =

         14.00
         11.00
         11.00

>> n=numel(a=input(''));a(mod((x=0:n-1)-x',n)+1)*a'
[2,5,8,3]

ans =

        102.00
         80.00
         62.00
         80.00

Попробуйте онлайн!


Вы можете использовать неявное расширение вместо bsxfun. Определение nбез -1сохранения также экономит несколько байтов. А если вы ограничитесь Octave, вы можете назначить aи 0:nпеременным на лету и сохранить еще немного . Кроме того, приходите сюда чаще! :-D
Луис Мендо

@ LuisMendo ах да. Я забыл, что Octave уже поддерживает неявное расширение. Сохранение переменной внутри inputфункции также является хорошим трюком. Я не думаю, что это может поддержать это. Я видел это только в C или C ++ из моего собственного опыта. Благодарность!
rayryeng - Восстановить Монику

1
@LuisMendo В ближайшее время я внесу предложенные изменения в качестве правки. Я был занят, но я не сделал это приоритетом, поскольку эта запись, безусловно, никогда не выиграет в подсчете байтов.
rayryeng - Восстановить Монику

@LuisMendo изменено. Большое спасибо :) Понял код, поскольку я менял свое объяснение выше.
rayryeng - Восстановить Монику

Рад, что смог помочь :-)
Луис Мендо

0

Javascript 79 байт

Принимает входной массив и выводит массив матричного вектора

a=>(b=[...a],a.map(x=>([...b].reduce((m,n,i)=>m+=n*a[i],0,b.push(b.shift())))))

объяснение

a=>(
    b=[...a],                    // copy the input into b
    a.map(x=>(                   // transform a into a new array
        [...b].reduce(           // copy b into a new array and reduce
            (m,n,i)=>m+=n*a[i],  // memo += the element in the array * the ith
                                 // element in a
            0,                   // start memo at 0
            b.push(b.shift())    // shift the first element in b to the end
                                 // not used by reduce, but performing this op
                                 // here saves a few bytes
        )
    ))
)

0

Clojure, 80 байт

#(map(fn[_ c](apply +(map * c %)))%(iterate(fn[c](into[(last c)](butlast c)))%))

iterateпроизводит бесконечную последовательность, но вместо использования, (take (count %) (iterate ...))чтобы остановить ее, я использую %в качестве дополнительного аргумента map.


0

Perl 5 , 65 + 1 (-a) = 66 байт

@o=@F;for(@o){$r=0;$r+=$_*$F[$i++%@F]for@o;say$r;unshift@F,pop@F}

Попробуйте онлайн!

Принимает входной вектор как разделенные пробелом числа. Выводит разделенные строкой числа, представляющие вектор результата.



0

Common Lisp, 78 байт

(lambda(x)(loop as i on(append x x)as y in x collect(reduce'+(mapcar'* i x))))

Попробуйте онлайн!

Удвойте массив (в данном случае список Lisp) и выполните итерации по спискам с iпомощью (используя x, через y, чтобы остановить итерацию). Затем вычислите следующий элемент результата, суммируя результат умножения каждого элемента на xкаждый элемент i(снова останавливаясь, когда более короткий список заканчивается).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.