Normaliser un vecteur

28

Pour normaliser un vecteur est à elle échelle à une longueur de 1 ( un vecteur unitaire ), tout en maintenant la direction cohérente.

Par exemple, si nous voulions normaliser un vecteur à 3 composantes, u , nous trouverions d'abord sa longueur:

| u | = sqrt (u x 2 + u y 2 + u z 2 )

... puis redimensionnez chaque composant selon cette valeur pour obtenir un vecteur de longueur 1.

û = u ÷ | u |


Le défi

Votre tâche consiste à écrire un programme ou une fonction qui, étant donné une liste non vide d'entiers signés, l'interprète comme un vecteur et le normalise. Cela devrait fonctionner pour n'importe quel nombre de dimensions, par exemple (cas de test arrondis à deux décimales):

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

Règles:

  • Vous pouvez supposer que la liste de saisie:
    • Avoir au moins un élément non nul
    • Ne contient que des nombres dans la plage de virgule flottante standard de votre langue
  • Votre sortie doit être précise à au moins deux décimales . Le retour de fractions / valeurs symboliques de «précision infinie» est également autorisé, si c'est ainsi que votre langue stocke en interne les données.
  • Les soumissions doivent être soit un programme complet qui effectue des E / S, soit une fonction. Les soumissions de fonctions peuvent soit renvoyer une nouvelle liste, soit modifier la liste donnée en place.
  • Les fonctions / classes vectorielles intégrées sont autorisées. De plus, si votre langue a un type de vecteur qui prend en charge un nombre arbitraire de dimensions, vous pouvez en prendre une en entrée.

Il s'agit d'un concours de , vous devez donc viser à obtenir la solution la plus courte possible (en octets).

FlipTack
la source
Doit-il avoir au moins deux décimales pour chaque entrée possible (ce qui n'est pas possible pour tout type standard de valeurs à virgule flottante) ou uniquement pour les exemples que vous fournissez? Par exemple, la réponse de Steadybox fournit 2 décimales de précision pour tous vos tests, mais il utilise des nombres entiers pour la somme des carrés, ce qui bien sûr échoue pour presque toutes les entrées (par exemple [0,1, 0,1]).
Christoph
... maintenant nous attendons juste une langue avec une fonction
normalisée
Il devrait être d'au moins 2dp pour chaque entrée possible @Christoph
FlipTack
@FlipTack mais cela exclut pratiquement toutes les langues car les points flottants ont des exposants plus grands que la mantisse, ce qui signifie qu'ils n'ont pas toujours assez de précision pour avoir des décimales.
Christoph
Pourquoi le 6 du 4e exemple et le -6 du 5e ne se normalisent-ils respectivement à 1 et -1?
Mât

Réponses:

15

05AB1E , 4 octets

Code:

nOt/

Essayez-le en ligne!

Explication

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
Adnan
la source
9
n0t ce à quoi je m'attendais /
YSC
10

JavaScript (ES6), 31 octets

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

Cas de test

Arnauld
la source
9

J , 8 octets

%+/&.:*:

Essayez-le en ligne!

6 octets %|@j./fonctionne si le vecteur est au moins bidimensionnel .

FrownyFrog
la source
J'adore la façon d'obtenir l'ampleur.
cole
1
@cole 1 octet de plus:%1%:@#.*:
FrownyFrog
6
Pourriez-vous s'il vous plaît ajouter une explication pour les non-initiés en J?
MechMK1
% (diviser par) + / (somme) & .: (sous) *: (carré). + résume deux choses. + / résume une liste de choses. &: modifie l'opération précédente en appliquant d'abord l'opération suivante puis son inverse. % prend normalement deux arguments, mais (% f) est une fonction de x à x% (fx). La plupart des opérateurs travaillent automatiquement sur des listes.
Roman Odaisky
Et selon les mêmes principes, la fonction qui «normalise» un vecteur en ajoutant un tel nombre à chaque composant qu'ils additionnent à zéro est «- + /% #».
Roman Odaisky
8

Gelée , 5 3 octets

÷ÆḊ

Essayez-le en ligne! ou consultez la suite de tests

Économisé 2 octets grâce aux miles!

caird coinheringaahing
la source
3 octets avec÷ÆḊ
miles
@miles Huh, je n'ai jamais entendu parler de cette fonction intégrée. Merci
caird coinheringaahing
malheureusement, ce
module
6

C,  73  70 octets

Merci à @Christoph d'avoir enregistré un octet!

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

Essayez-le en ligne!

Steadybox
la source
+1. s=0,i=0au lieu d'en s=i=0enregistrer un
xanoetux
J'adore l'utilisation de s[-i]mais malheureusement, *--v/=sqrt(s);c'est 1 octet plus court.
Christoph
1
@xanoetux Merci, mais j'ai besoin d'initialiser les variables à l'intérieur de la fonction, car les fonctions doivent être réutilisables . En outre, en tant que variables globales, set isont automatiquement initialisés à 0. (Il s'avère que je n'ai pas besoin d'initialiser idans la fonction, car la fonction la laisse toujours à la valeur 0)
Steadybox
1
@Christoph Merci! Au départ, j'imprimais les valeurs de la fonction, j'avais donc besoin v[-i]d'obtenir les valeurs dans le bon ordre.
Steadybox
4

Python, 47 46 octets

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

Essayez-le en ligne!

PattuX
la source
3

