Encontre o número mais próximo em uma determinada matriz

21

Isso é inspirado em um problema do mundo real que eu tive. Estou curioso para ver se existe alguma maneira inteligente de fazer isso.

Você recebe duas matrizes não classificadas, A e B, cada uma contendo um número arbitrário de flutuadores. A e B não têm necessariamente os mesmos comprimentos. Escreva uma função que pegue os elementos de A sequencialmente e encontre o valor mais próximo na matriz B. O resultado deve estar contido em uma nova matriz.

Condição de vitória

O código mais curto vence (como de costume).

Orhym
fonte
11
Arredondar para o número inteiro mais próximo?
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳
11
@ n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳ Eu li que como "round cada elemento de A ao elemento mais próximo de B"
John Dvorak
@ JanDvorak: Bem, eu entendo a parte sobre a direção do arredondamento, mas o problema não especificou quantos dígitos.
N
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Arredonde para o flutuador mais próximo. A resposta tem a saída flutua de matriz / lista B.
Orhym
11
As matrizes A e B serão classificadas?
Level River St

Respostas:

17

APL, 13 17

(21 bytes em UTF-8)

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

Se você deseja lambda verdadeiro (A como argumento à esquerda e B como à direita):

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

Como funciona:

{...}¨Achama a função lambda {...}com todo valor A (em vez de chamar com A como matriz), reunindo resultados na matriz da mesma forma

|⍵-B calcula valores absolutos da diferença entre o argumento ⍵ e tudo em B (- é subtração, | é abs).

↑⍋ pega o índice do menor elemento (⍋ classifica os índices que retornam a matriz, ↑ obtém o primeiro elemento)

B[...] está apenas buscando elemento (s) pelo (s) índice (s).

A solução é bastante direta, embora use um recurso maravilhoso da função de classificação da APL retornando o vetor de permutação (índices do elemento classificado na matriz original) em vez da própria matriz classificada.

Vovanium
fonte
Como é que isso funciona?
John Dvorak
Explicado em resposta
Vovanium
Como diabos você sabe escrever isso?
Martijn
É como escrever chinês. Para mim, não há grande diferença escrevendo algumas das palavras alienígenas ou personagens alienígenas ...
Vovanium
17

Mathematica - 17

#&@@@Nearest@A/@B

Como funciona? Sim, admito que há um pouco de trapaça aqui porque o Mathematica possui a funcionalidade mais próxima . O resto é direto e se preocupa em organizar o resultado em uma matriz 1D. Parece feio apenas por causa do esforço extra para abreviá-lo.

Szabolcs
fonte
11
Ha! Bem vinda! :)
Dr. belisarius
6

C # - 103 97 87 bytes

Não tenho certeza se entendi corretamente essa pergunta, mas aqui está minha solução. Usei Listas em vez de matrizes, porque isso me permite escrever um código mais curto.

Uma matriz inteira é menor que uma lista inteira.

Entrada:

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

Método:

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

Saída:

2, 22, 15, 49

Se minha resposta não estiver correta, deixe um comentário abaixo.

EDIT: AS @grax apontou, a questão agora é sobre carros alegóricos. Portanto, eu gostaria de incluir sua resposta também.

95 bytes (resposta de Grax)

