Bir Vektörü Normalize Et


28

İçin normalize bir vektör bir 1 uzunluğa (ölçeklemek için bir birim vektör tutarlı yönü tutarak).

Biz 3 bileşenleri ile bir vektör normalleştirmek istiyorsa Örneğin, u , öncelikle uzunluğunu bulur:

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

... ve daha sonra uzunluk 1 vektör elde etmek için her bileşeni bu değerle ölçeklendirin.

û = u ÷ | u |


Meydan okuma

Göreviniz, boş olmayan bir imzalı tamsayı listesi verilen, vektör olarak yorumlayan ve normalleştiren bir program veya işlev yazmaktır. Bu, herhangi bir sayıda boyut için çalışmalıdır, örneğin (iki ondalık basamağa yuvarlanmış test durumları):

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

Kurallar:

  • Giriş listesinin şöyle olacağını varsayabilirsiniz:
    • En az bir sıfır olmayan öğeye sahip
    • Yalnızca kendi dilinizin standart kayan nokta aralığında sayılar içerir
  • Çıktınız en az iki ondalık basamağa kadar doğru olmalıdır . Diliniz dahili olarak bu şekilde saklanıyorsa, "sonsuz hassasiyet" kesirlerine / sembolik değerlere geri dönülmesine de izin verilir.
  • Gönderimler, G / Ç gerçekleştiren tam bir program veya bir işlev olmalıdır. İşlev gönderimleri yeni bir liste döndürebilir veya verilen listeyi değiştirebilir.
  • Yerleşik vektör fonksiyonlarına / sınıflarına izin verilir. Ek olarak, eğer dilinizde isteğe bağlı sayıda boyutu destekleyen bir vektör tipi varsa, bunlardan birini girdi olarak alabilirsiniz.

Bu bir yarışması, bu yüzden mümkün olan en kısa çözümü (bayt cinsinden) elde etmeyi hedeflemelisiniz.


Mümkün olan her giriş için (herhangi bir standart kayan nokta değeri için mümkün değildir) veya yalnızca sağladığınız örnekler için en az iki ondalık basamak olması mı gerekir? Örneğin Steadybox'ın cevabı, tüm testleriniz için 2 ondalık hassasiyet yeri sağlar, ancak neredeyse tüm girdiler için başarısız olan karelerin toplamı için inç kullanır (örn. [0.1, 0.1]).
Christoph

... şimdi sadece bir karaktere eşlenmiş yerleşik norm işlevi olan bir lang bekliyoruz ...
vaxquis

Her olası giriş için en az 2dp olmalıdır @Christoph
FlipTack

@FlipTack bu temelde tüm dilleri dışlar, çünkü kayan noktaların mantissa'dan daha büyük üstleri vardır;
Christoph

Neden dördüncü örnekte 6 ve 5. sırada -6 sırasıyla 1 ve -1 olarak normalleşmiyor?
Direk

Yanıtlar:


15

05AB1E , 4 bayt

Kod:

nOt/

Çevrimiçi deneyin!

açıklama

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
Beklediğim
n0t

10

JavaScript (ES6), 31 bayt

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

Test durumları



9

J , 8 bayt

%+/&.:*:

Çevrimiçi deneyin!

6 bayt %|@j./işler vektör, en az 2 boyutlu ise .


Büyüklüğü elde etmenin yolunu seviyorum.
cole,

1
@cole 1 byte daha uzun:%1%:@#.*:
FrownyFrog

6
Lütfen J'de başlatılmamış için bir açıklama ekleyebilir misiniz?
MechMK1

% (bölünerek) + / (toplam) & .: (altında) *: (kare). + iki şeyi toplar. + /, şeylerin bir listesini toplar. & .: önceki işlemi önce aşağıdaki işlemi, ardından tersini uygulayarak değiştirir. % normalde iki argüman alır, fakat (% f), x ile x% (fx) arasında bir fonksiyondur. Çoğu operatör otomatik olarak listelerde çalışır.
Roman Odaisky

Aynı prensiplere göre, bir sıfıra topladıkları her bileşene böyle bir sayı ekleyerek bir vektörü “normalleştiren” işlev “- + /% #” şeklindedir.
Roman Odaisky



6

C,  73  70 bayt

Bayt tasarrufu için @Christoph teşekkürler!

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

Çevrimiçi deneyin!


+1. s=0,i=0bir s=i=0tasarruf yerine
xanoetux

Ben kullanımını seviyorum s[-i]ama ne yazık ki *--v/=sqrt(s);1 byte kısa.
Christoph

1
@ xanoetux Teşekkürler, fakat fonksiyon içindeki değişkenleri başlatmam gerekiyor çünkü fonksiyonların tekrar kullanılabilir olması gerekiyor . Ayrıca, global değişkenler olarak sve i0'a otomatik olarak başlatılırlar. ( i
İşlevde başlatmam gerekmediği anlaşılıyor

