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

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]

правила

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

Ответы:

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€вместо этого.

Эрик Outgolfer
источник
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 отображается на каждый элемент и дает векторное матричное произведение.
Laikoni
источник
Намного умнее моего ответа! Мне 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

Haskell , 56 55 52 байта

f l=[sum$zipWith(*)l$drop i$l++l|i<-[0..length l-1]]

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

Сохранено один байт благодаря @Laikoni

Сохранено три байта: l++lвместоcycle l

jferard
источник
Вы можете сохранить байт с помощью zipWith(*)l$drop i$cycle l.
Лайкони
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]
Zgarb
источник
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

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

rayryeng - Восстановить Монику
источник
Вы можете использовать неявное расширение вместо 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
        )
    ))
)
asgallant
источник
0

Clojure, 80 байт

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

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

NikoNyrh
источник
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}

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

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

Xcali
источник
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(снова останавливаясь, когда более короткий список заканчивается).

Renzo
источник