Нормалізувати вектор


28

Для того, щоб нормалізувати вектор, щоб масштабувати його до довжини 1 ( одиничний вектор ), в той час зберігаючи напрямок послідовною.

Наприклад, якби ми хотіли нормалізувати вектор з трьома компонентами, u , ми спочатку знайдемо його довжину:

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

... і потім масштабуйте кожен компонент за цим значенням, щоб отримати вектор 1 довжини.

û = u ÷ | u |


Змагання

Ваше завдання - написати програму або функцію, яка, даючи не порожній список підписаних цілих чисел, інтерпретує її як векторну і нормалізує її. Це має працювати для будь-якої кількості вимірів, наприклад (тестові випадки округлені до двох знаків після коми):

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

Правила:

  • Ви можете припустити, що список введення:
    • Мати хоча б один ненульовий елемент
    • Вміст чисел лише у стандартному діапазоні з плаваючою точкою вашої мови
  • Вихід повинен бути точним як мінімум до двох знаків після коми . Повернення дробів / символічних значень "безмежної точності" також дозволено, якщо саме так ваша мова внутрішньо зберігає дані.
  • Подання повинні бути або повною програмою, яка виконує введення-виведення, або функцією. Представлення функцій можуть або повернути новий список, або змінити даний список на місці.
  • Вбудовані векторні функції / класи дозволяються. Крім того, якщо ваша мова має векторний тип, який підтримує довільну кількість вимірів, ви можете взяти один із них як вхідний.

Це змагання з , тому ви повинні прагнути досягти найкоротшого можливого рішення (у байтах).


Чи має бути принаймні два десяткових знаки для кожного можливого введення (що неможливо для будь-якого стандартного типу значень з плаваючою комою) або лише для наведених вами прикладів? Наприклад, відповідь Steadybox забезпечує два десяткових знаки точності для всіх ваших тестів, але він використовує ints для суми квадратів, що, звичайно, не відповідає майже для всіх вхідних даних (наприклад, [0,1, 0,1]).
Крістоф

... тепер ми просто чекаємо, коли язик із вбудованою функцією норми буде відображено на один char ...
vaxquis

На кожен можливий вхід має бути принаймні 2dp @Christoph
FlipTack

@FlipTack, але це виключає в основному всі мови, оскільки плаваючі точки мають більші показники, ніж мантіса, а це означає, що вони не завжди мають достатню точність, щоб мати десяткові знаки.
Крістоф

Чому 6 у четвертому прикладі та -6 у 5-му відповідно не нормалізуються на 1 та -1?
Щогли

Відповіді:



10

JavaScript (ES6), 31 байт

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

Тестові справи



9

Любіть спосіб набуття величини.
cole

1
@cole на 1 байт довше:%1%:@#.*:
FrownyFrog

6
Не могли б ви додати пояснення для непосвячених у J?
MechMK1

% (ділити на) + / (сума) & .: (під) *: (квадрат). + підсумовує дві речі. + / підсумовує список речей. & .: модифікує попередню операцію, застосовуючи спочатку наступну операцію та її зворотну згодом. % зазвичай приймає два аргументи, але (% f) є функцією від x до x% (fx). Більшість операторів автоматично працює над списками.
Роман Одайський

І за тими ж принципами функція, яка "нормалізує" вектор, додаючи таке число до кожного компонента, яке вони дорівнюють нулю, є "- + /% #".
Роман Одайський

8

Желе , 5 3 байти

÷ÆḊ

Спробуйте в Інтернеті! або переглянути набір тестів

Збережено 2 байти за милі!


3 байти з÷ÆḊ
миль

@miles Huh, ніколи не знав про це вбудований. Дякую
caird coinheringaahing

на жаль, що вбудований модуль дає + ve mod для скалярів на TIO, наприклад, абсолютне значення. Проблема вимагала збереження знаку
jayprich


6

C,  73  70 байт

Дякуємо @Christoph за збереження байта!

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

Спробуйте в Інтернеті!


+1. s=0,i=0замість s=i=0збереження одного
xanoetux

Я люблю використання, s[-i]але, на жаль *--v/=sqrt(s);, на 1 байт коротше.
Крістоф

