ウィルロジャース現象


35

いわゆるウィルロジャース現象は、1つの要素が2つのセット間で移動したときに2つの(マルチ)セットの平均を上げることで統計を微調整する方法を説明します。簡単な例として、2つのセットを考えます

A = {1, 2, 3}
B = {4, 5, 6}

それらの算術平均は 2、および5です。私たちが移動した場合4A

A = {1, 2, 3, 4}
B = {5, 6}

今、平均である2.55.5の両方の平均値は、単純な再編を通じて提起されているので、それぞれ。

別の例として、考えてみましょう

A = {3, 4, 5, 6} --> A = {3, 5, 6}
B = {2, 3, 4, 5} --> B = {2, 3, 4, 4, 5}

一方、セットの両方の平均を上げることはできません

A = {1, 5, 9}
B = {4, 5, 7, 8}

チャレンジ

非負整数の2つのリストが与えられた場合、1つのリストから別のリストに単一の整数を移動して、両方の平均値を上げることが可能かどうかを判断します。

空のリストの平均は定義されていないため、リストの1つに要素が1つしか含まれていない場合、この要素は移動できません。

プログラムまたは関数を作成し、STDIN(または最も近い代替)、コマンドライン引数または関数引数を介して入力を取得し、STDOUT(または最も近い代替)、関数の戻り値または関数(out)パラメーターを介して結果を出力できます。

入力は、任意の便利な文字列またはリスト形式で取得できます。

各リスト内の要素が一意であると仮定したり、ソートされていると仮定したりしないでください。両方のリストに少なくとも1つの要素が含まれていると想定できます。

出力があるべきtruthy両方の平均が単一の整数と移動して上昇させることができるならばfalsyをそう。

これはコードゴルフなので、最短の回答(バイト単位)が勝ちです。

テストケース

真実:

[1], [2, 3]
[1, 2, 3], [4, 5, 6]
[3, 4, 5, 6], [2, 3, 4, 5]
[6, 5, 9, 5, 6, 0], [6, 2, 0, 9, 5, 2]
[0, 4], [9, 1, 0, 2, 8, 0, 5, 5, 4, 9]

偽物:

[1], [2]
[2, 4], [5]
[1, 5], [2, 3, 4, 5]
[2, 1, 2, 3, 1, 3], [5, 1, 6]
[4, 4, 5, 2, 4, 0], [9, 2, 10, 1, 9, 0]

リーダーボード

これは、通常のリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットです。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

# Ruby, <s>104</s> <s>101</s> 96 bytes

