15
\$\begingroup\$

Given an integer array of at least two elements, output the Matrix-Vector (defined below) of the array.

To compute the Matrix-Vector, first rotate through the size-n input array to create a matrix of size n x n, with the first element of the array following the main diagonal. This forms the matrix portion. For the vector, flip the input array vertically. Then perform normal matrix multiplication. The output vector is the result.

For example,

a = [1, 2, 3]

First, rotate the array two times to the right, to obtain [3, 1, 2] and [2, 3, 1], then stack them to form a 3x3 matrix

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

Next, flip the array vertically to form the vector

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

Perform usual matrix multiplication

[[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]]

And the output is [14, 11, 11] or [[14], [11], [11]] (your choice of whether it's flattened or not).

Example #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]

Rules

  • The input and output can be assumed to fit in your language's native integer type.
  • The input and output can be given in any convenient format.
  • Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
  • If possible, please include a link to an online testing environment so other people can try out your code!
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
asked Jul 28, 2017 at 14:36
\$\endgroup\$

23 Answers 23

10
\$\begingroup\$

Jelly, 5 bytes

ṙJṚæ.

Try it online!

Explanation

Firstly:

$$\left[\begin{matrix} \vec{v}_1 \\ \vec{v}_2 \\ \vec{v}_3 \\ \vec{v}_4 \\ \end{matrix}\right] \vec{x} = \left[\begin{matrix} \vec{v}_1 \cdot \vec{x} \\ \vec{v}_2 \cdot \vec{x} \\ \vec{v}_3 \cdot \vec{x} \\ \vec{v}_4 \cdot \vec{x} \\ \end{matrix}\right]$$

where \$\vec{v}_k\$ are row vectors and \$x\$ is a column vector.

This demonstrates that matrix multiplication is just dot product between rows and columns.

Then, \$\vec{v}_1\$ is actually \$\vec{v}\$ rotated \0ドル\$ to the right, and \$\vec{v}_k\$ is \$\vec{v}\$ rotated \$k-1\$ to the right, etc.

From another angle, \$\vec{v}_1\$ is \$\vec{v}\$ rotated \$n\$ to the left, and \$\vec{v}_n\$ is \$\vec{v}\$ rotated \1ドル\$ to the left, etc.

How it works

ṙ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)
caird coinheringaahing
50.8k11 gold badges133 silver badges363 bronze badges
answered Jul 28, 2017 at 14:48
\$\endgroup\$
0
5
\$\begingroup\$

Python 2, 68 bytes

lambda x:[sum(map(int.__mul__,x,x[i:]+x[:i]))for i in range(len(x))]

Try it online!

answered Jul 28, 2017 at 14:53
\$\endgroup\$
4
\$\begingroup\$

Python 2, 73 bytes

def f(v):r=range(len(v));return[sum(v[i]*(v*2)[i+j]for i in r)for j in r]

Try it online!

answered Jul 28, 2017 at 14:44
\$\endgroup\$
1
  • \$\begingroup\$ (v*2)[i+j] nice trick \$\endgroup\$ Commented Jul 28, 2017 at 14:44
4
\$\begingroup\$

Pyth, 10 bytes

ms*VQ.>QdU

Test suite.

answered Jul 28, 2017 at 14:52
\$\endgroup\$
3
\$\begingroup\$

Jelly, 9 bytes

×ばつW€

Try it online!

A function that returns a vertical array. As a full program it appears as if it returns a horizontal array. To return a horizontal array you'd do ×ばつ8S€ instead.

answered Jul 28, 2017 at 14:39
\$\endgroup\$
0
3
\$\begingroup\$

05AB1E, 11 bytes

DgGDÁ})ε*}O

Try it online!

answered Jul 28, 2017 at 14:58
\$\endgroup\$
2
\$\begingroup\$

Haskell, 49 bytes

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

Try it online!

For an input v=[1,2]

  • iterate tail$v++v yields the list [[1,2,1,2],[2,1,2],[1,2],[2],[],...]
  • fst<$>zip l v is the same as take(length v)l and yields [[1,2,1,2],[2,1,2]]
  • sum.zipWith(*)v is mapped on each element and to yield the vector-matrix row product.
