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 code-golf so all usual golfing rules apply, and the shortest code (in bytes) wins.
23 Answers 23
Jelly, 5 bytes
ṙJṚæ.
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)
Python 2, 68 bytes
lambda x:[sum(map(int.__mul__,x,x[i:]+x[:i]))for i in range(len(x))]
Jelly, 9 bytes
×ばつW€
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.
Haskell, 49 bytes
f v=sum.zipWith(*)v.fst<$>zip(iterate tail$v++v)v
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 astake(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.
-
\$\begingroup\$ A lot smarter than my answer! I like
fst<$>zip l v
very much. \$\endgroup\$jferard– jferard2017年07月28日 19:55:57 +00:00Commented Jul 28, 2017 at 19:55
R, (削除) 66 (削除ここまで) 62 bytes
sapply(length(n<-scan()):1,function(i)c(n[-(1:i)],n[1:i])%*%n)
-
\$\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– Giuseppe2017年08月02日 14:23:21 +00:00Commented 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\$Giuseppe– Giuseppe2017年08月02日 14:45:49 +00:00Commented Aug 2, 2017 at 14:45
-
2\$\begingroup\$ It's shorter to use Mathematica's own matrix multiplication than to recreate it yourself:
Most@FoldList[RotateRight,#,1^#].#&
. (But nice trick usingFold
instead ofNest
!) \$\endgroup\$Not a tree– Not a tree2017年07月28日 23:52:16 +00:00Commented Jul 28, 2017 at 23:52
J, 14 bytes
+/ .*~#\.1&|.]
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
-
\$\begingroup\$ This is quite nice. One question. When you do
1&|.
aren't you bonding1
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– Jonah2017年07月28日 19:32:24 +00:00Commented Jul 28, 2017 at 19:32 -
-
\$\begingroup\$ ah, TIL. is that something you use often? \$\endgroup\$Jonah– Jonah2017年07月28日 21:46:56 +00:00Commented 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\$miles– miles2017年07月28日 22:22:40 +00:00Commented Jul 28, 2017 at 22:22
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
Haskell, (削除) 56 (削除ここまで) (削除) 55 (削除ここまで) 52 bytes
f l=[sum$zipWith(*)l$drop i$l++l|i<-[0..length l-1]]
Saved one byte thanks to @Laikoni
Saved three bytes: l++l
instead of cycle l
-
\$\begingroup\$ You can save a byte with
zipWith(*)l$drop i$cycle l
. \$\endgroup\$Laikoni– Laikoni2017年07月28日 18:51:45 +00:00Commented Jul 28, 2017 at 18:51
Husk, 11 bytes
mΣ§‡* ́ṀKoṫ¢
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]
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
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]
).n=numel(...);
- Obtains the total number of elements in the input vector.x=0:n-1
- Creates a row vector that increases from0
up ton-1
in steps of 1.(x=0:n-1)-x'
- Performs broadcasting so that we have an x n
matrix so that each rowi
are elements from 0 up ton-1
with each element in rowi
subtracted byi
.mod(..., n)+1
- Ensures that any values that are negative wrap around ton
so that each rowi
contains the vector from 0 up ton-1
circularly shifted to the left byi
elements. We add 1 as MATLAB / Octave starts indexing vectors or matrices with 1.a(...)
- Creates an 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.(...)*a'
- Performs matrix vector multiplication by transposing / flippinga
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!
-
\$\begingroup\$ You can use implicit expansion instead of
bsxfun
. Definingn
without-1
saves a few bytes too. And if you restrict to Octave you can assigna
and0:n
to variables on the fly and save some more. Also, come here more often!! :-D \$\endgroup\$Luis Mendo– Luis Mendo2017年07月29日 15:48:09 +00:00Commented 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\$rayryeng– rayryeng2017年07月29日 21:49:48 +00:00Commented 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\$rayryeng– rayryeng2017年07月30日 08:10:37 +00:00Commented 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\$rayryeng– rayryeng2017年07月30日 13:12:14 +00:00Commented Jul 30, 2017 at 13:12
-
\$\begingroup\$ Glad I could help :-) \$\endgroup\$Luis Mendo– Luis Mendo2017年07月30日 15:04:46 +00:00Commented Jul 30, 2017 at 15:04
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
)
))
)
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
.
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}
Takes the input vector as space separated numbers. Outputs linefeed separated numbers representing the result vector.
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;}
An array may be represented in input as a pointer and length.
Common Lisp, 78 bytes
(lambda(x)(loop as i on(append x x)as y in x collect(reduce'+(mapcar'* i x))))
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).