Normalizuj wektor

28

Aby znormalizować wektor, należy przeskalować go do długości 1 ( wektor jednostkowy ), zachowując spójność kierunku.

Na przykład, jeśli chcielibyśmy znormalizować wektor składający się z 3 składników, u najpierw ustalilibyśmy jego długość:

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

... a następnie przeskaluj każdy składnik według tej wartości, aby uzyskać wektor długości 1.

û = u ÷ | u |


Wyzwanie

Twoim zadaniem jest napisanie programu lub funkcji, która biorąc pod uwagę niepustą listę liczb całkowitych, interpretuje ją jako wektor i normalizuje. Powinno to działać dla dowolnej liczby wymiarów, na przykład (przypadki testowe zaokrąglone do dwóch miejsc po przecinku):

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

Zasady:

  • Możesz założyć, że lista wejściowa:
    • Mieć co najmniej jeden niezerowy element
    • Zawiera tylko liczby ze standardowego zakresu zmiennoprzecinkowego w Twoim języku
  • Wynik powinien być dokładny do co najmniej dwóch miejsc po przecinku . Dopuszczalne jest również zwracanie ułamków / wartości symbolicznych „nieskończonej precyzji”, jeśli w ten sposób dane są przechowywane wewnętrznie przez Twój język.
  • Zgłoszenia powinny być albo pełnym programem wykonującym operacje we / wy, albo funkcją. Przesłanie funkcji może albo zwrócić nową listę, albo zmodyfikować podaną listę.
  • Wbudowane funkcje / klasy wektorowe są dozwolone. Dodatkowo, jeśli twój język ma typ wektorowy, który obsługuje dowolną liczbę wymiarów, możesz wziąć jeden z nich jako dane wejściowe.

Jest to konkurs , więc powinieneś dążyć do jak najkrótszego możliwego rozwiązania (w bajtach).

FlipTack
źródło
Czy musi mieć co najmniej dwa miejsca po przecinku na każde możliwe dane wejściowe (co nie jest możliwe dla żadnego standardowego typu wartości zmiennoprzecinkowych), czy tylko dla podanych przykładów? Np. Odpowiedź Steadyboksa zapewnia 2 miejsca dziesiętne precyzji dla wszystkich testów, ale używa liczb całkowitych do sumy kwadratów, co oczywiście nie powiedzie się dla prawie wszystkich danych wejściowych (np. [0,1, 0,1]).
Christoph
... teraz tylko czekamy na język z wbudowaną funkcją
normowania
Powinien wynosić co najmniej 2dp za każde możliwe wejście @Christoph
FlipTack
@FlipTack, ale wyklucza to w zasadzie wszystkie języki, ponieważ zmiennoprzecinkowe mają większe wykładniki niż mantysa, co oznacza, że ​​nie zawsze mają wystarczającą precyzję, aby mieć miejsca dziesiętne.
Christoph
Dlaczego 6 w czwartym przykładzie i -6 w piątym odpowiednio nie normalizują się do 1 i -1?
Maszt

Odpowiedzi:

15

05AB1E , 4 bajty

Kod:

nOt/

Wypróbuj online!

Wyjaśnienie

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
źródło
9
n0t tego się spodziewałem /
YSC
10

JavaScript (ES6), 31 bajtów

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

Przypadki testowe

Arnauld
źródło
10

Mathematica, 9 bajtów

Normalize

Wypróbuj online!

J42161217
źródło
12
Lub #/Norm@#&dla tej samej liczby bajtów.
Martin Ender
9

J , 8 bajtów

%+/&.:*:

Wypróbuj online!

6 bajtów %|@j./działa, jeśli wektor jest co najmniej dwuwymiarowy .

