威尔·罗杰斯现象


35

所谓的威尔·罗杰斯Will Rogers)现象描述了一种通过在两个元素之间移动一个元素时提高两个(多)集合中的平均值来调整统计量的方法。举一个简单的例子,考虑两组

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

它们的算术平均值分别为 25。如果我们移动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}

挑战

给定两个非负整数列表,请确定是否可以通过将一个整数从一个列表移动到另一个列表来提高两个平均值。

空列表的平均值未定义,因此,如果列表之一仅包含一个元素,则不能移动该元素。

您可以编写程序或函数,通过STDIN(或最接近的替代方案),命令行参数或函数自变量获取输入,并通过STDOUT(或最接近的替代方案),函数返回值或函数(out)参数输出结果。

输入可以采用任何方便的字符串或列表格式。

您不能假定每个列表中的元素都是唯一的,也不可以对它们进行排序。您可以假设两个列表都包含至少一个元素。

输出应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]

排行榜

这是一个堆栈片段,用于按语言生成常规排行榜和获胜者概述。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

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


作为一个数学家而不是一个编码器,我无法真正解决挑战,但是我对以下问题感兴趣:如果可以通过将一些有限的整数集合(例如五个)从一组集合转移到另一个集合来提高两个平均值,是否总是可以通过移动一个整数来提高两个平均值?因此表明挑战确实涵盖了所有情况。
Trevor J Richards

3
@TrevorRichards我认为最后一个虚假的测试用例涵盖了这一点。您可以移动a 19,这将同时提高两个均值,但不能通过移动单个均值来做到。
马丁·恩德

@TrevorRichards通常,如果集合A和B的a和b的平均值为a <b,则如果B的子集C的平均值为c使得a <c <b,则可以同时提高两个平均值。另一方面,如果您要求所有从B移到A的元素的值都小于b,那么您的假设将是正确的。
Alchymist 2015年

Answers:


11

Pyth,29 28 26 24字节

感谢@Jakube使用.p和为我节省了3个字节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)

将两个列表作为输入。检查第一个列表中的元素是否大于平均元素但小于另一个元素。然后,对交换的两个输入执行相同的操作。具有两层列表的理解要比定义一个单独的函数来尝试两个命令的时间要短(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
您可以将平均值写为:(+ /÷≢)
Moris Zucca

@MorisZucca谢谢!编辑使用您的建议。
Alex A.

3

R, 66 52字节

作为一个未命名的函数,它接受2个向量。摆脱了一些虚假的内容。

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;

(为便于阅读而精简)

11

z2 1

z3 1

z4 1

z5 1

零6

零7

零8

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中执行此操作,默认情况下除法将返回浮点数,因此您根本不需要该乘法。(我认为使用Python 3根本不需要更改代码。)
mathmandan 2015年

@mathmandan为我节省了一个字节。谢谢:)
Kamehameha 2015年

您可以删除f=并更改in[0,1]for为,以使其成为匿名函数in 0,1for。由于您实际上只有101个字节,因此将您降低到98个字节
。– Kade

@ Vioz-谢谢,不知道我能做到这一点:)
Kamehameha

2

CJam,28个字节

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

这是一个匿名函数,该函数从堆栈中弹出一个二维数组,并返回一个可移动元素的数组作为回报。

在受支持的浏览器中,您可以在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]}}

将包含两个数组的数组作为输入。

尝试从该组中找到一个子平均项目,该子平均项目的平均值高于另一个组的平均值。

测试:http//ideone.com/444W4U


开始工作时没有注意到已经有一个Ruby解决方案,最后得到了非常相似的东西,但是通过让该函数假定第一个列表“更好”,然后以相反的方式进行调用,它减少了两个字符。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不错的方法!我得到有关变量的NameError b。我认为递归调用应类似于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个字节

作为未命名的lambda,由last参数返回r。假定AB要像容器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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.