Zjawisko Willa Rogersa

35

Tak zwane zjawisko Will Rogers opisuje sposób dostrajania statystyki poprzez podniesienie średniej w dwóch (wielu) zestawach, gdy jeden element jest przenoszony między dwoma zestawami. Jako prosty przykład rozważ dwa zestawy

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

Ich średnie arytmetyczne są 2i 5, odpowiednio. Jeśli przeniesiemy 4do A:

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

Teraz są średnie 2.5i 5.5, odpowiednio, więc obie średnie zostały podniesione przez proste przegrupowanie.

Jako kolejny przykład rozważ

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

Z drugiej strony nie jest możliwe podniesienie obu średnich dla zbiorów

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

Wyzwanie

Biorąc pod uwagę dwie listy nieujemnych liczb całkowitych, określ, czy możliwe jest podniesienie obu średnich, przenosząc jedną liczbę całkowitą z jednej listy na drugą.

Średnia pustej listy nie jest zdefiniowana, więc jeśli jedna z list zawiera tylko jeden element, tego elementu nie można przenieść.

Możesz napisać program lub funkcję, pobierając dane wejściowe przez STDIN (lub najbliższą alternatywę), argument wiersza poleceń lub argument funkcji i wypisując wynik przez STDOUT (lub najbliższą alternatywę), wartość zwracaną funkcji lub parametr funkcji (wyjściowej).

Dane wejściowe mogą być pobierane w dowolnym dogodnym formacie ciągu lub listy.

Nie można zakładać, że elementy na każdej liście są unikalne, ani że są posortowane. Możesz założyć, że obie listy zawierają co najmniej jeden element.

Wyjście powinno być zgodne z prawdą, jeśli obie wartości średnie można podnieść, przesuwając jedną liczbę całkowitą, a fałsz w przeciwnym razie.

To jest kod golfowy, więc wygrywa najkrótsza odpowiedź (w bajtach).

Przypadki testowe

Prawda:

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

Falsy:

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

Liderów

Oto fragment kodu, który pozwala wygenerować zarówno zwykłą tabelę wyników, jak i przegląd zwycięzców według języka.

Aby upewnić się, że twoja odpowiedź się pojawi, zacznij od nagłówka, korzystając z następującego szablonu Markdown:

# Language Name, N bytes

gdzie Njest rozmiar twojego zgłoszenia. Jeśli poprawisz swój wynik, możesz zachować stare wyniki w nagłówku, przekreślając je. Na przykład:

# 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
źródło
Jako matematyk, a nie programista, nie jestem w stanie sprostać temu wyzwaniu, ale interesuje mnie następujące pytanie: czy można podnieść obie średnie, przesuwając pewną liczbę całkowitą (powiedzmy pięć) z jednego zestawu na drugi , czy zawsze wynika, że ​​obie wartości średnie można podnieść, przesuwając tylko jedną liczbę całkowitą ? To pokazuje, że wyzwanie naprawdę obejmuje wszystkie przypadki.
Trevor J Richards
3
@TrevorRichards Myślę, że obejmuje to ostatni przypadek testu na fałsz. Można przesunąć 1i 9powyżej, które mogłyby podnieść obie średnie, ale nie można zrobić poprzez przeniesienie jednego.
Martin Ender
@ TrevorRichards Ogólnie, jeśli zbiory A i B mają średnie a i b z <b, wówczas obie średnie można podnieść, jeśli istnieje podzbiór C B, który ma średnią c taką, że a <c <b. Z drugiej strony, jeśli wymagasz, aby wszystkie elementy przeniesione z B do A miały wartości <b, twoja hipoteza byłaby prawdziwa.
Alchymist

Odpowiedzi:

11

Pyth, 29 28 26 24 bajtów

Dzięki @Jakube za uratowanie mi 3 bajtów za pomocą .pi L.

Bardzo proste, sprawdza, czy którykolwiek element na liście 2 jest większy niż średnia z listy 1 i mniej niż średnia z listy 2, a następnie powtarza się z przełączoną listą 1 i listą 2.

Lcsblbff&>YyhT<YyeTeT.pQ

Drukuje niepustą listę dla prawdy i []dla 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

Wypróbuj online tutaj .

Pakiet testowy.

Maltysen
źródło
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)

Pobiera dwie listy jako dane wejściowe. Sprawdza, czy pierwsza lista zawiera element większy niż średnia, ale mniejszy niż drugi. Następnie robi to samo dla dwóch zamienionych wejść. Posiadanie dwuwarstwowego zrozumienia listy było krótsze niż zdefiniowanie oddzielnej funkcji do wypróbowania dwóch rzędów (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
źródło
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

możemy sprawdzić, czy powiększamy lub obniżamy średnią, sprawdzając, czy element do usunięcia lub włączenia jest większy, czy mniejszy niż średnia.

możemy to sprawdzić, sprawdzając, czy średnia jest mniejsza czy większa od elementu, usuwając ten element z tablicy i sprawdzając, czy średnia nowej tablicy jest ujemna czy dodatnia, co z kolei jest tak samo jak sprawdzenie, czy suma jest dodatnia czy ujemna .

sprawdzenie, że jest to bardzo proste jako sum.map(-n+).

dumny haskeller
źródło
6

Mathematica, 49 47 bajtów

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

Ocenia czystą funkcję, która oczekuje danych wejściowych w formularzu {list1, list2}.

jcai
źródło
4

APL, 45 40 bajtów

Zaoszczędź 5 bajtów dzięki Morisowi Zucca!

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

Tworzy to nienazwaną funkcję dyadyczną, która akceptuje tablice po lewej i prawej stronie i zwraca 1 lub 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
}