FrownyFrog
źródło
Uwielbiam sposób na uzyskanie wielkości.
cole
1
@cole 1 bajt dłużej:%1%:@#.*:
FrownyFrog
6
Czy możesz dodać wyjaśnienie dla niewtajemniczonych w J?
MechMK1,
% (podziel przez) + / (suma) i .: (poniżej) *: (kwadrat). + sumuje dwie rzeczy. + / podsumowuje listę rzeczy. & .: modyfikuje poprzednią operację, stosując najpierw następującą operację, a następnie jej odwrotność. % zwykle przyjmuje dwa argumenty, ale (% f) jest funkcją od x do x% (fx). Większość operatorów automagicznie pracuje na listach.
Roman Odaisky
Zgodnie z tymi samymi zasadami funkcja, która „normalizuje” wektor przez dodanie takiej liczby do każdego składnika, który sumuje do zera, to „- + /% #”.
Roman Odaisky
8

Galaretka , 5 3 bajtów

÷ÆḊ

Wypróbuj online! lub zobacz pakiet testowy

Zaoszczędzone 2 bajty dzięki kilometrom!

Cairney Coheringaahing
źródło
3 bajty z÷ÆḊ
milami
@miles Huh, nigdy nie wiedziałem o tym wbudowanym. Dzięki
caird coinheringaahing
niestety wbudowany
moduł
6

C,  73  70 bajtów

Dzięki @Christoph za uratowanie bajtu!

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

Wypróbuj online!

Steadybox
źródło
+1. s=0,i=0zamiast s=i=0ratuje jeden
xanoetux
Uwielbiam używać, s[-i]ale niestety *--v/=sqrt(s);jest o 1 bajt krótszy.
Christoph
1
@xanoetux Dzięki, ale muszę zainicjować zmienne wewnątrz funkcji, ponieważ funkcje muszą być wielokrotnego użytku . Poza tym, jako zmienne globalne si isą automatycznie inicjowane na 0. (Okazuje się, że nie muszę inicjować iw funkcji, ponieważ funkcja zawsze pozostawia wartość 0)
Steadybox
1
@Christoph Thanks! Początkowo drukowałem wartości z funkcji, więc musiałem v[-i]uzyskać wartości we właściwej kolejności.
Steadybox
4

Python, 47 46 bajtów

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

Wypróbuj online!

PattuX
źródło
3

CJam , 9 bajtów

{_:mhzf/}

Wypróbuj online!

Wyjaśnienie

_    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
źródło
3

TI-Basic, 6 bajtów

