28
\$\begingroup\$

To normalize a vector is to scale it to a length of 1 (a unit vector), whilst keeping the direction consistent.

For example, if we wanted to normalize a vector with 3 components, u, we would first find its length:

|u| = sqrt(ux2 + uy2 + uz2)

...and then scale each component by this value to get a length 1 vector.

û = u ÷ |u|


The Challenge

Your task is to write a program or function which, given a non-empty list of signed integers, interprets it as a vector, and normalizes it. This should work for any number of dimensions, for example (test cases rounded to two decimal places):

[20]           -> [1]
[-5]           -> [-1]
[-3, 0]        -> [-1, 0]
[5.5, 6, -3.5] -> [0.62, 0.68, -0.40]
[3, 4, -5, -6] -> [0.32, 0.43, -0.54, -0.65]
[0, 0, 5, 0]   -> [0, 0, 1, 0]

Rules:

  • You can assume the input list will:
    • Have at least one non-zero element
    • Only contain numbers within your language's standard floating point range
  • Your output should be accurate to at least two decimal places. Returning "infinite precision" fractions / symbolic values is also allowed, if this is how your language internally stores the data.
  • Submissions should be either a full program which performs I/O, or a function. Function submissions can either return a new list, or modify the given list in place.
  • Builtin vector functions/classes are allowed. Additionally, if your language has a vector type which supports an arbitrary number of dimensions, you can take one of these as input.

This is a contest, so you should aim to achieve the shortest solution possible (in bytes).

\$\endgroup\$
  • \$\begingroup\$ Does it have to have at least two decimal places for every possible input (which is not possible for any standard type of floating point values) or only for the examples you provide? E.g. Steadybox's answer provides 2 decimal places of precision for all your test but he uses ints for the sum of squares which of course fails for almost all inputs (e.g. [0.1, 0.1]). \$\endgroup\$ – Christoph Nov 27 '17 at 11:07
  • \$\begingroup\$ ... now we just wait for a lang with built-in norm function mapped to one char... \$\endgroup\$ – vaxquis Nov 27 '17 at 13:55
  • \$\begingroup\$ It should be to at least 2dp for every possible input @Christoph \$\endgroup\$ – FlipTack Nov 27 '17 at 16:09
  • \$\begingroup\$ @FlipTack but that rules out basically all languages because floatings points have bigger exponents than mantissa which means they do not always have enough precision to have any decimal places. \$\endgroup\$ – Christoph Nov 27 '17 at 19:34
  • \$\begingroup\$ Why don't the 6 in the 4th example and the -6 in the 5th respectively normalize to 1 and -1? \$\endgroup\$ – Mast Nov 28 '17 at 13:03

35 Answers 35

15
\$\begingroup\$

05AB1E, 4 bytes

Code:

nOt/

Try it online!

Explanation

n     # Square each element of the input
 O    # Sum all elements
  t   # Take the square root of the sum
   /  # Divide each element by the square root of the sum
\$\endgroup\$
  • 9
    \$\begingroup\$ n0t what I expected / \$\endgroup\$ – YSC Nov 27 '17 at 10:19
10
\$\begingroup\$

JavaScript (ES6), 31 bytes

a=>a.map(n=>n/Math.hypot(...a))

Test cases

let f =

a=>a.map(n=>n/Math.hypot(...a))

console.log(JSON.stringify(f([20]          ))) // -> [1]
console.log(JSON.stringify(f([-5]          ))) // -> [-1]
console.log(JSON.stringify(f([-3, 0]       ))) // -> [-1, 0]
console.log(JSON.stringify(f([5.5, 6, -3.5]))) // -> [0.62, 0.68, -0.40]
console.log(JSON.stringify(f([3, 4, -5, -6]))) // -> [0.32, 0.43, -0.54, -0.65]
console.log(JSON.stringify(f([0, 0, 5, 0]  ))) // -> [0, 0, 1, 0]

