Belirli bir dizideki en yakın sayıyı bulun


21

Bu yaşadığım gerçek bir dünya probleminden ilham alıyor. Bunun için zekice bir yol olup olmadığını görmek merak ediyorum.

Size her biri isteğe bağlı sayıda kayan nokta içeren A ve B dizileri verilmiştir. A ve B mutlaka aynı uzunluklara sahip değildir. A'nın elemanlarını sırayla alan ve B dizisindeki en yakın değeri bulan bir fonksiyon yazın. Sonuç yeni bir dizide bulunmalıdır.

Koşulu kazanmak

En kısa kod kazanır (her zamanki gibi).


1
En yakın tam sayıya mı dönersiniz?
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ "A'nın her bir elemanını B'nin en yakın elemanına yuvarla" olarak okudum
John Dvorak

@JanDvorak: Yuvarlama yönü ile ilgili kısmı anlıyorum, ancak sorun kaç basamak olduğunu belirtmedi.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ En yakın şamandıraya yuvarlak. Bu sorunun cevabı dizi / listeden B
dizini çıkarmak zorunda

1
A ve B dizileri sıralanır mı?
Level River St

Yanıtlar:


17

APL, 13 17

(UTF-8'de 21 bayt)

B[{↑⍋|⍵-B}¨A]

Eğer gerçek lambda istiyorsanız (A argüman olarak sol ve A sağdan B):

{⍵[⍺{↑⍋|⍺-⍵}¨⊂⍵]}

Nasıl çalışır:

{...}¨A{...}Her A değerinde lambda işlevini çağırır (A dizisini çağırmak yerine), sonuçları aynı şekildeki diziye toplar

|⍵-B ument argümanı ile tümü arasındaki B'nin mutlak fark değerlerini hesaplar (- çıkarma, | abs'dir).

↑⍋ En küçük elemanın indeksini alır (array dizi dönen endeksleri sıralar, first ilk elemanı alır)

B[...] sadece eleman (lar) ı indeks (ler) ile alıyor.

Çözüm, APL'nin sıralama işlevini döndüren permütasyon vektörünü (sıralanmış öğenin orijinal dizideki dizinleri) sıralı dizinin kendisinden ziyade harika özelliğini kullanmasına rağmen oldukça basittir.


Bu nasıl çalışıyor?
John Dvorak

Cevap olarak
açıklandı

Bunu nasıl yazacağını nasıl biliyorsun?
Martijn

Bu Çince yazmak gibi bir şey. Benim için yabancı ya da yabancı karakter yazarken büyük bir fark yok ...
Vovanium

17

Mathematica - 17

#&@@@Nearest@A/@B

O nasıl çalışır? Evet, burada biraz hile olduğunu itiraf ediyorum, çünkü Mathematica yerleşik olarak en yakın işlevselliğe sahip. Gerisi basittir ve 1D dizisindeki sonucun düzenlenmesiyle ilgilidir. Sadece kısa yapmak için ekstra çaba nedeniyle çirkin görünüyor.


1
Ha! Hoşgeldiniz! :)
Dr. belisarius

6

C # - 103 97 87 Bayt

Bu soruyu doğru anlamış mıyım emin değilim ama işte yine de benim çözümüm. Diziler yerine Listeler kullandım çünkü kısa kod yazmamı sağlıyor.

Bir tamsayı dizisi bir tamsayı listesinden daha kısa.

Giriş:

t(new int[] { 0, 25, 10, 38 }, new int[] { 3, 22, 15, 49, 2 });

Yöntem:

