Normalizza un vettore


28

Per normalizzare un vettore è in scala ad una lunghezza di 1 ( un vettore unitario ), mantenendo la direzione coerente.

Ad esempio, se volessimo normalizzare un vettore con 3 componenti, u , troveremmo prima la sua lunghezza:

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

... e quindi ridimensionare ciascun componente di questo valore per ottenere un vettore di lunghezza 1.

û = u ÷ | u |


La sfida

Il tuo compito è scrivere un programma o una funzione che, dato un elenco non vuoto di numeri interi con segno, lo interpreta come un vettore e lo normalizzi. Questo dovrebbe funzionare per qualsiasi numero di dimensioni, ad esempio (casi di test arrotondati al secondo decimale):

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

Regole:

  • Puoi presumere che l'elenco di input:
    • Avere almeno un elemento diverso da zero
    • Contiene solo numeri all'interno dell'intervallo standard in virgola mobile della tua lingua
  • L'output deve essere accurato con almeno due cifre decimali . Restituire anche frazioni / valori simbolici di "precisione infinita" è consentito, se è così che la tua lingua memorizza internamente i dati.
  • Gli invii dovrebbero essere un programma completo che esegue I / O o una funzione. Gli invii di funzioni possono restituire un nuovo elenco o modificare il dato elenco in atto.
  • Sono consentite funzioni / classi vettoriali incorporate. Inoltre, se la tua lingua ha un tipo vettoriale che supporta un numero arbitrario di dimensioni, puoi prenderne una come input.

Questa è una gara di , quindi dovresti mirare a raggiungere la soluzione più breve possibile (in byte).


Deve avere almeno due cifre decimali per ogni possibile input (che non è possibile per alcun tipo standard di valori in virgola mobile) o solo per gli esempi forniti? Ad esempio, la risposta di Steadybox fornisce 2 decimali di precisione per tutti i test, ma usa ints per la somma dei quadrati che ovviamente fallisce per quasi tutti gli input (ad es. [0.1, 0.1]).
Christoph,

... ora aspettiamo solo un lang con la funzione norma integrata mappata su un carattere ...
vaxquis,

Dovrebbe essere almeno 2dp per ogni possibile input @Christoph
FlipTack il

@FlipTack, ma questo esclude praticamente tutte le lingue perché i punti fluttuanti hanno esponenti più grandi della mantissa, il che significa che non hanno sempre abbastanza precisione per avere posizioni decimali.
Christoph,

Perché il 6 nel 4 ° esempio e il -6 nel 5 ° si normalizzano rispettivamente a 1 e -1?
Albero

Risposte:


15

05AB1E , 4 byte

Codice:

nOt/

Provalo online!

Spiegazione

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 quello che mi aspettavo /
YSC il

10

JavaScript (ES6), 31 byte

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

Casi test



9

J , 8 byte

%+/&.:*:

Provalo online!

6 byte %|@j./funziona se il vettore è almeno bidimensionale .


Adoro il modo di ottenere la grandezza.
Cole

1
@cole 1 byte in più:%1%:@#.*:
FrownyFrog il

6
Potresti aggiungere una spiegazione per i non iniziati in J?
MechMK1

% (dividi per) + / (somma) & .: (sotto) *: (quadrato). + somma due cose. + / somma un elenco di cose. & .: modifica l'operazione precedente applicando prima l'operazione seguente e successivamente l'inverso. % normalmente accetta due argomenti, ma (% f) è una funzione da x a x% (fx). La maggior parte degli operatori lavora automagicamente sugli elenchi.
Roman Odaisky,

E secondo gli stessi principi, la funzione che "normalizza" un vettore aggiungendo un numero tale a ciascun componente da sommare a zero è "- + /% #".
Roman Odaisky,



6

C,  73  70 byte

Grazie a @Christoph per aver salvato un byte!

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

Provalo online!


+1. s=0,i=0invece di s=i=0salvare uno
xanoetux il

Adoro l'uso di s[-i]ma purtroppo *--v/=sqrt(s);è 1 byte più breve.
Christoph,

1
@xanoetux Grazie, ma devo inizializzare le variabili all'interno della funzione, perché le funzioni devono essere riutilizzabili . Inoltre, come variabili globali, se ivengono inizializzati automaticamente su 0. (Risulta che non ho bisogno di inizializzare inella funzione, perché la funzione la lascia sempre al valore 0)
Steadybox

1
@Christoph Grazie! Inizialmente stavo stampando i valori dalla funzione, quindi avevo bisogno v[-i]di ottenere i valori nell'ordine corretto.
Steadybox,



