Das Will Rogers-Phänomen

35

Das sogenannte Will Rogers-Phänomen beschreibt eine Möglichkeit, die Statistik zu optimieren, indem der Durchschnitt in zwei (Mehrfach-) Sätzen erhöht wird, wenn ein Element zwischen den beiden Sätzen verschoben wird. Betrachten Sie als einfaches Beispiel die beiden Mengen

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

Deren arithmetische Mittel sind 2und 5jeweils. Wenn wir den 4zu bewegen A:

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

Nun sind die Mittelwerte sind 2.5und 5.5jeweils so haben beide Mittelwerte durch eine einfache Umgruppierung angehoben.

Als weiteres Beispiel betrachten

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

Andererseits ist es nicht möglich, beide Mittelwerte für die Sätze zu erhöhen

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

Die Herausforderung

Bestimmen Sie anhand von zwei Listen nicht negativer Ganzzahlen, ob es möglich ist, beide Durchschnitte zu erhöhen, indem Sie eine einzelne Ganzzahl von einer Liste zur anderen verschieben.

Der Durchschnitt einer leeren Liste ist nicht definiert. Wenn also eine der Listen nur ein Element enthält, kann dieses Element nicht verschoben werden.

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Die Eingabe kann in einem beliebigen geeigneten Zeichenfolge- oder Listenformat erfolgen.

Sie dürfen nicht davon ausgehen, dass die Elemente in jeder Liste eindeutig oder sortiert sind. Sie können davon ausgehen, dass beide Listen mindestens ein Element enthalten.

Die Ausgabe sollte wahr sein, wenn beide Mittelwerte durch Verschieben einer einzelnen Ganzzahl erhöht werden können, andernfalls ist sie falsch .

Dies ist Codegolf, daher gewinnt die kürzeste Antwort (in Bytes).

Testfälle

Wahrheit:

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

Falsch:

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

Bestenlisten

Hier ist ein Stack-Snippet, um sowohl eine reguläre Rangliste als auch eine Übersicht der Gewinner nach Sprache zu generieren.

Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

# Language Name, N bytes

Wo Nist die Größe Ihres Beitrags? Wenn Sie Ihre Punktzahl verbessern, können Sie alte Punkte in der Überschrift behalten, indem Sie sie durchstreichen. Zum Beispiel:

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

Martin Ender
quelle
Als Mathematiker und nicht als Kodierer kann ich die Herausforderung nicht wirklich angehen, aber die folgende Frage interessiert mich: Wenn beide Durchschnitte durch Verschieben einer endlichen Ansammlung von ganzen Zahlen (sagen wir fünf) von einer Menge zur anderen gebildet werden können , folgt daraus immer, dass beide Durchschnitte durch Verschiebung nur einer ganzen Zahl angehoben werden können ? Dies zeigt, dass die Herausforderung wirklich alle Fälle abdeckt.
Trevor J Richards
3
@ TrevorRichards Ich denke, der letzte falsche Testfall deckt dies ab. Sie könnten ein 1und 9mehr bewegen , was beide Durchschnitte erhöhen würde, aber Sie können dies nicht tun, indem Sie einen einzelnen bewegen.
Martin Ender
@TrevorRichards Wenn die Mengen A und B Durchschnittswerte a und b mit a <b haben, können beide Durchschnittswerte erhöht werden, wenn es eine Teilmenge C von B gibt, deren Durchschnitt c so ist, dass a <c <b ist. Wenn Sie jedoch alle von B nach A verschobenen Elemente mit Werten <b benötigen, ist Ihre Hypothese wahr.
Alchymist

Antworten:

11

Pyth, 29 28 26 24 Bytes

Vielen Dank an @Jakube für das Speichern von 3 Bytes mit .pund L.

Ganz einfach: Prüft, ob Elemente in Liste 2 größer als der Mittelwert von Liste 1 und kleiner als der Mittelwert von Liste 2 sind, und wiederholt dies, wobei Liste 1 und Liste 2 vertauscht sind.

Lcsblbff&>YyhT<YyeTeT.pQ

Druckt eine nicht-leere Liste für truthy und []für Falsey.

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

Probieren Sie es hier online aus .

Test Suite.

Maltysen
quelle
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)

Nimmt zwei Listen als Eingabe. Prüft, ob die erste Liste ein Element enthält, das größer als der Durchschnitt, aber kleiner als das andere ist. Dann gilt das gleiche für die beiden getauschten Eingänge. Ein zweischichtiges Listenverständnis war kürzer als die Definition einer separaten Funktion, um die beiden Befehle auszuprobieren (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)
xnor
quelle
7

Haskell, 58 57

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

Wir können überprüfen, ob wir den Durchschnitt vergrößern oder verkleinern, indem wir überprüfen, ob das zu entfernende oder einzuschließende Element größer oder kleiner als der Durchschnitt ist.

Wir können dies überprüfen, indem wir prüfen, ob der Durchschnitt kleiner oder größer als ein Element ist, indem wir dieses Element aus dem Array entfernen und prüfen, ob der Durchschnitt des neuen Arrays negativ oder positiv ist. Dies ist wiederum eine Überprüfung, ob die Summe positiv oder negativ ist .

Überprüfung, die sehr einfach als ausgedrückt wird sum.map(-n+).

stolzer haskeller
quelle
6

