Menormalkan Vektor

28

Untuk menormalkan suatu vektor berarti menskalakannya menjadi panjang 1 ( vektor satuan ), sambil menjaga arahnya konsisten.

Misalnya, jika kita ingin menormalkan vektor dengan 3 komponen, u , pertama-tama kita akan menemukan panjangnya:

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

... dan kemudian skala setiap komponen dengan nilai ini untuk mendapatkan vektor panjang 1.

û = u ÷ | u |


Tantangan

Tugas Anda adalah menulis sebuah program atau fungsi yang, mengingat daftar bilangan bulat yang tidak kosong, menafsirkannya sebagai vektor, dan menormalkannya. Ini harus bekerja untuk sejumlah dimensi, misalnya (kasus uji dibulatkan ke dua tempat desimal):

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

Aturan:

  • Anda dapat mengasumsikan daftar input akan:
    • Memiliki setidaknya satu elemen yang tidak nol
    • Hanya berisi angka dalam rentang titik mengambang standar bahasa Anda
  • Output Anda harus akurat untuk setidaknya dua tempat desimal . Mengembalikan nilai fraksi / nilai simbolik "presisi tak terbatas" juga diperbolehkan, jika ini adalah cara bahasa Anda menyimpan data secara internal.
  • Pengajuan harus berupa program lengkap yang menjalankan I / O, atau suatu fungsi. Pengajuan fungsi dapat mengembalikan daftar baru, atau mengubah daftar yang diberikan di tempat.
  • Fungsi / kelas vektor bawaan diizinkan. Selain itu, jika bahasa Anda memiliki jenis vektor yang mendukung jumlah dimensi yang berubah-ubah, Anda dapat mengambil salah satunya sebagai input.

Ini adalah kontes , jadi Anda harus berusaha mencapai solusi sesingkat mungkin (dalam byte).

FlipTack
sumber
Apakah harus memiliki setidaknya dua tempat desimal untuk setiap input yang mungkin (yang tidak mungkin untuk jenis standar nilai floating point) atau hanya untuk contoh yang Anda berikan? Misalnya jawaban Steadybox memberikan 2 tempat desimal presisi untuk semua pengujian Anda, tetapi ia menggunakan ints untuk jumlah kuadrat yang tentu saja gagal untuk hampir semua input (mis. [0,1, 0,1]).
Christoph
... sekarang kita tunggu saja lang dengan fungsi norma
bawaan yang
Seharusnya minimal 2dp untuk setiap input yang mungkin
@Christoph
@FlipTack tetapi itu mengesampingkan pada dasarnya semua bahasa karena titik apung memiliki eksponen yang lebih besar daripada mantissa yang berarti mereka tidak selalu memiliki presisi yang cukup untuk memiliki tempat desimal.
Christoph
Mengapa 6 pada contoh ke-4 dan -6 di ke-5 tidak dinormalisasi menjadi 1 dan -1?
Tiang

Jawaban:

15

05AB1E , 4 byte

Kode:

nOt/

Cobalah online!

Penjelasan

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
sumber
9
bukan apa yang saya harapkan /
YSC
10

JavaScript (ES6), 31 byte

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

Uji kasus

Arnauld
sumber
10

Mathematica, 9 byte

Normalize

Cobalah online!

J42161217
sumber
12
Atau #/Norm@#&untuk jumlah byte yang sama.
Martin Ender
9

J , 8 byte

%+/&.:*:

Cobalah online!

6 byte %|@j./berfungsi jika vektor setidaknya 2 dimensi .

FrownyFrog
sumber
Cinta cara mendapatkan besarnya.
cole
1
@cole 1 byte lebih lama:%1%:@#.*:
FrownyFrog
6
Bisakah Anda menambahkan penjelasan untuk yang belum tahu di J?
MechMK1
% (dibagi dengan) + / (jumlah) & .: (di bawah) *: (persegi). + menjumlahkan dua hal. + / menjumlahkan daftar hal-hal. & .: memodifikasi operasi sebelumnya dengan menerapkan operasi berikut terlebih dahulu dan kebalikannya setelahnya. % biasanya mengambil dua argumen, tetapi (% f) adalah fungsi dari x ke x% (fx). Sebagian besar operator secara otomatis bekerja pada daftar.
Roman Odaisky
Dan dengan prinsip yang sama, fungsi yang "menormalkan" vektor dengan menambahkan angka sedemikian rupa ke setiap komponen yang dijumlahkan menjadi nol adalah "- + /% #".
Roman Odaisky
8

Jelly , 5 3 byte

÷ÆḊ

Cobalah online! , atau lihat test suite

Disimpan 2 byte berkat mil!

caird coinheringaahing
sumber
3 byte dengan÷ÆḊ
mil
@miles Huh, tidak pernah tahu tentang builtin itu. Terima kasih
caird coinheringaahing
sayangnya built-in memberikan + ve mod untuk skalar per TIO nilai absolut seperti examplelike .. masalah yang diminta menjaga tanda
jayprich
6

C,  73  70 byte

Terima kasih kepada @Christoph karena telah menghemat satu byte!

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

Cobalah online!

Steadybox
sumber
+1. s=0,i=0bukannya s=i=0menghemat satu
xanoetux
Saya suka menggunakan s[-i]tetapi sayangnya *--v/=sqrt(s);1 byte lebih pendek.
Christoph
1
@xanoetux Terima kasih, tapi saya perlu menginisialisasi variabel di dalam fungsi, karena fungsi harus dapat digunakan kembali . Selain itu, sebagai variabel global, sdan isecara otomatis diinisialisasi ke 0. (Ternyata saya tidak perlu menginisialisasi idalam fungsi, karena fungsi selalu meninggalkannya pada nilai 0)
Steadybox
1
@Christoph Terima kasih! Saya awalnya mencetak nilai-nilai dari fungsi, jadi saya harus v[-i]mendapatkan nilai-nilai dalam urutan yang benar.
Steadybox
4

