Trova il numero più vicino in un determinato array


21

Questo è ispirato da un problema del mondo reale che ho avuto. Sono curioso di vedere se esiste un modo intelligente per farlo.

Ti vengono dati due array non ordinati, A e B, ciascuno contenente un numero arbitrario di float. A e B non hanno necessariamente le stesse lunghezze. Scrivere una funzione che accetta gli elementi di A in sequenza e trova il valore più vicino nell'array B. Il risultato deve essere contenuto in un nuovo array.

Condizioni di vittoria

Vince il codice più corto (come al solito).


1
Arrotondare al numero intero più vicino?
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ L'ho letto come "attorno a ciascun elemento di A fino all'elemento più vicino di B"
John Dvorak,

@JanDvorak: Bene, capisco la parte relativa alla direzione di arrotondamento, ma il problema non è stato specificato a quante cifre.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Arrotonda al galleggiante più vicino. La risposta deve produrre float dall'array / elenco B.
Orhym,

1
Le matrici A e B verranno ordinate?
Level River St

Risposte:


17

APL, 13 17

(21 byte in UTF-8)

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

Se vuoi il vero lambda (A come argomento a sinistra e B come a destra):

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

Come funziona:

{...}¨A invoca la funzione lambda {...} con ogni valore A (anziché invocare A come array), raccogliendo i risultati in array della stessa forma

|⍵-B calcola i valori assoluti della differenza tra l'argomento ⍵ e tutto in B (- è la sottrazione, | è abs).

↑⍋ accetta l'indice del minimo elemento (⍋ ordina gli array che restituiscono gli indici, ↑ ottiene il primo elemento)

B[...] sta semplicemente recuperando gli elementi per indice (i).

La soluzione è piuttosto semplice, sebbene utilizzi la meravigliosa funzione della funzione di ordinamento di APL che restituisce il vettore di permutazione (indici degli elementi ordinati nella matrice originale) piuttosto che la matrice ordinata stessa.


Come funziona?
John Dvorak,

Spiegato in risposta
Vovanium

Come diavolo sai come scrivere questo?
Martijn,

È come scrivere cinese. Per me, non c'è grande differenza nel scrivere parole aliene o personaggi alieni ...
Vovanium,

17

Mathematica - 17

#&@@@Nearest@A/@B

Come funziona? Sì, ammetto che qui c'è un po 'di imbrogli perché Mathematica ha la funzionalità integrata più vicina . Il resto è semplice e si occupa di organizzare il risultato in un array 1D. Sembra brutto solo a causa dello sforzo extra per renderlo breve.


1
Ha! Benvenuto! :)
Dr. belisarius,

6

C # - 103 97 87 byte

Non sono del tutto sicuro di aver capito bene questa domanda, ma ecco comunque la mia soluzione. Ho usato gli elenchi anziché gli array, perché mi consente di scrivere codice più breve.

Un array intero è più corto di un elenco intero.

Ingresso:

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

Metodo:

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

Produzione:

2, 22, 15, 49

Se la mia risposta non è corretta, si prega di lasciare un commento sotto di essa.

EDIT: AS @grax ha sottolineato, la domanda ora riguarda i float. Pertanto vorrei includere anche la sua risposta.

95 byte (risposta di Grax)

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

Anche le liste vanno bene.
Orhym,

1
Rinomina itemin ie
salverai

@Aschratt grazie mille!
Tsavinho,

