Normalizar um vetor

28

Para normalizar um vector é para dimensioná-lo até um comprimento de 1 ( um vector de unidade ), enquanto se mantinha a direcção consistente.

Por exemplo, se quiséssemos normalizar um vetor com 3 componentes, u , primeiro encontraríamos seu comprimento:

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

... e, em seguida, dimensione cada componente por esse valor para obter um vetor de comprimento 1.

û = u ÷ | u |


O desafio

Sua tarefa é escrever um programa ou função que, dada uma lista não vazia de números inteiros assinados, interprete-o como um vetor e o normalize. Isso deve funcionar para qualquer número de dimensões, por exemplo (casos de teste arredondados para duas casas decimais):

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

Regras:

  • Você pode assumir que a lista de entrada irá:
    • Ter pelo menos um elemento diferente de zero
    • Contém apenas números dentro do intervalo de ponto flutuante padrão do seu idioma
  • Sua saída deve ser precisa com pelo menos duas casas decimais . Também é permitido o retorno de frações / valores simbólicos de "precisão infinita", se é assim que seu idioma armazena os dados internamente.
  • Os envios devem ser um programa completo que execute E / S ou uma função. Os envios de funções podem retornar uma nova lista ou modificar a lista fornecida no local.
  • Funções / classes de vetores incorporadas são permitidas. Além disso, se o seu idioma tiver um tipo de vetor que suporte um número arbitrário de dimensões, você poderá usar um deles como entrada.

Como é um concurso de , você deve ter como objetivo alcançar a solução mais curta possível (em bytes).

FlipTack
fonte
Ele precisa ter pelo menos duas casas decimais para cada entrada possível (o que não é possível para nenhum tipo padrão de valores de ponto flutuante) ou apenas para os exemplos que você fornece? Por exemplo, a resposta de Steadybox fornece 2 casas decimais de precisão para todos os seus testes, mas ele usa ints para a soma dos quadrados que, obviamente, falham em quase todas as entradas (por exemplo, [0,1, 0,1]).
Christoph
... Agora é só esperar para um lang com built-in função de norma mapeado para um caractere ...
vaxquis
Deve ser a pelo menos 2DP para cada possível @ Christoph entrada
FlipTack
@FlipTack, mas isso exclui basicamente todos os idiomas, porque os pontos flutuantes têm expoentes maiores que os mantissa, o que significa que eles nem sempre têm precisão suficiente para ter casas decimais.
Christoph
Por que o 6 no 4º exemplo e o -6 no 5º respectivamente normalizam para 1 e -1?
Mast

Respostas:

15

05AB1E , 4 bytes

Código:

nOt/

Experimente online!

Explicação

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
fonte
9
n0t o que eu esperava /
YSC
10

JavaScript (ES6), 31 bytes

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

Casos de teste

Arnauld
fonte
10

Mathematica, 9 bytes

Normalize

Experimente online!

J42161217
fonte
12
Ou #/Norm@#&para a mesma contagem de bytes.
Martin Ender
9

J , 8 bytes

%+/&.:*:

Experimente online!

6 bytes %|@j./funcionam se o vetor for pelo menos bidimensional .

FrownyFrog
fonte
Adoro a maneira de obter a magnitude.
cole
1
@cole 1 byte mais:%1%:@#.*:
FrownyFrog
6
Você poderia, por favor, adicionar uma explicação para os não iniciados em J?
MechMK1
% (dividir por) + / (soma) e .: (abaixo) *: (quadrado). + soma duas coisas. + / resume uma lista de coisas. & .: modifica a operação anterior aplicando a operação a seguir primeiro e seu inverso depois. % normalmente recebe dois argumentos, mas (% f) é uma função de x a x% (fx). A maioria dos operadores trabalha automaticamente em listas.
Roman Odaisky
E pelos mesmos princípios, a função que “normaliza” um vetor adicionando um número a cada componente que somam zero é “- + /% #”.
Roman Odaisky
8

Geléia , 5 3 bytes

÷ÆḊ

Experimente online! ou veja a suíte de testes

Economizou 2 bytes graças a milhas!

caird coinheringaahing
fonte
3 bytes com÷ÆḊ
milhas
@miles Huh, nunca soube disso. Graças
Caird coinheringaahing
infelizmente isso built-in dá + ve mod para escalares por TIO examplelike valor absoluto .. o problema solicitado manter o sinal
jayprich
6

C,  73  70 bytes

Agradecemos a @Christoph por salvar um byte!

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

Experimente online!

Steadybox
fonte
+1. s=0,i=0em vez de s=i=0salva um
xanoetux 27/11
Eu amo o uso de, s[-i]mas infelizmente *--v/=sqrt(s);é 1 byte mais curto.
Christoph
1
@xanoetux Obrigado, mas preciso inicializar as variáveis ​​dentro da função, porque as funções precisam ser reutilizáveis . Além disso, como variáveis globais, se isão automaticamente inicializados para 0. (Acontece que eu não precisam para inicializar ina função, porque a função sempre deixa-lo pelo valor 0)
Steadybox
1
@Christoph Obrigado! Inicialmente, eu estava imprimindo os valores da função, portanto, precisava v[-i]obtê-los na ordem correta.
Steadybox
4

