コードゴルフをやってみました。
の最小値を見つける∑W_i*|X-X_i|
問題は、重み付きのリストの重み付き中央値を見つけることにx[i]
なりますw[i]
(定義については以下を参照)。最短で、最もシンプルで、最も美しいプログラムでそれをどのように行いますか?
これが私のコードが元々どのように見えたかです(説明は質問への回答にあり、短いバージョンが以下の回答の1つとして投稿されています)。
#define zero(x) ( abs(x) < 1e-10 ) /* because == doesn't work for floats */
float sum = 0;
int i;
for (i = 0; i < n; i++)
sum += w[i];
while (sum > 0)
sum -= 2*w[--i];
right = x[i] // the rightmost minimum point
left = ( zero(sum) && zero(w[i]-w[i-1]) ) ? x[i-1] : right;
answer = (left + right) / 2;
i
(実際には、変数が表示されて再利用されているため、すでに大幅に最適化されていますsum
)
ルール
浮動小数点数と整数:言語が異なれば浮動小数点演算標準も異なるため、問題を整数に再定式化し、x[i]
必要にw[i]
応じて回答の2倍の値(常に整数)を返すことができます。回答を返す、印刷する、または変数に割り当てることができます。
加重中央値と説明の定義:
x[i]
ソートされた長さの配列の中央値は、奇数か偶数かによって異なりn
ます。x[n/2]
(x[n/2-1/2]+x[n/2+1/2])/2
n
ソートされていない配列の中央値は、ソート後の配列の中央値です(trueですが、配列はソートされています)x[i]
整数の正の重みを持つの重み付き中央値は、の各出現がの出現に変更されw[i]
た、より大きな配列の中央値として定義されます。x[i]
w[i]
x[i]
私が見たいもの
質問する理由の1つは、最も適切な言語には、単純な配列の合計とラムダによる反復があると想定していることです。関数型言語は妥当だと思いましたが、それについてはよくわかりません。それで、それは質問の一部です。私の望みは次のようなものを見ることです
// standard function add := (a,b) :-> a + b
myreduce := w.reduce
with: add
until: (value) :-> 2*value >= (w.reduce with:add)
answer = x [myreduce from:Begin] + x [myreduce from:End]
これが可能で、実際にはもっと短い言語があれば、Dunno。
テストデータ
static int n = 10;
for (int j = 0; j < n; j++) {
w[j] = j + 1;
x[j] = j;
}
回答:6または12。
static int n = 9;
int w[n], x[n] ;
for (int j = 0; j < n; j++) {
w[j] = j + ((j<6) ? 1 : 0);
x[j] = j + 1;
}
回答:6.5または13。