Python, 47 46 byte

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

Cobalah online!

PattuX
sumber
3

CJam , 9 byte

{_:mhzf/}

Cobalah online!

Penjelasan

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

TI-Basic, 6 byte

Ans/√(sum(Ans2

Jalankan dengan {1,2,3}:prgmNAME, di mana {1,2,3}vektor dinormalisasi.

Membagi setiap elemen dalam vektor dengan akar kuadrat dari jumlah kuadrat elemennya.

pizzapants184
sumber
Kami mendapat jawaban yang sama!
kamoroso94
@ kamoroso94 Whoops! Tidak melihat Anda ketika saya memposting ini. Jika Anda ingin menambahkan penjelasan dari ini ke jawaban Anda, saya akan menghapus ini.
pizzapants184
Nah saya hanya akan menghapus milik saya. Anda lebih berupaya dalam jawaban Anda: P
kamoroso94
3

R , 23 byte

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

Cobalah online!

v%*%vmenghitung titik produk v dengan dirinya sendiri.
Fungsi ini akan mengeluarkan peringatan untuk vektor dengan panjang 2 atau lebih besar.

Giuseppe
sumber
2

MATL , 5 byte

t2&|/

Cobalah online!

Saya tidak sepenuhnya yakin ini adalah cara terpendek untuk melakukan ini. Pertama, kita menduplikasi input, lalu pilih tipe output kedua |(yang mana adalah abs, normatau determinant). Akhirnya, kami membagi input dengan norma.

Alternatif untuk 7 byte:

t2^sX^/
Stewie Griffin
sumber
2

Haskell , 29 byte

f x=map(/sqrt(sum$(^2)<$>x))x

Cobalah online!

Atau untuk 1 byte lebih banyak pointfree: map=<<flip(/).sqrt.sum.map(^2)

ბიმო
sumber
2

Funky , 42 byte

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

Cobalah online!

ATaco
sumber
2

C ++ (gcc), 70 byte

Masukan oleh std::valarray<float>. Menimpa vektor asli.

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

Cobalah online!

Colera Su
sumber
Saya hanya mengintai codegolf setiap saat, tetapi bukankah ini C + + tidak valid, diberi "#import", yang merupakan ekstensi spesifik Microsoft?
phresnel
@phresnel #importbekerja setidaknya dengan GCC, Dentang dan MinGW juga. Tapi, ya, itu bukan standar C ++.
Steadybox
@ saluran Saya lupa menentukan gcc. Tetap.
Colera Su
2

Common Lisp, 69 byte

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

Cobalah online!

Renzo
sumber
2

APL (Dyalog) , 13 12 10 byte

1 byte disimpan berkat @ Adám

2 byte disimpan berkat @ngn

⊢÷.5*⍨+.×⍨

Cobalah online!

Bagaimana?

  ÷  .5*⍨  +.  ×⍨
u  ÷       Σ   u²
Uriel
sumber
Latih kurang:⊢÷.5*⍨(+/×⍨)
Adám
@ Adam terima kasih banyak! Saya sudah berusaha selama berjam-jam, tidak bisa mendapatkan kereta untuk bekerja
Uriel
Kita harus melakukan sesuatu tentang itu, karena ini tidak terlalu sulit. Ketika Anda memiliki fungsi monadik (selain yang paling kanan), mulailah tanda kurung di sebelah kirinya (atau gunakan jika itu tidak diturunkan). Selain itu, cukup tukar dan untuk dan : {⍵÷.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()))

Cobalah online!

+64 byte untuk 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;}

Cobalah online!

+13 byte untuk using System;

Pendekatan 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;
}
Ayb4btu
sumber
1

Pip , 10 byte

9 byte kode, +1 untuk -pbendera.

g/RT$+g*g

Mengambil vektor sebagai argumen baris perintah yang terpisah. Cobalah online!

Bagaimana itu bekerja

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

Pyth, 5 byte

cR.aQ

Cobalah online: Test Suite

Penjelasan:

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

Perl 6 , 25 byte

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

Cobalah online!

$_, argumen daftar ke fungsi, dibagi elementwise ( »/») oleh akar kuadrat dari jumlah kuadrat elemen ( »²).

Sean
sumber
1

Ruby, 39 35 byte

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

-4 byte terima kasih kepada G B.

m-chrzan
sumber
1
Simpan beberapa byte dengan menggunakan sum{...}sebagai gantinyamap{...}.sum
GB
0

APL NARS 12 Karakter

f←{⍵÷√+/⍵*2}
RosLuP
sumber
Anda tidak perlu menghitung f← dalam hitungan byte Anda, karena Anda dapat menggunakan dfns tanpa itu. Omong-omong, apakah satu byte tunggal di NARS? Saya tidak terbiasa dengan hal itu, jadi tanyakan saja
Uriel
@Uriel Nars Apl dalam beberapa yang saya tahu akan menulis dengan Unicode sehingga jumlah byte harus 12x2
RosLuP
0

Google Sheets, 65 byte

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

Daftar input ada di kolom Adengan satu entri per sel. Beginilah biasanya spreadsheet menggunakan daftar. Sayangnya, ini biasanya akan menghasilkan daftar panjang ,0,0,0,0,0,....di akhir sehingga kita harus mengabaikan mereka yang memiliki If Blank then Blank else Mathlogika.

Jika semuanya ada dalam satu sel, maka solusinya adalah 95 byte:

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

Cepat 4, 44 byte

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

Hitung ulang norma vektor untuk setiap komponen, tetapi setidaknya ini singkat!

Alexander - Pasang kembali Monica
sumber