3

CJam , 9 byte

{_:mhzf/}

Provalo online!

Spiegazione

_    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 byte

Ans/√(sum(Ans2

Corri con {1,2,3}:prgmNAME, dove{1,2,3} il vettore da normalizzare.

Divide ogni elemento nel vettore per la radice quadrata della somma dei quadrati dei suoi elementi.


Abbiamo avuto la stessa risposta!
kamoroso94,

@ kamoroso94 Whoops! Non ho visto i tuoi quando l'ho pubblicato. Se vuoi aggiungere la spiegazione da questo alla tua risposta, lo eliminerò.
pizzapants184,

No, mi limiterò a rimuovere il mio. Metti più impegno nella tua risposta: P
kamoroso94

3

R , 23 byte

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

Provalo online!

v%*%vcalcola il prodotto punto di v con se stesso.
La funzione emetterà un avviso per vettori di lunghezza 2 o superiore.



2

MATL , 5 byte

t2&|/

Provalo online!

Non sono del tutto sicuro che questo sia il modo più breve per farlo. Innanzitutto, dupliciamo l'input, quindi selezioniamo il secondo tipo di output di |(che è o abs, normodeterminant ). Infine, dividiamo l'input per la norma.

Alternativa per 7 byte:

t2^sX^/




2

C ++ (gcc), 70 byte

Inserito da std::valarray<float>. Sovrascrive il vettore originale.

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

Provalo online!


Di tanto in tanto sto solo nascondendo codegolf, ma questo C ++ non è valido, dato "#import", che è un'estensione specifica di Microsoft?
galleria

@phresnel #importfunziona anche con GCC, Clang e MinGW. Ma sì, non è C ++ standard.
Steadybox,

@phresnel Ho dimenticato di specificare gcc. Fisso.
Colera,


2

APL (Dyalog) , 13 12 10 byte

1 byte salvato grazie a @ Adám

2 byte salvati grazie a @ngn

⊢÷.5*⍨+.×⍨

Provalo online!

Come?

  ÷  .5*⍨  +.  ×⍨
u  ÷       Σ   u²

Treno per meno:⊢÷.5*⍨(+/×⍨)
Adám,

@Adám grazie mille! Ci provo da ore, non riesco a far funzionare nessun treno
Uriel,

Dovremmo fare qualcosa al riguardo, in quanto non è davvero così difficile. Quando hai una funzione monadica (diversa da quella più a destra), inizia una parentesi alla sua sinistra (o usa a se non è derivata). Oltre a questo, solo di swap e per la e : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨)
Adám

(+/×⍨)->+.×⍨
ngn


1

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

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

Provalo online!

+64 byte per il using System;using System.Collections.Generic;using System.Linq;

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

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

Provalo online!

+13 byte per using System;

L'approccio 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;
}


1

Pip , 10 byte

9 byte di codice, +1 per la -pbandiera.

g/RT$+g*g

Prende il vettore come argomenti della riga di comando separati. Provalo online!

Come funziona

      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 byte

cR.aQ

Provalo online: Test Suite

Spiegazione:

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 byte

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

Provalo online!

$_, l'argomento elenco per la funzione, è diviso elementwise ( »/») per la radice quadrata della somma dei quadrati degli elementi ( »²).


1

Rubino, 39 35 byte

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

-4 byte grazie a G B.


1
Salvare alcuni byte utilizzando sum{...}invece dimap{...}.sum
GB

0

Personaggi APL NARS 12

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

Non è necessario contare f← nel conteggio dei byte, poiché è possibile utilizzare i DNS senza di esso. A proposito, è un singolo byte in NARS? Non ne ho familiarità, quindi chiedo solo
Uriel,

@Uriel Nars Apl nei pochi che conosco scriverebbe con Unicode, quindi il numero di byte dovrebbe essere 12x2
RosLuP

0

Fogli Google, 65 byte

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

L'elenco di input è in colonna Acon una voce per cella. Ecco come i fogli di calcolo normalmente usano gli elenchi. Sfortunatamente, ciò comporterebbe normalmente un lungo elenco di ,0,0,0,0,0,....alla fine, quindi dobbiamo ignorare quelli con ilIf Blank then Blank else Math logica.

Se fosse tutto in una cella, invece, la soluzione sarebbe 95 byte:

=ArrayFormula(TextJoin(",",1,If(Split(A1,",")="","",Split(A1,",")/Sqrt(Sumsq(Split(A1,","))))))

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.