Mathematica, 49 47 Bytes

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

Wird zu einer reinen Funktion ausgewertet, die Eingaben im Formular erwartet {list1, list2}.

jcai
quelle
4

APL, 45 bis 40 Bytes

5 Bytes gespart dank Moris Zucca!

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

Dadurch wird eine unbenannte dyadische Funktion erstellt, die Arrays links und rechts akzeptiert und 1 oder 0 zurückgibt.

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

Sie können es online ausprobieren .

Alex A.
quelle
1
Sie können den Mittelwert schreiben als: (+ / ÷ ÷)
Moris Zucca
@ MorisZucca Danke! Bearbeitet, um Ihren Vorschlag zu verwenden.
Alex A.
3

R, 66 52 Bytes

Als unbenannte Funktion werden 2 Vektoren akzeptiert. Ich habe ein paar falsche Sachen beseitigt.

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

Tests

> 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
> 
MickyT
quelle
3

SAS / IML, 67

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

Es verwendet Operatoren zur Indexreduktion, um die Antwort zu erhalten. Sie geben 0 zurück, wenn kein Element gefunden wird, das den Anforderungen entspricht, oder 1, wenn eines gefunden wird.

Nicht golfen, hier gebe ich den tatsächlichen Wert selbst mit Matrixmultiplikation zurück:

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;

Tests:

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

(Aus Gründen der Lesbarkeit gekürzt)

z1 1

z2 1

z3 1

z4 1

z5 1

z6 0

z7 0

z8 0

z9 0

z10 0

Joe
quelle
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]])

Nimmt die Eingabe als Array der 2 Eingaben und gibt einen Booleschen Wert zurück.
Die Logik lautet: -finde den Durchschnitt der 2 Listen und finde dann ein Element so, dass es kleiner als der Durchschnitt der eigenen Liste und größer als der Durchschnitt der anderen Liste ist.

Das Testen für die angegebenen Eingaben wird hier demonstriert

Kamehameha
quelle
2
Sie können *1.stattdessen *1.0ein Byte speichern. Wenn Sie dies in Python 3 tun, gibt die Division standardmäßig einen Gleitkommawert zurück, sodass Sie diese Multiplikation überhaupt nicht benötigen. (Ich glaube nicht, dass Sie Ihren Code ändern müssen, um Python 3 zu verwenden.)
mathmandan
@mathmandan Sparte mir ein Byte. Danke :)
Kamehameha
Sie können es eine anonyme Funktion machen durch Entfernen f=und Änderung in[0,1]forzu in 0,1for. Da Sie tatsächlich bei 101 Bytes sind, werden Sie auf 98 reduziert.
Kade
@ Vioz- Danke, wusste nicht, dass ich das tun könnte :)
Kamehameha
2

CJam, 28 Bytes

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

Dies ist eine anonyme Funktion, die ein zweidimensionales Array aus dem Stapel entfernt und im Gegenzug ein Array beweglicher Elemente zurücklässt.

In unterstützten Browsern können Sie alle Testfälle gleichzeitig im CJam-Interpreter überprüfen .

Testfälle

Code

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

Eingang

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

Ausgabe

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

Wie es funktioniert

Wenn A und B die Arrays sind und avg (A) ≤ avg (B) , prüfen wir einfach, ob B ∩ {⌊avg (A) ⌋ + 1,…, ⌈avg (B) ⌉-1} nicht leer ist. Jedes Element in diesem Schnittpunkt kann von B nach A verschoben werden , um beide Mittelwerte zu erhöhen.

{          }%              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.

Dies verschiebt das Array aller Elemente des Arrays mit dem höheren Durchschnitt, der verschoben werden kann, um beide Durchschnitte zu erhöhen. Dieses Array ist nur dann leer / falsch, wenn keine Elemente verschoben werden können, um dieses Ergebnis zu erzielen.

Dennis
quelle
1

Rubin, 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]}}

Nimmt als Eingabe ein Array, das die beiden Arrays enthält.

Versucht, ein unterdurchschnittliches Element aus der Gruppe mit dem höheren Durchschnitt zu finden, der größer als der Durchschnitt der anderen Gruppe ist.

Test: http://ideone.com/444W4U

Cristian Lupascu
quelle
Begonnen, ohne es zu bemerken, gab es bereits eine Ruby-Lösung, die etwas sehr Ähnliches ergab, aber zwei Zeichen weniger enthält, indem die Funktion davon ausgeht, dass die erste Liste 'besser' ist, und sich dann umgekehrt nennt. 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]}
Histokrat
@histocrat Netter Ansatz! Ich bekomme allerdings einen NameError bezüglich der Variablen b. Ich denke, der rekursive Aufruf sollte so etwas wie sein f[a.rotate,p].
Cristian Lupascu
1
Hoppla, so habe ich durch Schummeln eine bessere Punktzahl erzielt.
Histokrat
1

Matlab, 54

Verwenden einer anonymen Funktion:

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

Beispiele:

>> 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
Luis Mendo
quelle
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);}

Beispielaufrufe:

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})
Stephan Schinkel
quelle
0

C ++ 14, 157 Bytes

Gibt als unbenanntes Lambda den letzten Parameter zurück r. Annimmt A, Bwerden Behälter wie vector<int>oder 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);}

Ungolfed:

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

Verwendung:

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;
}
Karl Napf
quelle