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


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

9
n0t o que eu esperava /
YSC

10

JavaScript (ES6), 31 bytes

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

Casos de teste



9

J , 8 bytes

%+/&.:*:

Experimente online!

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


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



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!


+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



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.

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.


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.



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




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!


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

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²

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


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)

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

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


1

Ruby, 39 35 bytes

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

-4 bytes graças a G B.


1
Salve alguns bytes usando em sum{...}vez demap{...}.sum
GB

0

APL NARS 12 caracteres

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

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.