\$\endgroup\$
10
\$\begingroup\$

Mathematica, 9 bytes

Normalize

Try it online!

\$\endgroup\$
  • 12
    \$\begingroup\$ Or #/Norm@#& for the same byte count. \$\endgroup\$ – Martin Ender Nov 26 '17 at 22:03
9
\$\begingroup\$

J, 8 bytes

%+/&.:*:

Try it online!

6 bytes %|@j./ works if the vector is at least 2-dimensional.

\$\endgroup\$
  • \$\begingroup\$ Love the way of getting the magnitude. \$\endgroup\$ – cole Nov 26 '17 at 22:54
  • 1
    \$\begingroup\$ @cole 1 byte longer: %1%:@#.*: \$\endgroup\$ – FrownyFrog Nov 27 '17 at 4:10
  • 6
    \$\begingroup\$ Could you please add an explanation for the uninitiated in J? \$\endgroup\$ – MechMK1 Nov 27 '17 at 7:49
  • \$\begingroup\$ % (divide by) +/ (sum) &.: (under) *: (square). + sums two things. +/ sums a list of things. &.: modifies the preceding operation by applying the following operation first and its inverse afterwards. % normally takes two arguments, but (% f) is a function from x to x % (f x). Most operators automagically work on lists. \$\endgroup\$ – Roman Odaisky Nov 28 '17 at 21:20
  • \$\begingroup\$ And by the same principles, the function that “normalizes” a vector by adding such a number to each component that they sum to zero is “- +/ % #”. \$\endgroup\$ – Roman Odaisky Nov 28 '17 at 21:26
8
\$\begingroup\$

Jelly, 5 3 bytes

÷ÆḊ

Try it online!, or see the test suite

Saved 2 bytes thanks to miles!

\$\endgroup\$
  • \$\begingroup\$ 3 bytes with ÷ÆḊ \$\endgroup\$ – miles Nov 26 '17 at 23:46
  • \$\begingroup\$ @miles Huh, never knew about that builtin. Thanks \$\endgroup\$ – caird coinheringaahing Nov 27 '17 at 0:12
  • \$\begingroup\$ unfortunately that built-in gives +ve mod for scalars per TIO examplelike absolute value .. the problem requested keeping the sign \$\endgroup\$ – jayprich May 1 '18 at 15:34
6
\$\begingroup\$

Octave, 13 bytes

@(x)x/norm(x)

Try it online!

\$\endgroup\$
6
\$\begingroup\$

C,  73  70 bytes

Thanks to @Christoph for saving a byte!