1
@xanoetux Спасибі, але мені потрібно ініціалізувати змінні всередині функції, тому що функції потребують багаторазового використання . Крім того, як глобальні змінні, sі iавтоматично ініціалізуються на 0. (Виявляється, мені не потрібно ініціалізувати iфункцію, оскільки функція завжди залишає її у значенні 0)
Steadybox

1
@Christoph Дякую! Я спочатку друкував значення з функції, тому мені потрібно v[-i]було отримати значення в правильному порядку.
Steadybox



3

CJam , 9 байт

{_:mhzf/}

Спробуйте в Інтернеті!

Пояснення

_    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 байт

Ans/√(sum(Ans2

Запустіть {1,2,3}:prgmNAME, де {1,2,3}вектор повинен бути нормалізований.

Розділяє кожен елемент у векторі на квадратний корінь суми квадратів його елементів.


Ми отримали таку ж відповідь!
kamoroso94

@ kamoroso94 На жаль! Не бачив ваших, коли я опублікував це. Якщо ви хочете додати пояснення з цього до своєї відповіді, я видалю це.
pizzapants184

Ні, я просто зніму свою. Ви доклали більше зусиль у своїй відповіді: P
kamoroso94



2

MATL , 5 байт

t2&|/

Спробуйте в Інтернеті!

Я не зовсім впевнений, що це найкоротший шлях для цього. По- перше, ми дублювати введення, а потім вибрати другий вихідний тип |(який є або abs, normабо determinant). Нарешті, розділимо вхід на норму.

Альтернатива для 7 байт:

t2^sX^/




2

C ++ (gcc), 70 байт

Введення по std::valarray<float>. Переписує оригінальний вектор.

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

Спробуйте в Інтернеті!


Мені просто ховається кодогольф раз у раз, але хіба це недійсний C ++ з огляду на "#import", що є розширенням для Microsoft?
phresnel

@phresnel також #importпрацює принаймні з GCC, Clang і MinGW. Але, так, це не стандартний C ++.
Steadybox

@phresnel я забув вказати gcc. Виправлено.
Колера Су


2

APL (Dyalog) , 13 12 10 байт

1 байт збережено завдяки @ Adám

2 байти збережено завдяки @ngn

⊢÷.5*⍨+.×⍨

Спробуйте в Інтернеті!

Як?

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

Потяг менше:⊢÷.5*⍨(+/×⍨)
Адам

@ Adám дякую багато! Я годинами намагався, жоден поїзд не міг працювати
Уріель

Ми повинні щось з цим зробити, оскільки це насправді не так складно. Коли у вас є монадійна функція (крім правої правої), починайте дужки ліворуч (або використовуйте, якщо вона не виведена). Крім цього, тільки заміна та для і : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨)
адам

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


1

C # (.NET Core) , 51 + 64 = 115 байт

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

Спробуйте в Інтернеті!

+64 байти для using System;using System.Collections.Generic;using System.Linq;

C # (.NET Core) , 94 + 13 = 107 байт

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

Спробуйте в Інтернеті!

+13 байт для using System;

Нелінкський підхід

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

Піп , 10 байт

9 байт коду, +1 для -pпрапора.

g/RT$+g*g

Приймає вектор як окремі аргументи командного рядка. Спробуйте в Інтернеті!

Як це працює

      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 байт

cR.aQ

Спробуйте в Інтернеті: Test Suite

Пояснення:

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

Рубін, 39 35 байт

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

-4 байти завдяки G B.


1
Збережіть кілька байт, використовуючи sum{...}замістьmap{...}.sum
GB

0

APL NARS 12 символів

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

Вам не доведеться вважати f← свій байт, оскільки ви можете використовувати dfns без нього. До речі, чи є один байт у NARS? Я з цим не знайомий, тому просто запитую
Уріель

@Uriel Nars Apl у кількох, яких я знаю, писав би з Unicode, тому кількість байтів повинна бути 12x2
RosLuP

0

Google Таблиці, 65 байт

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

Список введення в колонці Aз одним записом на комірку. Ось як зазвичай електронні таблиці використовують списки. На жаль, це, як правило, призводить до довгого списку ,0,0,0,0,0,....наприкінці, тому нам доводиться ігнорувати тих, хто має If Blank then Blank else Mathлогіку.

Якби все було в одній комірці, натомість рішення було б 95 байт:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.