Oblicz wektor macierzowy

14

Biorąc pod uwagę tablicę liczb całkowitych składającą się z co najmniej dwóch elementów, wyślij wektor macierzy (zdefiniowany poniżej) tablicy.

Aby obliczyć wektor macierzy , najpierw obróć ntablicę wprowadzania rozmiaru n x n, aby utworzyć macierz wielkości , przy czym pierwszy element tablicy będzie podążał za główną przekątną. To tworzy część matrycy. W przypadku wektora odwróć tablicę wejściową pionowo. Następnie wykonaj normalne mnożenie macierzy. Wektor wyjściowy jest wynikiem.

Na przykład,

a = [1, 2, 3]

Po pierwsze, należy obrócić tablice dwa razy na prawo, w celu uzyskania [3, 1, 2]i [2, 3, 1], następnie stosu je, tworząc 3x3macierz

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

Następnie odwróć tablicę pionowo, aby utworzyć wektor

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

Wykonaj zwykłe mnożenie macierzy

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

Wyjście to [14, 11, 11]lub [[14], [11], [11]](wybór, czy ma być spłaszczony, czy nie).

Przykład nr 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]

Zasady

  • Można założyć, że dane wejściowe i wyjściowe pasują do natywnego typu liczb całkowitych twojego języka.
  • Dane wejściowe i wyjściowe można podawać w dowolnym dogodnym formacie .
  • Dopuszczalny jest pełny program lub funkcja. Jeśli funkcja, możesz zwrócić dane wyjściowe zamiast je drukować.
  • Jeśli to możliwe, dołącz link do internetowego środowiska testowego, aby inne osoby mogły wypróbować Twój kod!
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).
AdmBorkBork
źródło

Odpowiedzi:

8

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)
Leaky Nun
źródło
5

Python 2, 68 bytes

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

Try it online!

Rod
źródło
4

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!

Arfie
źródło
(v*2)[i+j] nice trick
Leaky Nun
3

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.

Erik the Outgolfer
źródło
2

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.
Laikoni
źródło
A lot smarter than my answer! I like fst<$>zip l v very much.
jferard
2

R, 66 62 bytes

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

Try it online!

Leaky Nun
źródło
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.
Giuseppe
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.
Giuseppe
1

Python 3 + numpy, 68 bytes

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

Try it online!

notjagan
źródło
1

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
miles
źródło
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?
Jonah
@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.
miles
ah, TIL. is that something you use often?
Jonah
@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.
miles
1

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
marinus
źródło
1

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

jferard
źródło
You can save a byte with zipWith(*)l$drop i$cycle l.
Laikoni
1

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]
Zgarb
źródło
1

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!

rayryeng - Reinstate Monica
źródło
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
Luis Mendo
@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!
rayryeng - Reinstate Monica
1
@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.
rayryeng - Reinstate Monica
@LuisMendo Changed. Thank you very much :) Got to understand the code as I was changing my explanation above.
rayryeng - Reinstate Monica
Glad I could help :-)
Luis Mendo
0

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
        )
    ))
)
asgallant
źródło
0

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.

NikoNyrh
źródło
0

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.

Xcali
źródło
0

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

Renzo
źródło