# Calculate the vector component

## Challenge

Assume two vectors $$\\mathbf{a} = (a_1,a_2,\cdots,a_n)\$$ and $$\\mathbf{b} = (b_1,b_2,\cdots,b_n)\$$ are given in an $$\n\$$-dimensional space, where at least one of $$\b_1,\cdots,b_n\$$ is nonzero. Then $$\\mathbf{a}\$$ can be uniquely decomposed into two vectors, one being a scalar multiple of $$\\mathbf{b}\$$ and one perpendicular to $$\\mathbf{b}\$$:

$$\mathbf{a} = \mathbf{b}x + \mathbf{b^\perp}\text{, where }\mathbf{b^\perp} \cdot \mathbf{b}=0.$$

Given $$\\mathbf{a}\$$ and $$\\mathbf{b}\$$ as input, find the value of $$\x\$$.

This can be also thought of as the following: Imagine a line passing through the origin and the point $$\\mathbf{b}\$$. Then draw a perpendicular line on it that passes through the point $$\\mathbf{a}\$$, and denote the intersection $$\\mathbf{c}\$$. Finally, find the value of $$\x\$$ that satisfies $$\\mathbf{c}=\mathbf{b}x\$$.

You can use an explicit formula too (thanks to @xnor), which arises when calculating the projection:

$$x=\frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{b} \cdot \mathbf{b}}$$

Standard rules apply. The shortest code in bytes wins.

## Example

Here is an example in 2D space, where a=(2,7) and b=(3,1). Observe that (2,7) = (3.9,1.3) + (-1.9,5.7) where (3.9,1.3) is equal to 1.3b and (-1.9,5.7) is perpendicular to b. Therefore, the expected answer is 1.3. ## Test cases

a         b          answer
(2,7)     (3,1)      1.3
(2,7)     (-1,3)     1.9
(3,4,5)   (0,0,1)    5
(3,4,5)   (1,1,1)    4
(3,4,5)   (1,-1,-1)  -2
(3,4,5,6) (1,-2,1,2) 1.2

• Will the values of the input vectors always be integers? Jun 10, 2020 at 12:23
• @Noodle9 No, it may have non-integers. Jun 10, 2020 at 13:22
• Can we take the dimension $n$ as additional argument? Jun 10, 2020 at 14:20
• @KevinCruijssen No, unless you're using pointer+length input. Jun 10, 2020 at 22:52

# APL (Dyalog Unicode), 1 byteSBCS

⌹


Check all test cases! When used dyadically, X ⌹ Y solves the least squares* system $$\Ya = X\$$ for a result $$\a\$$ of the appropriate shape, e.g.:

• if $$\Y\$$ is a matrix and $$\X\$$ is a vector, we try to solve a linear system of equations.
• if $$\Y\$$ and $$\X\$$ are matrices, we compute $$\Y\$$'s (pseudo-)inverse and multiply it on the left of $$\X\$$.
• when both $$\X\$$ and $$\Y\$$ are vectors, the least squares formulation reduces to what we want, namely

$$\frac{X \cdot Y}{||Y||^2}$$

*the least squares system $$\Ya = X\$$ can be understood as "what should $$\a\$$ be such that $$\Ya\$$ is as close as can be to $$\X\$$?", where closeness is measured with the usual L2 distance.

• We have a winner. I very much doubt any language can do this in 0 bytes.
Jun 10, 2020 at 8:24
• If I open a file and I see that thing in it, I will mark it as virus. Jun 12, 2020 at 3:40
• @darksky a couple of months ago I would've done the exact same thing
– RGS
Jun 12, 2020 at 6:51

-1 byte thanks to @xnor!

(!)b=sum.zipWith(*)b
a#b=a!b/b!b


Try it online!

# Coconut, 35 bytes

(a,b)->p(a,b)/p(b,b)
p=sum..map\$(*)


Try it online!

• Save a byte by making definition of ! a bit less pointfree: (!)v=sum.zipWith(*)v
– xnor
Jun 10, 2020 at 19:40

# R, 24 bytes

function(a,b)a%*%b/b%*%b


Try it online!

• lm(a~b-1) does slightly better. Jun 13, 2020 at 9:18
• @Xi'an that's great, and it's also a principally different approach, so I'd suggest you to post it as a separate answer. Jun 13, 2020 at 10:47

# Python 3 + numpy, 20 bytes

lambda a,b:a@b/(b@b)


Try it online!

# MATL, 2 bytes

Y\


Try it online!

Least squares approach such as used in the APL answer.

# Jelly, 6 5 bytes

ḋ÷@ḋ


Try it online!

Simple translation of the given formula. Takes $$\\mathbf{b}\$$ as the left argument and $$\\mathbf{a}\$$ as the right argument.

ḋ        The dot product of b and
itself,
÷@     dividing
ḋ    the dot product of b and a.


# Charcoal, 21 18 bytes

Ｆ²⊞υΣＥＡ×κ§θλＩ∕⊟υ⊟υ


Try it online! Link is to verbose version of code. Takes inputs in the order b, a. Explanation:

Ｆ²


Repeat twice...

⊞υΣＥＡ×κ§θλ


Input a vector, take its dot product with b and push the result to the predefined empty list.

Ｉ∕⊟υ⊟υ


Retrieve the dot products and take their quotient.

• The previous version was lost because I happened to slip under the grace edit period by a couple of seconds, but you didn't miss much, just a one-byte golf from taking inputs in reverse order and separate a two-byte golf.
– Neil
Jun 10, 2020 at 10:42
• 10 bytes using the newer version of Charcoal on ATO: Ｉ∕Σ×θηΣ×ηη Attempt This Online Link is to verbose version of code. Does not take inputs in reverse order.
– Neil
Sep 25, 2022 at 21:25

# 05AB1E, 6 bytes

*OInO/


Implements the given formula:

$$x = \frac{a_1\times b_1 + a_2\times b_2 + \dots + a_n\times b_n}{b_1^2 + b_2^2 + \dots + b_n^2}$$

Explanation:

*       # Multiply the values at the same indices in the two (implicit) input-lists
O      # Sum this list
I     # Push the second input-list again
n    # Square each value
O   # Take the sum of that
/  # And divide the two values
# (after which the result is output implicitly)


# C (gcc), 84 74 73 bytes

Saved 10 bytes thanks to dingledooper!!!

Saved a byte thanks to ceilingcat!!!

float f(a,b,n)float*a,*b;{float x,y;for(;n--;y+=*b**b++)x+=*a++**b;x/=y;}


Try it online!

Inputs two pointers to vectors $$\a,b\$$ and their dimension $$\n\$$ and returns their component..

Uses given formula:

$$x = \frac{a_0\cdot b_0 + a_1\cdot b_1 + \dots + a_{n-1}\cdot b_{n-1}}{b_0^2 + b_1^2 + \dots + b_{n-1}^2}$$

# Wolfram Language (Mathematica), 9 bytes

#.#2/#.#&


Try it online! Pure function. Takes b followed by a as input and returns a rational number as output. It just directly uses Mathematica's notation for the dot product.

# Fortran >= 95, 66 bytes

Taking advantage of implicit typing for the return type.

function x(a,b)
real a(:),b(:)
x=dot_product(a,b)/norm2(b)**2
end


# [R], 22 bytes

Taking advantage of a resident regression function, lm

function(a,b)lm(a~b-1)


Try it online!

# Java 10, 84 74 bytes

a->b->{float A=0,B=0;int i=0;for(var t:b){A+=a[i++]*t;B+=t*t;}return A/B;}


Try it online.

# Japt v2.0a0, 9 bytes

í*V x÷Vx²


Try it