s,i;f(v,n)float*v;{for(s=0;i++<n;)s+=*v**v++;for(;--i;)*--v/=sqrt(s);}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ +1. s=0,i=0 instead of s=i=0 saves one \$\endgroup\$ – xanoetux Nov 27 '17 at 6:10
  • \$\begingroup\$ I love the use of s[-i]but sadly *--v/=sqrt(s); is 1 byte shorter. \$\endgroup\$ – Christoph Nov 27 '17 at 11:08
  • 1
    \$\begingroup\$ @xanoetux Thanks, but I need to initialize the variables inside the function, because functions need to be reusable. Besides, as global variables, s and i are automatically initialized to 0. (Turns out I don't need to initialize i in the function, because the function always leaves it at value 0) \$\endgroup\$ – Steadybox Nov 27 '17 at 11:30
  • 1
    \$\begingroup\$ @Christoph Thanks! I was initially printing the values from the function, so I needed v[-i] to get the values in correct order. \$\endgroup\$ – Steadybox Nov 27 '17 at 11:31
4
\$\begingroup\$

Python, 47 46 bytes

lambda v:[e/sum(e*e for e in v)**.5for e in v]

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Julia, 9 bytes

normalize

Try it online!

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

CJam, 9 bytes

{_:mhzf/}

Try it online!

Explanation

_    e# Duplicate input.
:mh  e# Fold hypothenuse-length over the vector. This gives the norm, unless the vector
     e# has only one component, in which case it just gives that component.
z    e# Abs. For the case of a single negative vector component.
f/   e# Divide each vector component by the norm.
\$\endgroup\$
3
\$\begingroup\$

TI-Basic, 6 bytes

Ans/√(sum(Ans2

Run with {1,2,3}:prgmNAME, where {1,2,3} is the vector to be normalized.

Divides each element in the vector by the square root of the sum of the squares of its elements.

\$\endgroup\$
  • \$\begingroup\$ We got the same answer! \$\endgroup\$ – kamoroso94 Nov 27 '17 at 3:24
  • \$\begingroup\$ @kamoroso94 Whoops! Didn't see yours when I posted this. If you want to add the explanation from this to your answer I'll delete this. \$\endgroup\$ – pizzapants184 Nov 27 '17 at 3:30
  • \$\begingroup\$ Nah I'll just remove mine. You put more effort into your answer :P \$\endgroup\$ – kamoroso94 Nov 27 '17 at 5:48
3
\$\begingroup\$

R, 23 bytes

function(v)v/(v%*%v)^.5

Try it online!

v%*%v computes the dot product of v with itself.
The function will issue a warning for length 2 or greater vectors.

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

Java (OpenJDK 8), 57 bytes

v->v.stream().map(x->x/v.stream().reduce(0d,Math::hypot))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

MATL, 5 bytes

t2&|/

Try it online!

I'm not entirely sure this is the shortest way to do this. First, we duplicate the input, then select the second output type of | (which is either abs, norm or determinant). Finally, we divide the input by the norm.

Alternative for 7 bytes:

t2^sX^/
\$\endgroup\$
2
\$\begingroup\$

Haskell, 29 bytes

f x=map(/sqrt(sum$(^2)<$>x))x

Try it online!

Or for 1 byte more pointfree: map=<<flip(/).sqrt.sum.map(^2)

\$\endgroup\$
2
\$\begingroup\$

Funky, 42 bytes

a=>(d=a::map)(c=>c/d(b=>b^2)::reduce@+^.5)

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Ohm v2, 5 bytes

D²Σ¬/

Try it online!

\$\endgroup\$
2
\$\begingroup\$

C++ (gcc), 70 bytes

Input by std::valarray<float>. Overwrites the original vector.

#import<valarray>
int f(std::valarray<float>&a){a/=sqrt((a*a).sum());}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I am just lurking codegolf every now and then, but isn't this invalid C++, given "#import", which is a Microsoft specific extension? \$\endgroup\$ – phresnel Nov 27 '17 at 11:01
  • \$\begingroup\$ @phresnel #import works at least with GCC, Clang and MinGW, too. But, yeah, it's not standard C++. \$\endgroup\$ – Steadybox Nov 27 '17 at 11:36
  • \$\begingroup\$ @phresnel I forgot to specify gcc. Fixed. \$\endgroup\$ – Colera Su Nov 27 '17 at 12:30
2
\$\begingroup\$

Common Lisp, 69 bytes

(lambda(v)(mapcar(lambda(x)(/ x(sqrt(loop as y in v sum(* y y)))))v))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog), 13 12 10 bytes

1 byte saved thanks to @Adám

2 bytes saved thanks to @ngn

⊢÷.5*⍨+.×⍨

Try it online!

How?

⊢  ÷  .5*⍨  +.  ×⍨
u  ÷    √   Σ   u²
\$\endgroup\$
  • \$\begingroup\$ Train for less: ⊢÷.5*⍨(+/×⍨) \$\endgroup\$ – Adám Nov 26 '17 at 22:15
  • \$\begingroup\$ @Adám thanks alot! I've been trying for hours, couldn't get any train to work \$\endgroup\$ – Uriel Nov 26 '17 at 22:27
  • \$\begingroup\$ We should do something about that, as it is really not so hard. When you have a monadic function (other than the rightmost one), begin a parenthesis to its left (or use a if it isn't derived). Other than that, just swap and for and : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨) \$\endgroup\$ – Adám Nov 27 '17 at 10:13
  • \$\begingroup\$ (+/×⍨) -> +.×⍨ \$\endgroup\$ – ngn Nov 28 '17 at 7:15
1
\$\begingroup\$

Husk, 8 7 bytes

´(Ṁ/√ṁ□

Try it online!

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

C# (.NET Core), 51+64=115 bytes

v=>v.Select(d=>d/Math.Sqrt(v.Select(x=>x*x).Sum()))

Try it online!

+64 bytes for the using System;using System.Collections.Generic;using System.Linq;

C# (.NET Core), 94+13=107 bytes

v=>{var m=0d;foreach(var x in v)m+=x*x;for(int i=0;i<v.Length;)v[i++]/=Math.Sqrt(m);return v;}

Try it online!

+13 bytes for using System;

The non-Linq approach

DeGolfed

v=>{
    var m=0d;
    foreach (var x in v)
        m+=x*x;

    for (int i=0; i < v.Length;)
        v[i++] /= Math.Sqrt(m);

    return v;
}
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 45 + 1 (-a) = 46 bytes

say$_/sqrt eval join'+',map"($_)**2",@F for@F

Try it online!

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

Pip, 10 bytes

9 bytes of code, +1 for -p flag.

g/RT$+g*g

Takes the vector as separate command-line arguments. Try it online!

How it works

      g*g  Arglist, multiplied by itself itemwise
    $+     Sum
  RT       Square root
g/         Divide arglist itemwise by that scalar
           Result is autoprinted (-p flag to format as list)
\$\endgroup\$
1
\$\begingroup\$

Pyth, 5 bytes

cR.aQ

Try it online: Test Suite

Explanation:

cR.aQQ   implicit Q at the end
c        divide
 R   Q   each element of the input
  .aQ    by the L2 norm of the input vector
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 25 bytes

{$_ »/»sqrt sum $_»²}

Try it online!

$_, the list argument to the function, is divided elementwise (»/») by the square root of the sum of the squares of the elements (»²).

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

Ruby, 39 35 bytes

->v{v.map{|x|x/v.sum{|x|x*x}**0.5}}

-4 bytes thanks to G B.

\$\endgroup\$
  • 1
    \$\begingroup\$ Save some bytes by using sum{...} instead of map{...}.sum \$\endgroup\$ – G B Nov 27 '17 at 11:34
0
\$\begingroup\$

APL NARS 12 Characters

f←{⍵÷√+/⍵*2}
\$\endgroup\$
  • \$\begingroup\$ You don't have to count f← in your byte count, since you can use the dfns without it. By the way, is a single byte in NARS? I'm not familiar with it, so just asking \$\endgroup\$ – Uriel Nov 26 '17 at 22:48
  • \$\begingroup\$ @Uriel Nars Apl in the few I know would write with Unicode so number of bytes should be 12x2 \$\endgroup\$ – RosLuP Nov 27 '17 at 6:01
0
\$\begingroup\$

Google Sheets, 65 bytes

=ArrayFormula(TextJoin(",",1,If(A:A="","",A:A/Sqrt(Sumsq(A:A)))))

The input list is in column A with one entry per cell. This is how spreadsheets would normally use lists. Unfortunately, this would normally result in a long list of ,0,0,0,0,0,.... at the end so we have to ignore those with the If Blank then Blank else Math logic.

If it was all in one cell, instead, the solution would be 95 bytes:

=ArrayFormula(TextJoin(",",1,If(Split(A1,",")="","",Split(A1,",")/Sqrt(Sumsq(Split(A1,","))))))
\$\endgroup\$
0
\$\begingroup\$

Swift 4, 44 bytes

{a in a.map{$0/sqrt(a.reduce(0){$0+$1*$1})}}

Recalculates the vector norm for every component, but at least it's terse!

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