CJam , 9 octets

{_:mhzf/}

Essayez-le en ligne!

Explication

_    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.
Martin Ender
la source
3

TI-Basic, 6 octets

Ans/√(sum(Ans2

Exécuter avec {1,2,3}:prgmNAME, où {1,2,3}est le vecteur à normaliser.

Divise chaque élément du vecteur par la racine carrée de la somme des carrés de ses éléments.

pizzapants184
la source
Nous avons la même réponse!
kamoroso94
@ kamoroso94 Oups! Je n'ai pas vu le vôtre quand j'ai posté ça. Si vous souhaitez ajouter l'explication de cela à votre réponse, je vais supprimer cela.
pizzapants184
Non, je vais juste retirer le mien. Vous mettez plus d'efforts dans votre réponse: P
kamoroso94
3

R , 23 octets

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

Essayez-le en ligne!

v%*%vcalcule le produit scalaire de v avec lui-même.
La fonction émettra un avertissement pour les vecteurs de longueur 2 ou supérieure.

Giuseppe
la source
2

MATL , 5 octets

t2&|/

Essayez-le en ligne!

Je ne suis pas entièrement sûr que ce soit le moyen le plus court de procéder. Tout d'abord, nous dupliquons l'entrée, puis sélectionnons le deuxième type de sortie de |(qui est soit abs, normsoit determinant). Enfin, nous divisons l'entrée par la norme.

Alternative pour 7 octets:

t2^sX^/
Stewie Griffin
la source
2

C ++ (gcc), 70 octets

Entrée par std::valarray<float>. Remplace le vecteur d'origine.

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

Essayez-le en ligne!

Colera Su
la source
Je suis juste à l'affût de codegolf de temps en temps, mais n'est-ce pas C ++ invalide, étant donné "#import", qui est une extension spécifique à Microsoft?
phresnel
@phresnel #importfonctionne également avec GCC, Clang et MinGW. Mais, oui, ce n'est pas du C ++ standard.
Steadybox
@phresnel J'ai oublié de spécifier gcc. Fixé.
Colera Su
2

APL (Dyalog) , 13 12 10 octets

1 octet enregistré grâce à @ Adám

2 octets enregistrés grâce à @ngn

⊢÷.5*⍨+.×⍨

Essayez-le en ligne!

Comment?

  ÷  .5*⍨  +.  ×⍨
u  ÷       Σ   u²
Uriel
la source
Entraînez-vous pour moins:⊢÷.5*⍨(+/×⍨)
Adám
@ Adám merci beaucoup! J'essaie depuis des heures, je n'ai pas pu faire de train pour travailler
Uriel
Nous devons faire quelque chose à ce sujet, car ce n'est vraiment pas si difficile. Lorsque vous avez une fonction monadique (autre que la fonction la plus à droite), commencez une parenthèse à sa gauche (ou utilisez-la si elle n'est pas dérivée). Autre que cela, il suffit d'échanger et pour et : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨)
Adám
(+/×⍨)->+.×⍨
ngn
1

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

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

Essayez-le en ligne!

+64 octets pour le using System;using System.Collections.Generic;using System.Linq;

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

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;}

Essayez-le en ligne!

+13 octets pour using System;

L'approche non Linq

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;
}
Ayb4btu
la source
1

Pip , 10 octets

9 octets de code, +1 pour l' -pindicateur.

g/RT$+g*g

Prend le vecteur comme arguments de ligne de commande séparés. Essayez-le en ligne!

Comment ça marche

      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)
DLosc
la source
1

Pyth, 5 octets

cR.aQ

Essayez-le en ligne: Test Suite

Explication:

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
Jakube
la source
1

Perl 6 , 25 octets

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

Essayez-le en ligne!

$_, l'argument de liste de la fonction, est divisé élément »/»par élément ( ) par la racine carrée de la somme des carrés des éléments ( »²).

Sean
la source
1

Rubis, 39 35 octets

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

-4 octets grâce à G B.

m-chrzan
la source
1
Économisez quelques octets en utilisant sum{...}au lieu demap{...}.sum
GB
0

APL NARS 12 caractères

f←{⍵÷√+/⍵*2}
RosLuP
la source
Vous n'avez pas à compter f← dans votre nombre d'octets, car vous pouvez utiliser les dfns sans lui. Soit dit en passant, est-ce qu'un seul octet dans NARS? Je ne le connais pas, alors demandez simplement
Uriel
@Uriel Nars Apl dans les quelques cas que je connais écrirait avec Unicode donc le nombre d'octets devrait être 12x2
RosLuP
0

Google Sheets, 65 octets

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

La liste des entrées est en colonne Aavec une entrée par cellule. C'est ainsi que les feuilles de calcul utiliseraient normalement des listes. Malheureusement, cela aboutirait normalement à une longue liste ,0,0,0,0,0,....à la fin, nous devons donc ignorer ceux qui ont la If Blank then Blank else Mathlogique.

Si tout était dans une seule cellule, la solution serait de 95 octets:

=ArrayFormula(TextJoin(",",1,If(Split(A1,",")="","",Split(A1,",")/Sqrt(Sumsq(Split(A1,","))))))
Ingénieur Toast
la source
0

Swift 4, 44 octets

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

Recalcule la norme vectorielle pour chaque composant, mais au moins c'est laconique!

Alexander - Rétablir Monica
la source