Możesz spróbować online .

Alex A.
źródło
1
możesz zapisać średnią jako: (+ / ÷ ≢)
Moris Zucca
@MorisZucca Dzięki! Edytowane, aby użyć Twojej sugestii.
Alex A.,
3

R, 66 52 bajtów

Jako funkcja bez nazwy, która przyjmuje 2 wektory. Pozbyłem się fałszywych, które.

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

Testy

> 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
źródło
3

SAS / IML, 67

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

Używa operatorów redukcji indeksu dolnego, aby uzyskać odpowiedź, zwracając 0, jeśli nie zostanie znaleziony element spełniający wymagania lub 1, jeśli taki zostanie znaleziony.

Bez golfa, tutaj zwracam samą wartość rzeczywistą za pomocą mnożenia macierzy:

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;

Testy:

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

(Skondensowane dla czytelności)

z1 1

z2 1

z3 1

z4 1

z5 1

z6 0

z7 0

z8 0

z9 0

z10 0

Joe
źródło
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]])

Pobiera dane wejściowe jako tablicę 2 danych wejściowych i zwraca wartość logiczną.
Logika polega na znalezieniu średniej z 2 list, a następnie znajdź element taki, że jest mniejszy niż średni z własnej listy i większy niż średnia z drugiej listy.

Testowanie pod kątem danych wejściowych jest tutaj pokazane

Kamehameha
źródło
2
Możesz zrobić *1.zamiast *1.0zapisać bajt. Alternatywnie, jeśli zrobisz to w Pythonie 3, dzielenie zwróci domyślnie liczbę zmiennoprzecinkową, więc w ogóle nie potrzebujesz tego mnożenia. (Nie sądzę, abyś musiał w ogóle zmieniać kod, aby korzystać z Pythona 3.)
mathmandan
@mathmandan Uratował mi bajt. Dzięki :)
Kamehameha
Możesz zmienić tę funkcję w anonimową, usuwając ją f=i zmieniając in[0,1]forna in 0,1for. Ponieważ faktycznie masz 101 bajtów, obniżasz to do 98.
Kade
@ Vioz- Dzięki, nie wiedziałem, że mogę to zrobić :)
Kamehameha
2

CJam, 28 bajtów

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

Jest to anonimowa funkcja, która wyrywa dwuwymiarową tablicę ze stosu i pozostawia w zamian tablicę ruchomych elementów.

W obsługiwanych przeglądarkach możesz zweryfikować wszystkie przypadki testowe jednocześnie w interpretera CJam .

Przypadki testowe

Kod

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

Wkład

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

Wydajność

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

Jak to działa

Jeśli A i B są tablicami, a avg (A) ≤ avg (B) , po prostu sprawdzamy, czy B ∩ {⌊avg (A) ⌋ + 1,…, ⌈avg (B) ⌉-1} nie jest puste. Dowolny element na tym skrzyżowaniu można przesunąć z B do A, aby zwiększyć obie średnie.

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

Spycha to tablicę wszystkich elementów tablicy z wyższą średnią, którą można przesunąć w celu zwiększenia obu średnich. Ta tablica jest pusta / falsy wtedy i tylko wtedy, gdy nie można przenieść żadnych elementów, aby osiągnąć ten wynik.

Dennis
źródło
1

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

Pobiera jako dane wejściowe tablicę zawierającą dwie tablice.

Próbuje znaleźć pozycję poniżej średniej z grupy o wyższej średniej, która jest większa niż średnia w innej grupie.

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

Cristian Lupascu
źródło
Rozpocząłem pracę nad tym, nie zauważając, że istnieje już rozwiązanie Ruby, a skończyło się czymś bardzo podobnym, ale łączy w sobie dwa mniej znaków, ponieważ funkcja zakłada, że ​​pierwsza lista jest „lepsza”, a następnie wywołuje się na odwrót. 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]}
histokrata
@histocrat Ładne podejście! Dostaję NameError dotyczący zmiennej b. Myślę, że połączenie rekurencyjne powinno być coś w rodzaju f[a.rotate,p].
Cristian Lupascu,
1
Ups, więc dzięki temu oszukałem lepszy wynik.
histocrat
1

Matlab, 54

Korzystanie z anonimowej funkcji:

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

Przykłady:

>> 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
źródło
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);}

Przykładowe połączenia:

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
źródło
0

C ++ 14, 157 bajtów

Jako nienazwana lambda, zwraca ostatni parametr r. Zakłada się A, Bże są to pojemniki takie jak vector<int>lub 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);}

Nie golfowany:

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

Stosowanie:

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
źródło