answered Jul 28, 2017 at 19:04
\$\endgroup\$
1
  • \$\begingroup\$ A lot smarter than my answer! I like fst<$>zip l v very much. \$\endgroup\$ Commented Jul 28, 2017 at 19:55
2
\$\begingroup\$

R, (削除) 66 (削除ここまで) 62 bytes

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

Try it online!

answered Jul 28, 2017 at 18:33
\$\endgroup\$
2
  • \$\begingroup\$ using Map(function(i)c(n[-(1:i)],n[1:i])%*%n,length(n<-scan()):1) is 3 bytes shorter; it just returns a list of matrices. \$\endgroup\$ Commented Aug 2, 2017 at 14:23
  • \$\begingroup\$ and a for loop for(i in seq(n<-scan()))F=c(c(n[-(1:i)],n[1:i])%*%n,F);F[1:i] is 61 bytes without returning a weird output format. \$\endgroup\$ Commented Aug 2, 2017 at 14:45
2
\$\begingroup\$

Mathematica, 35 bytes

Most@FoldList[RotateRight,#,1^#].#&

Try it online!

-9 bytes from @Not a tree

answered Jul 28, 2017 at 14:57
\$\endgroup\$
1
  • 2
    \$\begingroup\$ It's shorter to use Mathematica's own matrix multiplication than to recreate it yourself: Most@FoldList[RotateRight,#,1^#].#&. (But nice trick using Fold instead of Nest!) \$\endgroup\$ Commented Jul 28, 2017 at 23:52
1
\$\begingroup\$

CJam, 17 bytes

{__,,\fm>\f.*::+}

Try it online!

answered Jul 28, 2017 at 15:03
\$\endgroup\$
1
\$\begingroup\$

GolfScript, 37 bytes

{..,({.)\+}[*]{[1$\]zip{~*}%{+}*}%\;}

Try it online!

answered Jul 28, 2017 at 15:10
\$\endgroup\$
1
\$\begingroup\$

Python 3 + numpy, 68 bytes

lambda v:dot([roll(v,i)for i in range(len(v))],v)
from numpy import*

Try it online!

answered Jul 28, 2017 at 15:13
\$\endgroup\$
1
\$\begingroup\$

J, 14 bytes

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

Try it online!

Explanation

+/ .*~#\.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
answered Jul 28, 2017 at 15:49
\$\endgroup\$
4
  • \$\begingroup\$ This is quite nice. One question. When you do 1&|. aren't you bonding 1 to |., creating a monad? but then you use that monad with both a left and right arg, with the left one determining how many times it's applied. What's going on here? \$\endgroup\$ Commented Jul 28, 2017 at 19:32
  • \$\begingroup\$ @Jonah It's a special form for &. When used as u n&f v, it is performing (n&f)^:u v. See the bottom of bond to see more parses of it. \$\endgroup\$ Commented Jul 28, 2017 at 21:44
  • \$\begingroup\$ ah, TIL. is that something you use often? \$\endgroup\$ Commented Jul 28, 2017 at 21:46
  • \$\begingroup\$ @Jonah It's useful for golfing in many cases. In this case, it could have been done in an equal number of bytes using rank #\.|."{], but I posted the shortest that I came up with first before trying alternatives. \$\endgroup\$ Commented Jul 28, 2017 at 22:22
1
\$\begingroup\$

APL, 17 bytes

(↑ ̄1⌽(⍳≢)⌽ ̈⊂)×ばつ

Explanation:

(↑ ̄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
answered Jul 28, 2017 at 18:46
\$\endgroup\$
1
\$\begingroup\$

Octave, 34 bytes

@(a)a*toeplitz(a,shift(flip(a),1))

Try it online!

answered Jul 29, 2017 at 2:44
\$\endgroup\$
1
\$\begingroup\$

Haskell, (削除) 56 (削除ここまで) (削除) 55 (削除ここまで) 52 bytes

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

Try it online!

Saved one byte thanks to @Laikoni

Saved three bytes: l++l instead of cycle l

answered Jul 28, 2017 at 16:03
\$\endgroup\$
1
  • \$\begingroup\$ You can save a byte with zipWith(*)l$drop i$cycle l. \$\endgroup\$ Commented Jul 28, 2017 at 18:51
1
\$\begingroup\$

Husk, 11 bytes

mΣ§‡* ́ṀKoṫ¢

Try it online!

Explanation

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]
answered Jul 29, 2017 at 7:35
\$\endgroup\$
1
\$\begingroup\$

Octave - (削除) 67 (削除ここまで) 48 bytes

Thanks to Luis Mendo for shaving this code down by 19 bytes!

Note: This code can only run in Octave. MATLAB does not support expressions inside functions that can create variables while simultaneously evaluating the expressions that create them.

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

The original code in MATLAB can be found here, but can be run in any version of MATLAB. This code is 67 bytes:

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

Explanation

  1. a=input(''); - Receives a (row) vector from the user through standard input. You must enter the vector in Octave form (i.e. [1,2,3]).
  2. n=numel(...); - Obtains the total number of elements in the input vector.
  3. x=0:n-1- Creates a row vector that increases from 0 up to n-1 in steps of 1.
  4. (x=0:n-1)-x' - Performs broadcasting so that we have a n x n matrix so that each row i are elements from 0 up to n-1 with each element in row i subtracted by i.
  5. mod(..., n)+1 - Ensures that any values that are negative wrap around to n so that each row i contains the vector from 0 up to n-1 circularly shifted to the left by i elements. We add 1 as MATLAB / Octave starts indexing vectors or matrices with 1.
  6. a(...) - Creates a n x n matrix where using (4), we access the correct indices of the input vector dictated by each value from (4) thus achieving the matrix we need.
  7. (...)*a' - Performs matrix vector multiplication by transposing / flipping a to become a column vector prior to doing the multiplication.

Example Runs

>> 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

Try it online!

answered Jul 29, 2017 at 1:46
\$\endgroup\$
5
  • \$\begingroup\$ You can use implicit expansion instead of bsxfun. Defining n without -1 saves a few bytes too. And if you restrict to Octave you can assign a and 0:n to variables on the fly and save some more. Also, come here more often!! :-D \$\endgroup\$ Commented Jul 29, 2017 at 15:48
  • \$\begingroup\$ @LuisMendo ah yes. I forget Octave has implicit expansion already supported. Also saving the variable inside the input function is a great trick. I didn't think it could support that. I've seen it only in C or C++ from my own experience. Thanks! \$\endgroup\$ Commented Jul 29, 2017 at 21:49
  • 1
    \$\begingroup\$ @LuisMendo I'll place your suggested changes as an edit soon. I have been busy, but I haven't made this a priority as this entry will surely never win in byte count. \$\endgroup\$ Commented Jul 30, 2017 at 8:10
  • \$\begingroup\$ @LuisMendo Changed. Thank you very much :) Got to understand the code as I was changing my explanation above. \$\endgroup\$ Commented Jul 30, 2017 at 13:12
  • \$\begingroup\$ Glad I could help :-) \$\endgroup\$ Commented Jul 30, 2017 at 15:04