<script>site = 'meta.codegolf'; postID = 5314; isAnswer = true; QUESTION_ID = 53913</script><script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>jQuery(function(){var u='https://api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)</code></pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>


コーダーではなく数学者として、私は実際に課題に取り組むことはできませんが、次の質問に興味があります:整数の有限コレクション(たとえば5)を一方のセットから他方のセットにシフトすることで両方の平均を上げることができる場合、常に1つの整数をシフトすることで両方の平均値が上がる可能性があるのですか?したがって、課題が本当にすべてのケースをカバーしていることを示しています。
トレバーJリチャーズ

3
@TrevorRichards最後の偽のテストケースがこれをカバーしていると思います。あなたは移動できる19オーバー、両方の平均値を上げることになるが、あなたは、単一のものを移動することによって、そうすることはできません。
マーティンエンダー

@TrevorRichards一般に、セットAとBの平均がa <bである場合、a <c <bのような平均cを持つBのサブセットCがある場合、両方の平均を上げることができます。一方、BからAに移動するすべての要素に値<bを持たせる必要がある場合、仮説は真になります。
アルキミスト

回答:


11

Pyth、29 28 26 24バイト

.pとで3バイト節約してくれた@Jakubeに感謝しますL

非常に簡単で、リスト2の要素がリスト1の平均より大きく、リスト2の平均より小さいかどうかをチェックし、リスト1とリスト2を切り替えて繰り返します。

Lcsblbff&>YyhT<YyeTeT.pQ

真実と偽りのために空でないリストを印刷[]します。

L                    Define y(b). Pyth has no builtin for mean
 c                   Float div
  sb                 Sum of b
  lb                 Length of b
f        .pQ         Filter all permutations of input
 f     eT            Filter the last element of the filter var
  &                  Logical and
   >Y                Inner filter var greater than
    y                Call the mean function we defined earlier
     hT              First element of outer filter var
   <Y                Inner filter var less than
    y                Mean of
     eT              Last element of outer filternvar

こちらからオンラインでお試しください

テストスイート。


7

Python 3、74

lambda*L:any(sum(C)/len(C)>x>sum(D)/len(D)for(C,D)in[L,L[::-1]]for x in C)

入力として2つのリストを受け取ります。最初のリストに、平均よりも大きいが他のリストよりも小さい要素があるかどうかを確認します。次に、スワップされた2つの入力に対して同じことを行います。2層のリストを理解することは、2つの順序を試すために別の関数を定義するよりも短くなりました(82)。

f=lambda A,B:any(sum(A)/len(A)>x>sum(B)/len(B)for x in A)
lambda A,B:f(A,B)|f(B,A)

7

ハスケル、58 57

x%y=any(\n->(\g->g x<0&&g y>0)$sum.map(n-))x
x?y=x%y||y%x

削除または含める要素が平均よりも大きいか小さいかを確認することで、平均を拡大または縮小するかどうかを確認できます。

配列からその要素を削除して平均が要素よりも小さいか大きいかを確認し、新しい配列の平均が負か正かどうかを確認することで確認できます。 。

それをチェックすることは非常に簡単に言えますsum.map(-n+)


6

Mathematica、49 47バイト

m=Mean;MemberQ[#2,x_/;m@#<x<m@#2]&@@#~SortBy~m&

フォームへの入力を期待する純粋な関数に評価され{list1, list2}ます。


4

APL、45 40バイト

Moris Zuccaのおかげで5バイト節約できました!

{U←∊⍺⍵[⊃⍒M←(+/÷≢)¨⍺⍵]⋄1∊(U<⌈/M)∧(U>⌊/M)}

これにより、左右の配列を受け入れ、1または0を返す名前のないダイアディック関数が作成されます。

{
  M←(+/÷≢)¨⍺⍵          ⍝ Compute the mean of each array
  U←∊⍺⍵[⊃⍒M]           ⍝ Get the array with the larger mean
  1∊(U<⌈/M)∧(U>⌊/M)    ⍝ Any smaller mean < U < larger mean
}

オンラインで試すことができます


1
あなたが書くことができ、平均:(+ /÷≢)
モリスズッカ

@MorisZuccaありがとう!提案を使用するように編集されました。
アレックスA.

3

R、66 52バイト

名前のない関数として、2つのベクトルを受け入れます。いくつかの偽りのwhichsを取り除きました。

function(a,b)any(a<(m=mean)(a)&a>m(b),b<m(b)&b>m(a))

テスト

> f=
+ function(a,b)any(a<(m=mean)(a)&a>m(b),b<m(b)&b>m(a))
> f(c(1), c(2, 3))
[1] TRUE
> f(c(1, 2, 3), c(4, 5, 6))
[1] TRUE
> f(c(3, 4, 5, 6), c(2, 3, 4, 5))
[1] TRUE
> f(c(6, 5, 9, 5, 6, 0), c(6, 2, 0, 9, 5, 2))
[1] TRUE
> f(c(0, 4), c(9, 1, 0, 2, 8, 0, 5, 5, 4, 9))
[1] TRUE
> 
> f(c(1), c(2))
[1] FALSE
> f(c(2, 4), c(5))
[1] FALSE
> f(c(1, 5), c(2, 3, 4, 5))
[1] FALSE
> f(c(2, 1, 2, 3, 1, 3), c(5, 1, 6))
[1] FALSE
> f(c(4, 4, 5, 2, 4, 0), c(9, 2, 10, 1, 9, 0))
[1] FALSE
> 

3

SAS / IML、67

start m(a,b);return((a>b[:]&&a<a[:])||(b>a[:]&&b<b[:]))[<>];finish;

添え字削減演算子を使用して答えを取得し、要件に一致する要素が見つからない場合は0を返し、見つからない場合は1を返します。

非ゴルフ、ここでは、行列乗算を使用して実際の値自体を返します。

proc iml;
  b={1 2 3 4 5 6 7 8 9 };
  a={2 3 4 5 6};
  start m(a,b);
  return (a#(a>b[:] && a < a[:]) || b#(b>a[:] && b < b[:]))[<>];
  finish;

  z= m(a,b);
  print z;
quit;

テスト:

%macro test(a,b,n);
  z&n=m({&a},{&b});
  print z&n;
%mend test;

proc iml;
  b={1 2 3 4 5 };
  a={2 3 4 5 6 7};
start m(a,b);return((a>b[:]&&a<a[:])||(b>a[:]&&b<b[:]))[<>];finish;

* True;
 %test(1,2 3,1);
 %test(1 2 3,4 5 6,2);
 %test(3 4 5 6, 2 3 4 5,3);
 %test(6 5 9 5 6 0,6 2 0 9 5 2,4);
 %test(0 4, 9 1 0 2 8 0 5 5 4 9,5);
* False;
 %test(1,2,6);
 %test(2 4, 5,7);
 %test(1 5, 2 3 4 5,8);
 %test(2 1 2 3 1 3, 5 1 6,9);
 %test(4 4 5 2 4 0, 9 2 10 1 9 0,10);

quit;

(読みやすさのために凝縮)

z1 1

z2 1

z3 1

z4 1

z5 1

z6 0

z7 0

z8 0

z9 0

z10 0


2

Python 2.7、 102 98 96

lambda p:any([1for i in 0,1for e in p[i]if g[i^1]<e<g[i]]for g in[[sum(l)*1./len(l)for l in p]])

入力を2つの入力の配列として受け取り、ブール値を返します。
ロジックは-2つのリストの平均を見つけ、それから自身のリストの平均よりも小さく、他のリストの平均よりも大きい要素を見つけます。

与えられた入力に対してそれをテストすることはここでデモされます


2
*1.代わりに*1.0バイトを保存することができます。あるいは、Python 3でこれを行うと、除算はデフォルトでfloatを返すため、その乗算はまったく必要ありません。(Python 3を使用するためにコードをまったく変更する必要はないと思います。)
mathmandan

@mathmandan 1バイト節約できました。ありがとう:)
カメハメハ

あなたは除去することによって、それを匿名関数を作ることができますf=し、変更in[0,1]forしますin 0,1for。実際には101バイトであるため、これにより98になります
。-ケード

@ Vioz-ありがとう、それができるとは知らなかった:)
カメハメハ

2

CJam、28バイト

{{_:+1$,d/\+}%$~(m],@0=i)>&}

これは、スタックから2次元配列をポップし、代わりに可動要素の配列を残す匿名関数です。

サポートされているブラウザーでは、CJamインタープリターですべてのテストケースを一度に検証できます。

テストケース

コード

q~]{{_:+1$,d/\+}%$~(m],@0=i)>&}%:p

