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


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

9
n0t tego się spodziewałem /
YSC

10

JavaScript (ES6), 31 bajtów

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

Przypadki testowe



9

J , 8 bajtów

%+/&.:*:

Wypróbuj online!

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


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



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!


+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



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.

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.


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.



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^/




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!


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

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²

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


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)

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

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 ( »²).


1

Rubin, 39 35 bajtów

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

-4 bajty dzięki G B.


1
Zaoszczędź niektóre bajty, używając sum{...}zamiastmap{...}.sum
GB

0

APL NARS 12 znaków

f←{⍵÷√+/⍵*2}

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,","))))))

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!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.