Ans/√(sum(Ans2

Uruchom z {1,2,3}:prgmNAME, gdzie {1,2,3}jest wektor do znormalizowania.

Dzieli każdy element w wektorze przez pierwiastek kwadratowy z sumy kwadratów jego elementów.

pizzapanty184
źródło
Mamy tę samą odpowiedź!
kamoroso94
@ kamoroso94 Whoops! Nie widziałem twojego, kiedy to opublikowałem. Jeśli chcesz dodać wyjaśnienie tego do swojej odpowiedzi, usunę to.
pizzapants184
Nie, po prostu usunę moje.
Wkładasz
3

R , 23 bajty

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

Wypróbuj online!

v%*%voblicza iloczyn iloczynu v z samym sobą.
Ta funkcja wyświetli ostrzeżenie dla wektorów o długości 2 lub większej.

Giuseppe
źródło
2

MATL , 5 bajtów

t2&|/

Wypróbuj online!

Nie jestem do końca pewien, czy jest to najkrótszy sposób na zrobienie tego. Najpierw powielamy dane wejściowe, a następnie wybieramy drugi typ danych wyjściowych |(którym jest albo abs, normalbo determinant). Wreszcie dzielimy dane wejściowe przez normę.

Alternatywa dla 7 bajtów:

t2^sX^/
Stewie Griffin
źródło
2

C ++ (gcc), 70 bajtów

Wejście od std::valarray<float>. Zastępuje oryginalny wektor.

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

Wypróbuj online!

Colera Su
źródło
Czaję tylko od czasu do czasu codegolf, ale czy to nie jest nieprawidłowe C ++, biorąc pod uwagę „#import”, które jest specyficznym rozszerzeniem Microsoft?
fresnel
@ phresnel #importwspółpracuje przynajmniej z GCC, Clang i MinGW. Ale tak, to nie jest standardowy C ++.
Steadybox
@ phresnel Zapomniałem podać gcc. Naprawiony.
Colera Su
2

Common Lisp, 69 bajtów

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

Wypróbuj online!

Renzo
źródło
2

APL (Dyalog) , 13 12 10 bajtów

1 bajt zapisany dzięki @ Adám

2 bajty zapisane dzięki @ngn

⊢÷.5*⍨+.×⍨

Wypróbuj online!

W jaki sposób?

  ÷  .5*⍨  +.  ×⍨
u  ÷       Σ   u²
Uriel
źródło
Trenuj za mniej:⊢÷.5*⍨(+/×⍨)
Adám
@ Adám dzięki bardzo! Próbowałem od wielu godzin, nie udało mi się dostać pociągu do pracy
Uriel
Powinniśmy coś z tym zrobić, ponieważ tak naprawdę nie jest to takie trudne. Jeśli masz funkcję monadyczną (inną niż skrajnie prawa), rozpocznij nawias po lewej stronie (lub użyj, jeśli nie jest wyprowadzony). Poza tym po prostu zamień i na i : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨)
Adám
(+/×⍨)->+.×⍨
ngn
1

C # (.NET Core) , 51 + 64 = 115 bajtów

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

Wypróbuj online!

+64 bajty dla using System;using System.Collections.Generic;using System.Linq;

C # (.NET Core) , 94 + 13 = 107 bajtów

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

Wypróbuj online!

+13 bajtów dla using System;

Podejście inne niż 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
źródło
1

Pip , 10 bajtów

9 bajtów kodu, +1 dla -pflagi.

g/RT$+g*g

Traktuje wektor jako osobne argumenty wiersza polecenia. Wypróbuj online!

Jak to działa

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

Pyth, 5 bajtów

cR.aQ

Wypróbuj online: pakiet testowy

Wyjaśnienie:

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

Perl 6 , 25 bajtów

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

Wypróbuj online!

$_, argument listy funkcji jest podzielony elementarnie ( »/») przez pierwiastek kwadratowy z sumy kwadratów elementów ( »²).

Sean
źródło
1

Rubin, 39 35 bajtów

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

-4 bajty dzięki G B.

m-chrzan
źródło
1
Zaoszczędź niektóre bajty, używając sum{...}zamiastmap{...}.sum
GB
0

APL NARS 12 znaków

f←{⍵÷√+/⍵*2}
RosLuP
źródło
Nie musisz liczyć f← swojej liczby bajtów, ponieważ bez niej możesz używać dfns. Nawiasem mówiąc, czy w NARS jest jeden bajt? Nie jestem z tym zaznajomiony, więc po prostu pytam
Uriel
@Uriel Nars Apl w nielicznych, o których wiem, że napisałbym w Unicode, więc liczba bajtów powinna wynosić 12
x 2
0

Arkusze Google, 65 bajtów

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

Lista wejściowa jest w kolumnie Az jednym wpisem na komórkę. W ten sposób arkusze kalkulacyjne normalnie używają list. Niestety zwykle powoduje to długą listę ,0,0,0,0,0,....na końcu, więc musimy zignorować If Blank then Blank else Mathlogikę.

Gdyby wszystko było w jednej komórce, rozwiązaniem byłoby 95 bajtów:

=ArrayFormula(TextJoin(",",1,If(Split(A1,",")="","",Split(A1,",")/Sqrt(Sumsq(Split(A1,","))))))
Inżynier Toast
źródło
0

Szybkie 4, 44 bajty

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

Ponownie oblicza normę wektorową dla każdego komponentu, ale przynajmniej jest to zwięzłe!

Alexander - Przywróć Monikę
źródło