Python, 47 46 bytes

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

Experimente online!

PattuX
fonte
3

CJam , 9 bytes

{_:mhzf/}

Experimente online!

Explicação

_    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
fonte
3

TI-Basic, 6 bytes

Ans/√(sum(Ans2

Corra com {1,2,3}:prgmNAME, onde {1,2,3}é o vetor a ser normalizado.

Divide cada elemento no vetor pela raiz quadrada da soma dos quadrados de seus elementos.

pizzapants184
fonte
Temos a mesma resposta!
kamoroso94
@ kamoroso94 Opa! Não vi o seu quando publiquei isso. Se você quiser adicionar a explicação disso à sua resposta, eu a excluirei.
pizzapants184
Não, eu vou remover o meu. Você coloca mais esforço em sua resposta: P
kamoroso94 27/11
3

R , 23 bytes

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

Experimente online!

v%*%vcalcula o produto escalar de v com ele mesmo.
A função emitirá um aviso para vetores de comprimento 2 ou superior.

Giuseppe
fonte
2

MATL , 5 bytes

t2&|/

Experimente online!

Não tenho certeza absoluta de que essa é a maneira mais curta de fazer isso. Em primeiro lugar, nós duplicar a entrada, em seguida, seleccionar o segundo tipo de saída |(que ou é abs, normou determinant). Finalmente, dividimos a entrada pela norma.

Alternativa para 7 bytes:

t2^sX^/
Stewie Griffin
fonte
2

Funky , 42 bytes

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

Experimente online!

ATaco
fonte
2

C ++ (gcc), 70 bytes

Entrada por std::valarray<float>. Substitui o vetor original.

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

Experimente online!

Colera Su
fonte
Estou apenas espreitando o codegolf de vez em quando, mas esse C ++ não é inválido, dado "#import", que é uma extensão específica da Microsoft?
Phresnel # 27/17
O @phresnel também #importtrabalha pelo menos com GCC, Clang e MinGW. Mas, sim, não é C ++ padrão.
Steadybox 27/11
@phresnel Esqueci de especificar o gcc. Fixo.
Colera Su
2

Lisp comum, 69 bytes

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

Experimente online!

Renzo
fonte
2

APL (Dyalog) , 13 12 10 bytes

1 byte salvo graças a @ Adám

2 bytes salvos graças a @ngn

⊢÷.5*⍨+.×⍨

Experimente online!

Quão?

  ÷  .5*⍨  +.  ×⍨
u  ÷       Σ   u²
Uriel
fonte
Treine por menos:⊢÷.5*⍨(+/×⍨)
Adám 26/11/17
@ Adám muito obrigado! Eu tenho tentado durante horas, não poderia ficar de trem para o trabalho
Uriel
Deveríamos fazer algo sobre isso, pois realmente não é tão difícil. Quando você tiver uma função monádica (diferente da mais à direita), inicie um parêntese à sua esquerda (ou use a se não deriva). Fora isso, apenas troque e for e : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨)
Adám 27/11/17
(+/×⍨)->+.×⍨
NGN
1

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

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

Experimente online!

+64 bytes para o 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;}

Experimente online!

+13 bytes para using System;

A abordagem não-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
fonte
1

Pip , 10 bytes

9 bytes de código, +1 para -psinalizador.

g/RT$+g*g

Toma o vetor como argumentos separados da linha de comando. Experimente online!

Como funciona

      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
fonte
1

Pitão, 5 bytes

cR.aQ

Experimente online: Conjunto de Testes

Explicação:

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
fonte
1

Perl 6 , 25 bytes

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

Experimente online!

$_, o argumento da lista para a função, é dividido elementwise ( »/») pela raiz quadrada da soma dos quadrados dos elementos ( »²).

Sean
fonte
1

Ruby, 39 35 bytes

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

-4 bytes graças a G B.

m-chrzan
fonte
1
Salve alguns bytes usando em sum{...}vez demap{...}.sum
GB
0

APL NARS 12 caracteres

f←{⍵÷√+/⍵*2}
RosLuP
fonte
Você não precisa contar f← na sua contagem de bytes, pois você pode usar o dfns sem ele. A propósito, existe um único byte no NARS? Eu não estou familiarizado com isso, então só pergunto
Uriel
@Uriel Nars Apl nos poucos que sei que escreveria com Unicode, portanto o número de bytes deve ser 12x2
RosLuP
0

Planilhas Google, 65 bytes

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

A lista de entrada está na coluna Acom uma entrada por célula. É assim que as planilhas normalmente usam listas. Infelizmente, isso normalmente resultaria em uma longa lista de ,0,0,0,0,0,....no final, então temos que ignorar aqueles com a If Blank then Blank else Mathlógica.

Se tudo estivesse em uma célula, a solução seria 95 bytes:

=ArrayFormula(TextJoin(",",1,If(Split(A1,",")="","",Split(A1,",")/Sqrt(Sumsq(Split(A1,","))))))
Engenheiro Toast
fonte
0

Swift 4, 44 bytes

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

Recalcula a norma de vetor para cada componente, mas pelo menos é concisa!

Alexander - Restabelecer Monica
fonte