1
@Christoph Teşekkürler! Başlangıçta fonksiyondan değerleri yazdırıyordum, bu yüzden v[-i]değerleri doğru sırayla almam gerekiyordu .
Steadybox



3

CJam , 9 bayt

{_:mhzf/}

Çevrimiçi deneyin!

açıklama

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

Ans/√(sum(Ans2

Çalıştır {1,2,3}:prgmNAME, {1,2,3}normalleştirilecek vektör nerede .

Vektördeki her elemanı, elemanlarının karelerinin toplamının kareköküne böler.


Aynı cevabı aldık!
kamoroso94

@ kamoroso94 Çorbalar! Bunu gönderdiğimde seninkini görmedim. Bu konudaki açıklamayı cevabınıza eklemek isterseniz bunu sileceğim.
pizzapants184

Hayır, sadece benimkini kaldıracağım. Cevabınıza daha fazla çaba sarfedersiniz: P
kamoroso94

3

R , 23 bayt

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

Çevrimiçi deneyin!

v%*%vv nin nokta çarpımını kendisiyle hesaplar.
İşlev, uzunluk 2 veya daha fazla vektör için bir uyarı verecektir.



2

MATL , 5 bayt

t2&|/

Çevrimiçi deneyin!

Bunun bunu yapmanın en kısa yolu olduğundan tam olarak emin değilim. İlk olarak, daha sonra, giriş yinelenen ikinci çıkışı türünü |(ya olduğu abs, normya da determinant). Son olarak, girdiyi normlara göre böleriz.

7 bayt için alternatif:

t2^sX^/




2

C ++ (gcc), 70 bayt

Girişi ile std::valarray<float>. Orijinal vektörün üzerine yazar.

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

Çevrimiçi deneyin!


Sadece şimdi ve sonra codegolf gizliyordum, ancak bu Microsoft'a özgü bir uzantı olan "#import" verilen bu geçersiz C ++ değil mi?
phresnel

@phresnel #import, en azından GCC, Clang ve MinGW ile de çalışır. Ama evet, standart C ++ değil.
Steadybox

@ phresnel gcc belirtmeyi unuttum. Sabit.
Colera Su


2

APL (Dyalog) , 13 12 10 bayt

@ Adám sayesinde 1 bayt kurtarıldı

@Ngn sayesinde 2 bayt kaydedildi

⊢÷.5*⍨+.×⍨

Çevrimiçi deneyin!

Nasıl?

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

Daha az tren için:⊢÷.5*⍨(+/×⍨)
Adám

@ Adám çok teşekkürler! Saatlerdir deniyorum, çalışmak için bir tren bulamadım
Uriel

Bu konuda bir şeyler yapmalıyız, çünkü o kadar da zor değil. Monadik bir işleve sahip olduğunuzda (en sağdaki hariç), soldan bir parantez başlatın (ya da türetilmemişse a kullanın ). Bunun dışında sadece takas ve için ve : {⍵÷.5*⍨+/×⍨⍵}{⍵÷.5*⍨(+/(×⍨⍵))}⊢÷.5*⍨(+/(×⍨⊢))⊢÷.5*⍨(+/(×⍨))⊢÷.5*⍨(+/×⍨)
Adam

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


1

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

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

Çevrimiçi deneyin!

İçin +64 bayt using System;using System.Collections.Generic;using System.Linq;

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

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

Çevrimiçi deneyin!

İçin +13 bayt using System;

Linq olmayan yaklaşım

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 bayt

9 baytlık kod, -pbayrak için +1 .

g/RT$+g*g

Vektörü ayrı komut satırı argümanları olarak alır. Çevrimiçi deneyin!

Nasıl çalışır

      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 bayt

cR.aQ

Çevrimiçi deneyin: Test Paketi

Açıklama:

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 bayt

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

Çevrimiçi deneyin!

$_fonksiyona verilen liste argümanı, elementwise ( »/») elemanlarının ( »²) karelerinin toplamının karekökü ile ayrılır .


1

Ruby, 39 35 bayt

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

G B. sayesinde -4 bayt


1
sum{...}map{...}.sum
GB

0

APL NARS 12 Karakter

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

Sen saymak gerekmez f← onsuz dfns kullanabilirsiniz beri, senin bayt sayısında. Bu arada, NARS'ta bir bayt mı? Ben aşina değilim, bu yüzden sadece soruyorum
Uriel

@Uriel Nars Apl az sayıda Unicode ile yazacağını biliyor, bu yüzden bayt sayısı 12x2 olmalı
RosLuP

0

Google Sayfaları, 65 bayt

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

Giriş listesi, Ahücre başına bir giriş içeren sütundadır . Elektronik sayfaların normalde listeleri kullanması budur. Ne yazık ki, bu normalde sonuçta uzun bir liste ile sonuçlanacaktır, bu ,0,0,0,0,0,....yüzden If Blank then Blank else Mathmantığı olanları görmezden gelmeliyiz.

Hepsi bir hücrede olsaydı, bunun yerine çözüm 95 bayt olurdu:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.