0
\$\begingroup\$

Javascript 79 bytes

Takes in an input array and outputs an array of the matrix vector

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

Explanation

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
 )
 ))
)
answered Jul 28, 2017 at 19:19
\$\endgroup\$
0
\$\begingroup\$

Clojure, 80 bytes

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

iterate produces an infinite sequence, but instead of using (take (count %) (iterate ...)) to stop it I use % as an extra argument to map.

answered Jul 28, 2017 at 20:23
\$\endgroup\$
0
\$\begingroup\$

Perl 5, 65 + 1 (-a) = 66 bytes

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

Try it online!

Takes the input vector as space separated numbers. Outputs linefeed separated numbers representing the result vector.

answered Jul 28, 2017 at 21:20
\$\endgroup\$
0
\$\begingroup\$

C (gcc), 126 bytes

i,j;int*f(int*a,int n){int*r=malloc(n*sizeof(int));for(i=0;i<n;i++){r[i]=0;for(j=0;j<n;j++)r[i]+=a[j]*a[(j-i+n)%n];}return r;}

Try it online!

An array may be represented in input as a pointer and length.

answered Jul 29, 2017 at 6:56
\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 78 bytes

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

Try it online!

Double the array (in this case a Lisp list) and iterate over the sublists with i (using x, through y, to stop the iteration). Then calculate the next element of the result by summing the result of multiplying each element of x with each element of i (again stopping when the shorter list is terminated).

answered Jul 29, 2017 at 7:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.