14
\$\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.
\$\endgroup\$

23 Answers 23

8
\$\begingroup\$

Jelly, 5 bytes

ṙJṚæ.

Try it online!

Explanation

Firstly:

where vk are row vectors and x is a column vector.

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

Then, v1 is actually v rotated 0 to the right, and vk is v rotated k-1 to the right, etc.

From another angle, v1 is v rotated n to the left, and vn is 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)
\$\endgroup\$
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!

\$\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!

\$\endgroup\$
  • \$\begingroup\$ (v*2)[i+j] nice trick \$\endgroup\$ – Leaky Nun Jul 28 '17 at 14:44
4
\$\begingroup\$

Pyth, 10 bytes

ms*VQ.>QdU

Test suite.

\$\endgroup\$
3
\$\begingroup\$

Jelly, 9 bytes

LḶN⁸ṙæ×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 LḶN⁸ṙ×⁸S€ instead.

\$\endgroup\$
3
\$\begingroup\$

05AB1E, 11 bytes

DgGDÁ})ε*}O

Try it online!

\$\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.
\$\endgroup\$
  • \$\begingroup\$ A lot smarter than my answer! I like fst<$>zip l v very much. \$\endgroup\$ – jferard Jul 28 '17 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!

\$\endgroup\$
  • \$\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\$ – Giuseppe Aug 2 '17 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\$ – Giuseppe Aug 2 '17 at 14:45
2
\$\begingroup\$

Mathematica, 35 bytes

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

Try it online!

-9 bytes from @Not a tree

\$\endgroup\$
1
\$\begingroup\$

CJam, 17 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

GolfScript, 37 bytes

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

Try it online!

\$\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!

\$\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
\$\endgroup\$
  • \$\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\$ – Jonah Jul 28 '17 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\$ – miles Jul 28 '17 at 21:44
  • \$\begingroup\$ ah, TIL. is that something you use often? \$\endgroup\$ – Jonah Jul 28 '17 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\$ – miles Jul 28 '17 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
\$\endgroup\$
1
\$\begingroup\$

Octave, 34 bytes

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

Try it online!

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

\$\endgroup\$
  • \$\begingroup\$ You can save a byte with zipWith(*)l$drop i$cycle l. \$\endgroup\$ – Laikoni Jul 28 '17 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]
\$\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!

\$\endgroup\$
  • \$\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\$ – Luis Mendo Jul 29 '17 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\$ – rayryeng Jul 29 '17 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\$ – rayryeng Jul 30 '17 at 8:10
  • \$\begingroup\$ @LuisMendo Changed. Thank you very much :) Got to understand the code as I was changing my explanation above. \$\endgroup\$ – rayryeng Jul 30 '17 at 13:12
  • \$\begingroup\$ Glad I could help :-) \$\endgroup\$ – Luis Mendo Jul 30 '17 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
        )
    ))
)
\$\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.

\$\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.

\$\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.

\$\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).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.