入力

[[1] [2 3]]
[[1 2 3] [4 5 6]]
[[3 4 5 6] [2 3 4 5]]
[[6 5 9 5 6 0] [6 2 0 9 5 2]]
[[0 4] [9 1 0 2 8 0 5 5 4 9]]
[[1] [2]]
[[2 4] [5]]
[[1 5] [2 3 4 5]]
[[2 1 2 3 1 3] [5 1 6]]
[[4 4 5 2 4 0] [9 2 10 1 9 0]]

出力

[2]
[4]
[4]
[5]
[4]
""
""
""
""
""

使い方

AとBが配列でavg(A)≤avg(B)の場合、B∩{⌊avg(A)⌋+ 1、…、⌈avg(B)⌉-1}が空でないかどうかを確認するだけです。この交差点の要素をBからAに移動すると、両方の平均を増やすことができます。

{          }%              e# For each of the arrays:
 _:+                       e#   Compute the sum of its elements.
    1$,                    e#   Compute its length.
       d/                  e#   Cast to Double and perform division.
         \+                e#   Prepend the computed average to the array.
             $             e# Sort the arrays (by the averages).
              ~            e# Dump both arrays on the stack.
               (           e# Shift out the higher average.
                m]         e# Round up to the nearest integer b.
                  ,        e# Push [0 ... b-1].
                   @0=     e# Replace the array with lower average by its average.
                      i)   e# Round down to the nearest integer a and add 1.
                        >  e# Skip the first a integer of the range.
                           e# This pushes [a+1 ... b-1].
                         & e# Intersect the result with the remaining array.