3
1. La funzione non dice specificamente di restituire il nuovo valore, ma penso che dovresti. 2. Dato che la domanda chiedeva il galleggiante, penso che dovresti usare il floatfloat[] t(float[] a, float[] b) {return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
Grax32,

@Grax Mentre scrivevo la mia prima risposta, la domanda non riguardava i float. Poiché la domanda è stata aggiornata, ho incluso anche la tua risposta. Grazie mille.
Tsavinho,

5

R, 41 caratteri

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

Spiegazione:

outer(A,B,`-`)calcola la differenza per ogni elemento x di A x-Be genera il risultato come una matrice (di lunghezza della dimensione (A) x lunghezza (B)).
which.minseleziona l'indice del numero minimo.
apply(x, 1, f)applica la funzione fsu ogni riga della matrice x.
Quindi apply(abs(outer(A,B,`-`)),1,which.min)restituisce gli indici della minima differenza assoluta tra ciascun elemento di A e gli elementi del vettore B.

Uso:

> 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

Il codice principale è sulla seconda riga, il resto è per l'utilizzo dell'input standard e dell'output piuttosto.

Provalo su http://cjam.aditsu.net/

Spiegazione:

q~ legge e valuta l'input
f{...} esegue il blocco per ciascun elemento del primo array e l'oggetto successivo (che è il secondo array), raccogliendo i risultati in un array
{...}$ordina il secondo array usando il blocco per calcolare una chiave per ogni elemento
1$copia l'attuale l'elemento dal primo array viene
-zsottratto quindi assume il valore assoluto
0=prende il primo valore dell'array ordinato (quello con la chiave minima)
\;scarta l'elemento dal primo array
pstampa la rappresentazione in stringa del risultato

Esempi (ispirati ad altre risposte):

Ingresso: [10.1 11.2 12.3 13.4 9.5] [10 12 14]
Uscita:[10 12 12 14 10]

Ingresso: [0 25 10 38] [3 22 15 49 2]
Uscita:[2 22 15 49]


4

Javascript (E6) 54 56 59

Ridurre al minimo la distanza. Usando square invece di abs basta salvare i caratteri.
Modifica algebra ...
Modifica correzione assegnazione inutile (resto del test senza la definizione della funzione)

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

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

Test

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

Risultato: [10, 12, 12, 14, 10]


1
D=non è necessario, poiché maprestituisce un nuovo array. Funzione di ordinamento alternativa (stessa lunghezza):(x,y)=>(x-=a)*x-(y-=a)*y
nderscore,

4

Python 3.x - 55 caratteri

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

ae bsono gli array di input e l'array desiderato è il risultato dell'espressione.


Ho modificato la risposta per renderla una funzione poiché la domanda richiede una funzione.
user80551

3

Haskell, 55

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

All'inizio, ho pensato di usare minimumBye comparing, ma dal momento che quelli non sono in Preludio, ci sono voluti un sacco di personaggi per qualificarli. Ha anche rubato l'idea quadrata di alcune altre risposte per radere un personaggio.


3

PowerShell - 44

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

Esempio

Con $ae $bimpostato su:

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

L'output è

40.5, 10, 40.5, 10, 20, 30

potresti usare i float nell'esempio per chiarire che gestisce anche i float
bebe l'

@bebe - Grazie, aggiornato per chiarirlo.
Rynant,

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

2

Ruby, 40 anni

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

Come la risposta di Python, ma la quadratura è un po 'più tesa di qualsiasi modo a cui potrei pensare di prendere valore assoluto.


2

Pyth - 12 11 byte

Nota: Pyth è molto più giovane di questa sfida, quindi questa risposta non è idonea a vincere.

Metodo semplice, utilizza la ofunzione ordine per ottenere una distanza minima e mla supera nella lista 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

Provalo online qui .


@Jakube oh sì, scusa.
Maltysen,

2

TI-BASIC, 24

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

Non si avvicina ad APL, ma utilizza funzioni meno potenti: non utilizza alcuna funzione "ordinata per" o "indice del minimo". Lo svantaggio di TI-BASIC qui è la sua mancanza di quelle funzioni e array multidimensionali.

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

La funzione min (ha due comportamenti: se utilizzata con numeri o elenchi reali, fornisce il valore più piccolo; tuttavia, se utilizzata con numeri o elenchi complessi, fornisce il valore con il valore assoluto più piccolo. Aggiungendo 0io moltiplicando per i^2l'interprete usa il secondo comportamento, quindi min(1,-2)restituisce -2mentre min(1+0i,-2+0i)restituisce 1.


1

Fortran 90: 88

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

Ciò richiede che venga containeditato all'interno di un programma completo:

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

Le parentesi quadre dichiarano un array mentre (...,i=)rappresentano un doloop implicito ; Quindi restituisco il valore di bper il quale elemento a(i)-bè ridotto a icona.


1

Matlab: 48

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

Suppone che Ae Bsiano matrici 1D nell'area di lavoro, Il risultato finale è Cnell'area di lavoro. Questo probabilmente funzionerebbe anche in Octave. L'indicizzazione condizionale lo rende abbastanza banale.


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

Okay ... Penso che questo piccolo codice abbia bisogno di spiegazioni.

All'inizio ho provato a fare il lavoro con due livelli di for loop trovando la differenza minima e impostando il valore corrente su min del valore di B. È molto semplice.

La stessa cosa può essere raggiunta con qsort e una funzione di confronto. Lo faccio ordinando B in base alla differenza anziché agli elementi di B. Troppe funzioni per un algoritmo così piccolo. Quindi la funzione q ora ha due scopi. Inizialmente, è l'algoritmo stesso, in secondo luogo (quando qsort lo chiama) un comparatore. Per la comunicazione tra i due stati, ho dovuto dichiarare i globi.

m indica se si trova nello stato di confronto o in quello principale .

esempio:

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

Il 166/163 conta o meno gli spazi bianchi?
Kyle Kanos,

Ovviamente no. Spazi e newline sono per facilità di comprensione.
bebe

0

GolfScript, 49 byte

Nota: questa è una soluzione parziale. Sto lavorando per renderlo una soluzione completa

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

Sì. GolfScript supporta il floating point. Provalo qui . Esempio:

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

Produzione:

[2.2 2.2 10.3 -20.1]

0

C # 262

Il programma trova differenze minime e salva il valore più vicino dall'array B. Lavorerò a breve sul golf.

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

Programma completo con codice di prova

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 è fantastico:

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();}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.