Уилл Роджерс Феномен


35

Так называемый феномен Уилла Роджерса описывает способ подстройки статистики путем увеличения среднего значения в двух (нескольких) наборах, когда один элемент перемещается между двумя наборами. В качестве простого примера рассмотрим два набора

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

Их арифметическими средствами являются 2и 5, соответственно. Если мы переместим 4в A:

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

Теперь средние значения 2.5и 5.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:

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

Leaderboards

Вот фрагмент стека, который генерирует как регулярную таблицу лидеров, так и обзор победителей по языкам.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

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


Как математик, а не программист, я не могу решить эту проблему, но меня интересует следующий вопрос: можно ли повысить обе средние величины, переместив некоторую конечную коллекцию целых чисел (скажем, пять) из одного набора в другой? всегда ли из этого следует, что обе средние могут быть подняты путем сдвига только одного целого числа ? Таким образом, показывая, что задача действительно охватывает все случаи.
Тревор Дж. Ричардс,

3
@TrevorRichards Я думаю, что последний фальшивый контрольный пример покрывает это. Вы можете переместить a 1и 9более, что поднимет оба средних, но вы не можете сделать это, сдвинув одно.
Мартин Эндер

@TrevorRichards В общем, если наборы A & B имеют средние значения a & b с a <b, то оба средних могут быть повышены, если существует подмножество C в B, имеющее среднее значение c, такое, что a <c <b. С другой стороны, если вам требуется, чтобы все элементы, перемещенные из B в A, имели значения <b, ваша гипотеза была бы верной.
Алхимик

Ответы:


11

Pyth, 29 28 26 24 байта

Спасибо @Jakube за то, что сэкономили мне 3 байта с помощью .pи 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
Вы можете написать среднее значение как: (+ / ÷ ≢)
Морис Цукка

@ MorisZucca Спасибо! Отредактировано, чтобы использовать ваше предложение.
Алекс А.

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;

(Сжатый для удобства чтения)

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, деление вернет число с плавающей запятой по умолчанию, поэтому вам не понадобится это умножение вообще. (Я не думаю, что вам вообще придется менять свой код, чтобы использовать Python 3.)
mathmandan

@mathmandan Спас меня байт. Спасибо :)
Kamehameha

Вы можете сделать это анонимной функцией, удалив 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 Хороший подход! Я получаю NameError относительно переменной, bхотя. Я думаю, что рекурсивный вызов должен быть примерно таким f[a.rotate,p].
Кристиан Лупаску,

1
К сожалению, так я получил лучший результат, обманывая.
гистократ

1

Матлаб, 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);}

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

Использование:

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;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.