void t(int[]a,int[]b){var e=a.Select(c=>b.OrderBy(i=>Math.Abs(c-i)).First()).ToArray();

Çıktı:

2, 22, 15, 49

Cevabım doğru değilse, lütfen altına bir yorum bırakın.

EDIT: AS @grax'a dikkat çekti, soru şamandıralarla ilgili. Bu nedenle cevabını da dahil etmek istiyorum.

95 Bayt (Grax'ın cevabı)

float[]t(float[]a,float[]b){return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}

Listeler de iyi.
Orhym

1
Yeniden adlandırın item, i6 ek karakter daha güvenli hale getirin;)
Aschratt

@Aschratt çok teşekkür ederim!
tsavinho

3
1. İşlev, özellikle yeni değeri döndürmeyi söylemez, ancak bence yapmalısınız. 2. Şamandıra için sorulan sorudan beri, şamandırayı kullanmanız gerektiğini düşünüyorumfloat[] t(float[] a, float[] b) {return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
Grax32,

@Grax İlk cevabımı yazdığım gibi, soru yüzen ile ilgili değildi. Soru güncellendiğinden, cevabınızı da dahil ettim. Çok teşekkür ederim.
tsavinho

5

R, 41 karakter

B[apply(abs(outer(A,B,`-`)),1,which.min)]

Açıklama:

outer(A,B,`-`)A farkının her x elementi için hesaplar x-Bve sonucu bir matris olarak (boyut uzunluğu (A) x uzunluk (B)) verir.
which.minminimal sayının indeksini seçer. Her matris sırasına
apply(x, 1, f)fonksiyon uygular . Böylece , her A elementi ile B vektörünün elementleri arasındaki minimum mutlak farkın indekslerini döndürür.fx
apply(abs(outer(A,B,`-`)),1,which.min)

Kullanımı:

> A <- runif(10,0,50)
> B <- runif(10,0,50)
> A
[1] 10.0394987 23.4564467 19.6667152 36.7101256 47.4567670 49.8315028  2.1321263 19.2866901  0.7668489 22.5539178
> B
[1] 44.010174 32.743469  1.908891 48.222695 16.966245 23.092239 24.762485 30.793543 48.703640  6.935354
> B[apply(abs(outer(A,B,`-`)),1,which.min)]
[1]  6.935354 23.092239 16.966245 32.743469 48.222695 48.703640  1.908891 16.966245  1.908891 23.092239

5

CJam - 14

q~
f{{1$-z}$0=\;}
p

Ana kod ikinci satırda, gerisi standart girdi ve güzel çıktı kullanımı içindir.

Http://cjam.aditsu.net/ adresinde deneyin

Açıklama:

q~okur ve giriş değerlendirir
f{...}ilk dizinin her bir elemanı ve bir sonraki nesnesi için blok (ikinci dizi), bir dizideki sonuçları toplamak yürütür
{...}$her öğe için bir anahtar hesaplamak için blok kullanılarak ikinci bir dizi sıralar
1$kopya akım ilk diziden
-zçıkarılan öğe, sonra mutlak değeri
0=alır, dizilen dizinin ilk değerini alır (minimum tuşa sahip olan)
\;ilk diziden gelen öğeyi atar
p, sonucun dizgi gösterimini basar.

Örnekler (diğer cevaplardan ilham alınmıştır):

Giriş: [10.1 11.2 12.3 13.4 9.5] [10 12 14]
Çıkış:[10 12 12 14 10]

Giriş: [0 25 10 38] [3 22 15 49 2]
Çıkış:[2 22 15 49]


4

Javascript (E6) 54 56 59

Mesafeyi en aza indirin. Abs yerine kare kullanmak sadece karakterleri tasarruf etmektir.
Düzenleme cebri ...
düzenleme düzeltme gereksiz atama (o / işlev tanımı w testin kalan)

F=(A,B)=>A.map(a=>B.sort((x,y)=>x*x-y*y+2*a*(y-x))[0])

was F=(A,B)=>D=A.map(a=>B.sort((x,y)=>((x-=a,y-=a,x*x-y*y))[0])

Ölçek

F([10.1, 11.2, 12.3, 13.4, 9.5],[10, 12, 14])

Sonuç: [10, 12, 12, 14, 10]


1
D=gerekli değildir, çünkü mapyeni bir dizi döndürür. Alternatif (aynı uzunluk) sıralama fonksiyonu:(x,y)=>(x-=a)*x-(y-=a)*y
nderscore 11:14

4

Python 3.x - 55 karakter

f=lambda a,b:[min((abs(x-n),x)for x in b)[1]for n in a]

ave bgiriş dizileridir ve istenen dizi ifadenin sonucudur.


Soruyu bir işlev gerektirdiğinden, işlevi bir işlev haline getirmek için cevabı değiştirdim.
user80551

3

Haskell, 55

c a b=[[y|y<-b,(y-x)^2==minimum[(z-x)^2|z<-b]]!!0|x<-a]

İlk başta kullanmayı düşündüm minimumByve comparingbunlar Prelude'de olmadığı için, onları nitelemek bir ton karakter aldı. Ayrıca bir karakteri tıraş etmek için karışma fikrini diğer bazı cevaplardan da çaldım.


3

PowerShell - 44

$a|%{$n=$_;($b|sort{[math]::abs($n-$_)})[0]}

Örnek

İle $ave 'ye $bayarla:

$a = @(36.3, 9, 50, 12, 18.7, 30)
$b = @(30, 10, 40.5, 20)

Çıktı

40.5, 10, 40.5, 10, 20, 30

Örnekte yüzdürme yöntemini kullanarak yüzer sapları da temizleyebiliyordunuz
bebe

@bebe - Teşekkürler, netleştirmek için güncellendi.
Rynant

-3 bayt:$a|%{$n=$_;($b|sort{($n-$_)*($n-$_)})[0]}
mazzy

2

Ruby, 40

f=->a,b{a.map{|x|b.min_by{|y|(x-y)**2}}}

Python cevabıyla aynı, fakat kare alma, mutlak değer almayı düşündüğümden biraz daha ters.


2

Pyth - 12 11 bayt

Not: Pyth bu mücadeleden çok daha genç, bu yüzden bu cevap kazanmaya uygun değil.

Basit yöntem, ominimum mesafeyi elde etmek için sipariş işlevini kullanır ve mlisteye aps a.

mho.a-dNQvz

m    vz    Map over evaled first input and implicitly print
 ho Q      Minimal mapped over evaled second input
  .a-      Absolute difference
   d       Lambda param 1
   b       Lambda param 2

Burada çevrimiçi deneyin .


@Jakube oh evet, üzgünüm.
Maltysen

2

TI-BASIC, 24

∟A+seq(min(∟B+i²∟A(N)),N,1,dim(∟A

APL'ye yaklaşmaz, ancak daha az güçlü işlevler kullanır - bu "sıralamaya" veya "en az dizin" işlevlerini kullanmaz. Buradaki TI-BASIC'in dezavantajı, bu işlevlerin ve çok boyutlu dizilerin olmamasıdır.

Ungolfed:

seq(       ,N,1,dim(∟A           #Sequence depending on the Nth element of list A
    ∟A(N)+min(   +0i)            #Number with minimum absolute value, add to ∟A(N)
              ∟B-∟A(N)           #Subtracts Nth element of ∟A from all elements of B

Dakika (fonksiyon iki davranışları vardır: gerçek sayılar veya listeler ile kullanıldığında, en küçük değeri verir; karmaşık sayılar veya listeler ile kullanıldığında ise, en küçük mutlak değere sahip değerini verir ekleme. 0iYa çarparak i^2nedenleri tercüman için ikinci davranışı kullanmak, yani min(1,-2)döner -2iken min(1+0i,-2+0i)geri dönüş 1.


1

Fortran 90: 88

function f();integer::f(size(a));f(:)=[(b(minloc(abs(a(i)-b))),i=1,size(a))];endfunction

Bu, containtam bir program içinde yayınlanmasını gerektirir :

program main
   real :: a(5), b(3)
   integer :: i(size(a))
   a = [10.1, 11.2, 12.3, 13.4, 9.5]
   b = [10, 12, 14]
   i = f()
   print*,i
 contains
   function f()
     integer :: f(size(a))
     f(:)=[(b(minloc(abs(a(i)-b))),i=1,size(a))]
   end function
end program main

Köşeli parantezler (...,i=), bir örtülü doçevrimi temsil ederken bir dizi bildirir ; Daha sonra bhangi elemanın a(i)-bküçültüldüğü değerini veririm .


1

Matlab: 48

f=@(a)B(abs(B-a)==min(abs(B-a)));C=arrayfun(f,A)

Çalışma alanında 1B matris olduğunu Ave BSon sonuç çalışma alanında olduğunu varsayar C. Bu muhtemelen Octave'da da işe yarayabilir. Koşullu indeksleme, bunu oldukça önemsiz kılar.


0

C 144 163

#define f float
f T, *C, m;
f *q(f *A, f *B, int S, f s)
{
    if(m) 
        return abs(T - *A) - abs(T - *B);
    for ( 
        C = malloc(S * 4);
        m = S--;
        C[S] = *B
    ) 
        T = A[S], 
        qsort(B, s, 4, q);
    return C;
}

Tamam ... Bu küçük kodun açıklamaya ihtiyacı olduğunu düşünüyorum.

İlk önce iki seviye için işi min farkını bulmak için kullanmaya çalıştım ve mevcut değeri B değerinin min. Bu çok basit.

Aynı şeye qsort ve bir karşılaştırma fonksiyonu ile ulaşılabilir . B elemanlarının yerine B farkına göre sıraladım. Böyle küçük bir algoritma için çok fazla fonksiyon var. Yani q fonksiyonu şimdi iki amaca hizmet ediyor. İlk başta, algoritmanın kendisi, ikincisi (qsort çağırdığında) bir karşılaştırıcı. İki devlet arasındaki iletişim için, küreler ilan etmek zorunda kaldım.

m , karşılaştırıcı durumunda mı yoksa ana durumda mı olduğunu gösterir .

örnek:

float A[] = {1.5, 5.6, 8.9, -33.1};
float B[] = {-20.1, 2.2, 10.3};
float *C;

C = q(A, B, sizeof(A)/sizeof(*A), sizeof(B)/sizeof(*B));
// C holds 2.2,2.2,10.3,-20.1

166/163, boşlukları sayıyor mu, saymıyor mu?
Kyle Kanos

Tabii ki değil. Boşluklar ve yeni satırlar anlama kolaylığı içindir.
bebe

0

GolfScript, 49 bayt

Not: Bu kısmi bir çözümdür. Tam bir çözüm yapmak için çalışıyorum

{{\.@\.[.,,\]zip@{[\~@-abs]}+%{~\;}$0=0==}%\;}:f;

Evet. GolfScript kayan noktaları destekliyor. Burada dene . Örnek:

# B is [-20.1 2.2 10.3]
[-201 10 -1?*
22 10 -1?*
103 10 -1?*]

# A. No floating point numbers allowed here.
# This is because 1.5{}+ (where the 1.5 is a
# single floating point number, not 1.5,
# which would be 1 1 5) results in the block
# {1.5 }, which leads to 1 1 5 when executed
[1 5 9 -30]

Çıktı:

[2.2 2.2 10.3 -20.1]

0

C # 262

Program min farklılıkları bulur ve B dizisinden en yakın değeri korur. Kısa bir süre sonra golf üzerinde çalışacağım.

List<float> F(List<float> a, List<float> b)
{
List<float> c = new List<float>();
float diff,min;
int k;
for(int i=0; i<a.Count;i++)
{
diff=0;
min=1e6F;
k = 0;
for(int j=0; j<b.Count;j++)
{
diff = Math.Abs(a[i] - b[j]);
if (diff < min)
{
min = diff;
k = j;
}
}
c.Add(b[k]);
}
return c;
}

Test kodu ile tam program

using System;
using System.Collections.Generic;
public class JGolf
{
    static List<float> NearestValues(List<float> a, List<float> b)
    {
        List<float> c = new List<float>();
        float diff,min;
        int k;
        for(int i=0; i<a.Count;i++)
        {
            diff=0;
            min=1e6F;
            k = 0;
            for(int j=0; j<b.Count;j++)
            {
                diff = Math.Abs(a[i] - b[j]);
                if (diff < min)
                {
                    min = diff;
                    k = j;
                }
            }
            c.Add(b[k]);
        }
        return c;
    }

    public static void Main(string[] args)
    {
        List<float> A = RandF(8413);
        Console.WriteLine("A");
        Print(A);
        List<float> B = RandF(9448);
        Console.WriteLine("B");
        Print(B);

        List<float> d = JGolf.NearestValues(A, B);
        Console.WriteLine("d");
        Print(d);
        Console.ReadLine();
    }

    private static List<float> RandF(int seed)
    {
        Random r = new Random(seed);
        int n = r.Next(9) + 1;
        List<float> c = new List<float>();
        while (n-- > 0)
        {
            c.Add((float)r.NextDouble() * 100);
        }
        return c;
    }

    private static void Print(List<float> d)
    {
        foreach(float f in d)
        {
            Console.Write(f.ToString()+", ");
        }
    }
}

0

C #: 120

Linq harika:

float[] t(float[] A, float[] B){return A.Select(a => B.First(b => Math.Abs(b-a) == B.Min(c=>Math.Abs(c-a)))).ToArray();}
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.