これにより、配列のすべての要素の配列がより高い平均でプッシュされ、両方の平均を増やすために移動できます。この結果を達成するために要素を移動できない場合にのみ、この配列は空/偽です。


1

ルビー、86

A=->x{x.reduce(0.0,:+)/x.size}
F=->q{b,a=q.sort_by{|x|A[x]};a.any?{|x|x<A[a]&&x>A[b]}}

2つの配列を含む配列を入力として受け取ります。

他のグループの平均よりも高い、より高い平均を持つグループからサブ平均アイテムを見つけようとします。

テスト:http : //ideone.com/444W4U


すでにRubyソリューションがあることに気付かずに作業を開始し、非常によく似たものになりましたが、関数に最初のリストが「より良い」と仮定し、それ自体を逆方向に呼び出すことで、2文字少なくなります。f=->a,s=1{i,j=a.map{|x|x.inject(0.0,:+)/x.size};a[0].any?{|y|i>y&&j<y}||s&&f[b,a,p]}
-histocrat

@histocrat素敵なアプローチ!bただし、変数に関するNameErrorが表示されます。再帰呼び出しは次のようにすべきだと思いますf[a.rotate,p]
クリスチャンルパスク

1
おっと、だから不正行為でより良いスコアを得たのです。
-histocrat

1

Matlab、54

無名関数を使用する:

f=@(A,B)any([B>mean(A)&B<mean(B) A>mean(B)&A<mean(A)])

例:

>> f=@(A,B)any([B>mean(A)&B<mean(B) A>mean(B)&A<mean(A)])
f = 
    @(A,B)any([B>mean(A)&B<mean(B),A>mean(B)&A<mean(A)])

>> f([1 2 3],[4 5 6])
ans =
     1

>> f([3 4 5 6],[2 3 4 5])
ans =
     1

>> f([1 5 9],[4 5 7 8])
ans =
     0

1

C#、104

bool f(int[]a,int[]b){double i=a.Average(),j=b.Average();return a.Any(x=>x<i&&x>j)||b.Any(x=>x<j&&x>i);}

呼び出しの例:

f(new []{1,2,3}, new []{4,5,6})
f(new []{1}, new []{2, 3})
f(new []{1, 2, 3}, new []{4, 5, 6})
f(new []{3, 4, 5, 6}, new []{2, 3, 4, 5})
f(new []{6, 5, 9, 5, 6, 0}, new []{6, 2, 0, 9, 5, 2})
f(new []{0, 4}, new []{9, 1, 0, 2, 8, 0, 5, 5, 4, 9})

f(new []{1}, new []{2})
f(new []{2, 4}, new []{5})
f(new []{1, 5}, new []{2, 3, 4, 5})
f(new []{2, 1, 2, 3, 1, 3}, new []{5, 1, 6})
f(new []{4, 4, 5, 2, 4, 0}, new []{9, 2, 10, 1, 9, 0})

0

C ++ 14、157バイト

名前のないラムダとして、最後のパラメータで戻りますr。またはのようなコンテナAであるBと仮定します。vector<int>array<int,>

[](auto A,auto B,int&r){auto m=[](auto C){auto s=0.;for(auto x:C)s+=x;return s/C.size();};r=0;for(auto x:A)r+=x<m(A)&&x>m(B);for(auto x:B)r+=x<m(B)&&x>m(A);}

ゴルフをしていない:

auto f=
[](auto A,auto B,int&r){
  auto m=[](auto C){
   auto s=0.;
   for(auto x:C) s+=x;
   return s/C.size();
  };
  r=0;
  for (auto x:A) r+=x<m(A)&&x>m(B);
  for (auto x:B) r+=x<m(B)&&x>m(A);
}
;

使用法:

int main() {
  std::vector<int>
    a={1,2,3}, b={4,5,6};
  //  a={1,5,9}, b={4,5,7,8};
  int r;
  f(a,b,r);
  std::cout << r << std::endl;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.