float[]t(float[]a,float[]b){return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
tsavinho
fonte
As listas também são boas.
Orhym
11
Renomeie itempara ie você
salvará
@Aschratt muito obrigado!
tsavinho 11/06
3
1. A função não diz especificamente para retornar o novo valor, mas acho que você deveria. 2. Uma vez que a questão chamado para float, eu acho que você deve usar flutuadorfloat[] t(float[] a, float[] b) {return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
Grax32
@ Grax Como escrevi minha primeira resposta, a pergunta não era sobre carros alegóricos. Como a pergunta foi atualizada, incluí sua resposta também. Muito obrigado.
tsavinho 12/06
5

R, 41 caracteres

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

Explicação:

outer(A,B,`-`)calcula para cada elemento x de A a diferença x-Be gera o resultado como uma matriz (do comprimento da cota (A) x comprimento (B)).
which.minescolhe o índice do número mínimo.
apply(x, 1, f)aplica a função fem cada linha da matriz x.
Então, apply(abs(outer(A,B,`-`)),1,which.min)retorna os índices da diferença absoluta mínima entre cada elemento de A e os elementos do vetor 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
plannapus
fonte
5

CJam - 14

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

O código principal está na segunda linha, o restante é para usar a entrada padrão e a saída bonita.

Experimente em http://cjam.aditsu.net/

Explicação:

q~lê e avalia que a entrada
f{...}executa o bloco para cada elemento da primeira matriz e o próximo objeto (que é a segunda matriz), coletando os resultados em uma matriz
{...}$classifica a segunda matriz usando o bloco para calcular uma chave para cada item
1$copia a corrente o item da primeira matriz
-zsubtrai, em seguida, pega o valor absoluto,
0=pega o primeiro valor da matriz classificada (aquele com a chave mínima)
\;descarta o item da primeira matriz,
pimprime a representação em seqüência do resultado

Exemplos (inspirados em outras respostas):

Entrada: [10.1 11.2 12.3 13.4 9.5] [10 12 14]
Saída:[10 12 12 14 10]

Entrada: [0 25 10 38] [3 22 15 49 2]
Saída:[2 22 15 49]

aditsu
fonte
4

Javascript (E6) 54 56 59

Minimize a distância. Usando quadrado em vez de abs, apenas salve caracteres.
Editar álgebra ...
Editar corrigir atribuição inútil (o restante de um teste sem a definição de função)

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

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

Teste

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

Resultado: [10, 12, 12, 14, 10]

edc65
fonte
11
D=não é necessário, pois mapretorna uma nova matriz. Função de classificação alternativa (do mesmo tamanho):(x,y)=>(x-=a)*x-(y-=a)*y
nderscore
4

Python 3.x - 55 caracteres

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

ae bsão as matrizes de entrada e a matriz desejada é o resultado da expressão.

Tal
fonte
Editei a resposta para torná-la uma função, pois a pergunta requer uma função.
user80551
3

Haskell, 55

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

No começo, pensei em usar minimumBye comparing, mas como esses não estão no Prelude, foram necessários muitos caracteres para qualificá-los. Também roubou a ideia quadrática de algumas outras respostas para raspar um personagem.

YawarRaza7349
fonte
3

PowerShell - 44

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

Exemplo

Com $ae $bdefinido como:

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

Saída é

40.5, 10, 40.5, 10, 20, 30
Rynant
fonte
você poderia usar carros alegóricos no exemplo de deixar claro que lida com carros alegóricos também
bebe
@ beeb - Obrigado, atualizado para deixar isso claro.
Rynant 12/06
-3 bytes:$a|%{$n=$_;($b|sort{($n-$_)*($n-$_)})[0]}
mazzy
2

Ruby, 40

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

O mesmo que a resposta do Python, mas a quadratura é um pouco mais tensa do que qualquer maneira que eu possa pensar em ter valor absoluto.

histocrata
fonte
2

Pitão - 12 11 bytes

Nota: Pyth é muito mais jovem que esse desafio, portanto, esta resposta não é elegível para vencer.

Método simples, usa a ofunção de ordem para obter uma distância mínima e maplicá-la na 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

Experimente online aqui .

Maltysen
fonte
@Jakube oh sim, desculpe.
Maltysen
2

TI-BASIC, 24

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

Não chega nem perto do APL, mas usa funções menos poderosas - isso não usa nenhuma função "classificada por" ou "índice do mínimo". A desvantagem do TI-BASIC aqui é a falta dessas funções e matrizes multidimensionais.

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

A função min (tem dois comportamentos: quando usada com números ou listas reais, fornece o menor valor; no entanto, quando usada com números ou listas complexos, fornece o valor com o menor valor absoluto. A adição 0iou multiplicação por i^2causa do intérprete use o segundo comportamento, então min(1,-2)retorna -2enquanto min(1+0i,-2+0i)retorna 1.

lirtosiast
fonte
1

Fortran 90: 88

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

Isso requer que ele seja containeditado em um programa 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

Os colchetes declaram uma matriz enquanto (...,i=)representam um doloop implícito ; Em seguida, retorno o valor bpara o qual o elemento a(i)-bé minimizado.

Kyle Kanos
fonte
1

Matlab: 48

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

Assume que Ae Bsão matrizes 1D na área de trabalho, o resultado final está Cna área de trabalho. Isso provavelmente também funcionaria no Octave. A indexação condicional torna isso bastante trivial.

Godric Seer
fonte
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;
}

Ok ... acho que esse pequeno código precisa de explicação.

No começo, tentei fazer o trabalho com dois níveis de loop for, encontrando a diferença mínima e defina o valor atual para min do valor de B. Isso é muito básico.

O mesmo pode ser alcançado com qsort e uma função comparadora. Eu faço o tipo B pela diferença em vez dos elementos de B. Muitas funções para um algoritmo tão pequeno. Portanto, a função q agora serve a dois propósitos. No início, é o próprio algoritmo, em segundo lugar (quando o qsort o chama) um comparador. Para a comunicação entre os dois estados, tive que declarar globais.

m significa se está no estado comparador ou no principal .

exemplo:

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
bebe
fonte
O 166/163 conta o espaço em branco ou não?
Kyle Kanos
Claro que não. Espaços e novas linhas são para facilitar o entendimento.
bebe
0

GolfScript, 49 bytes

Nota: esta é uma solução parcial. Estou trabalhando para torná-lo uma solução completa

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

Sim. O GolfScript suporta ponto flutuante. Experimente aqui . Exemplo:

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

Saída:

[2.2 2.2 10.3 -20.1]
Justin
fonte
0

C # 262

O programa encontra diferenças mínimas e economiza o valor mais próximo da Matriz B. Vou trabalhar no golfe em breve.

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

Programa completo com código de teste

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()+", ");
        }
    }
}
bacchusbeale
fonte
0

C #: 120

O Linq é incrível:

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();}
DLeh
fonte