これは、私が抱えていた現実の問題に触発されました。これについて賢明な方法があるかどうか見てみたい。
並べ替えられていない2つの配列AとBが与えられ、それぞれに任意の数のfloatが含まれています。AとBは必ずしも同じ長さではありません。Aの要素を順番に受け取り、配列Bで最も近い値を見つける関数を作成します。結果は新しい配列に含まれる必要があります。
勝利条件
最短のコードが勝ちます(通常どおり)。
これは、私が抱えていた現実の問題に触発されました。これについて賢明な方法があるかどうか見てみたい。
並べ替えられていない2つの配列AとBが与えられ、それぞれに任意の数のfloatが含まれています。AとBは必ずしも同じ長さではありません。Aの要素を順番に受け取り、配列Bで最も近い値を見つける関数を作成します。結果は新しい配列に含まれる必要があります。
勝利条件
最短のコードが勝ちます(通常どおり)。
回答:
(UTF-8で21バイト)
B[{↑⍋|⍵-B}¨A]
真のラムダが必要な場合(Aは左引数、Bは右引数):
{⍵[⍺{↑⍋|⍺-⍵}¨⊂⍵]}
{...}¨A
{...}
(配列としてAを呼び出す代わりに)すべてのA値でラムダ関数を呼び出し、結果を同じ形状の配列に収集します
|⍵-B
引数⍵とBのすべての差の絶対値を計算します(-は減算、|はabs)。
↑⍋
最小要素のインデックスを取ります(⍋インデックスを返す配列をソートし、↑最初の要素を取得します)
B[...]
インデックスによって要素を取得しているだけです。
このソリューションは、ソートされた配列自体ではなく、順列ベクトル(元の配列内のソートされた要素のインデックス)を返すAPLのソート関数の素晴らしい機能を使用していますが、非常に簡単です。
#&@@@Nearest@A/@B
どのように機能しますか?はい、Mathematicaには最も近い機能が組み込まれているため、ここで少しごまかしがあります。残りは簡単で、結果を1D配列に配置することに関係しています。それは短くするための余分な努力のためにのみいように見えます。
この質問を正しく理解したかどうかはわかりませんが、とにかくここに私の解決策があります。
短いコードを書くことができるので、配列の代わりにリストを使用しました。
整数配列は整数リストよりも短いです。
入力:
t(new int[] { 0, 25, 10, 38 }, new int[] { 3, 22, 15, 49, 2 });
方法:
void t(int[]a,int[]b){var e=a.Select(c=>b.OrderBy(i=>Math.Abs(c-i)).First()).ToArray();
出力:
2, 22, 15, 49
私の答えが正しくない場合は、その下にコメントを残してください。
編集: @graxが指摘したように、問題はフロートに関するものです。したがって、彼の答えも含めたいと思います。
float[]t(float[]a,float[]b){return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
item
を変更するi
と、追加の6文字が安全になります;)
float[] t(float[] a, float[] b) {return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
B[apply(abs(outer(A,B,`-`)),1,which.min)]
説明:
outer(A,B,`-`)
Aの各要素xの差x-B
を計算し、結果を(次元length(A)x length(B)の)行列として出力します。
which.min
最小数のインデックスを選択します。matrixの各行に
apply(x, 1, f)
関数f
を適用しますx
。
したがってapply(abs(outer(A,B,`-`)),1,which.min)
、Aの各要素とベクトルBの要素間の最小絶対差のインデックスを返します。
使用法:
> 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
q~
f{{1$-z}$0=\;}
p
メインコードは2行目にあり、残りは標準入力ときれいな出力を使用するためのものです。
http://cjam.aditsu.net/で試してください
説明:
q~
入力
f{...}
を読み取り、評価して、最初の配列の各要素と次のオブジェクト(2番目の配列)の各要素のブロックを実行し、配列で結果を収集し
{...}$
て、ブロックを使用して2番目の配列をソートし、各項目のキーを計算し
1$
て現在の最初の配列から項目を
-z
減算してから、絶対値
0=
を取得し、ソートされた配列(最小キーを持つもの)の最初の値を取得します。
\;
最初の配列から項目を破棄し
p
、結果の文字列表現を出力します
例(他の回答からヒントを得た):
入力:[10.1 11.2 12.3 13.4 9.5] [10 12 14]
出力:[10 12 12 14 10]
入力:[0 25 10 38] [3 22 15 49 2]
出力:[2 22 15 49]
距離を最小化します。absの代わりにsquareを使用して、文字を保存します。代数を
編集 ... 修正役に立たない割り当てを
編集(テストの残りの関数定義なし)
F=(A,B)=>A.map(a=>B.sort((x,y)=>x*x-y*y+2*a*(y-x))[0])
だった F=(A,B)=>D=A.map(a=>B.sort((x,y)=>((x-=a,y-=a,x*x-y*y))[0])
テスト
F([10.1, 11.2, 12.3, 13.4, 9.5],[10, 12, 14])
結果: [10, 12, 12, 14, 10]
D=
map
新しい配列を返すため、必要ありません。代替(同じ長さ)ソート関数:(x,y)=>(x-=a)*x-(y-=a)*y
f=lambda a,b:[min((abs(x-n),x)for x in b)[1]for n in a]
a
およびb
は入力配列であり、目的の配列は式の結果です。
$a|%{$n=$_;($b|sort{[math]::abs($n-$_)})[0]}
例
$a
し、$b
次のように設定します。
$a = @(36.3, 9, 50, 12, 18.7, 30)
$b = @(30, 10, 40.5, 20)
出力は
40.5, 10, 40.5, 10, 20, 30
$a|%{$n=$_;($b|sort{($n-$_)*($n-$_)})[0]}
単純な方法で、o
順序関数を使用して最小距離を取得m
し、listでそれを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
∟A+seq(min(∟B+i²∟A(N)),N,1,dim(∟A
APLには近づきませんが、あまり強力ではない関数を使用します。これは、「並べ替え」または「最小のインデックス」関数を使用しません。ここでのTI-BASICの欠点は、これらの関数と多次元配列がないことです。
ゴルフをしていない:
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
分(関数は、2つの動作を有している:実数またはリストを使用する場合には、最小値を与える、複素数またはリストを使用した場合しかし、それは最も小さい絶対値の値を与える追加。0i
によって又は乗算i^2
原因インタプリタへ2番目の動作を使用するため、をmin(1,-2)
返しますが-2
、をmin(1+0i,-2+0i)
返します1
。
function f();integer::f(size(a));f(:)=[(b(minloc(abs(a(i)-b))),i=1,size(a))];endfunction
これにはcontain
、完全なプログラム内で編集する必要があります。
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
角括弧は配列を宣言しますが(...,i=)
、暗黙のdo
ループを表します。次に、b
要素a(i)-b
が最小化されている値を返します。
#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;
}
さて...この小さなコードには説明が必要だと思います。
最初に、2つのレベルのforループでジョブを実行して最小差を見つけ、現在の値をBの値の最小値に設定しようとしました。それは非常に基本的なことです。
同じことは、qsortとコンパレータ関数で達成できます。Bの要素ではなく、差でBをソートします。このような小さなアルゴリズムには関数が多すぎます。そのため、関数qは2つの目的を果たします。最初はアルゴリズムそのものであり、2番目(qsortが呼び出すとき)はコンパレータです。2つの状態間の通信では、グローバルを宣言する必要がありました。
mは、コンパレーター状態かメイン状態かを表します。
例:
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
注:これは部分的な解決策です。私はそれを完全なソリューションにすることに取り組んでいます
{{\.@\.[.,,\]zip@{[\~@-abs]}+%{~\;}$0=0==}%\;}:f;
はい。GolfScriptは浮動小数点をサポートします。ここで試してみてください。例:
# 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]
出力:
[2.2 2.2 10.3 -20.1]
プログラムは最小の違いを見つけて、配列Bから最も近い値を保存します。ゴルフについては、まもなく作業します。
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;
}
テストコード付きの完全なプログラム
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()+", ");
}
}
}