Compare the averages of my lists

Getting the average of a list (e.g [2,6,7])

• Get the length of the list: [2,6,7] -> 3
• Sum the numbers in the list: 2 + 6 + 7 = 15.
• Divide the sum by their count: 15 / 3 = 5.

You should compare the averages of two lists of positive integers N and M, by returning a value if N has a higher average, another value if M has a higher average, and another one in case of a tie.

I/O rules

All the standard Input and Output methods are allowed.

Input

You may take input as two separate lists, a nested list, or anything else you consider suitable for the task. Please specify the format.

Output

The values provided have to be distinct and must consist of at least one non-whitespace character. Also, they must be consistent between runs (a single value for N, a single value for M, a single value for Tie). Please specify those in your answer. The values can be non-empty Strings, Bool values, Integers, or anything you consider suitable.

Specs

• The lists will not necessarily have equal length.

• You are guaranteed that the lists are non-empty.

Test Cases

I chose the values N wins, M wins and Tie, which are pretty much self-evident.

N, M                     ->   Output     (Averages)

,                  -> N wins  (N has 7, M has 6 )
[4,5], [4,4]             -> N wins  (N has 4.5, M has 4)
[2,3,4], [4,5,6]         -> M wins  (N has 3, M has 5)
[4,1,3], [7,3,2,1,1,2]   -> Tie     (both have 2.666...)
[100,390,1], [89,82,89]  -> N wins  (N has 163.666..., M has 86.666...)
[92,892], [892,92]       -> Tie     (lists are basically identical)
[10,182], [12,78,203,91] -> Tie     (both have 96)

Default Loopholes apply. Explanations are encouraged! This is , so the shortest code in bytes wins!

• – Mr. Xcoder Jul 5 '17 at 17:55
• if my language of choice only supports integers, can I take input multiplied by 1000? That way the calculated averages would still be accurate to 3 decimal places – Skidsdev Jul 7 '17 at 10:28
• @Mayube Yes, that is allowed – Mr. Xcoder Jul 7 '17 at 10:29
• We have to return an output of at least 1 character. Does that mean we are required to return a character or a string? Or do you mean an output whose string value is of a least 1 character? – Olivier Grégoire Jul 7 '17 at 12:14
• @OlivierGrégoire The output given must be at least 1 character long (you cannot return an empty string, but can return any String of at least 1 character, and also any non-whitespace character). IT's up to you. – Mr. Xcoder Jul 7 '17 at 12:19

Actually, 5 bytes

♂æi-s

Try it online!

1 for N > M, 0 for N = M, -1 for N < M.

Explanation:

♂æi-s Takes input in format [N, M]
♂æ    Map average
i   Dump to stack in reverse
-  Subtract
s Get sign

Mathematica, 15 bytes

Order@@Mean/@#&

Try it online!

Function which expects a list of two lists. Mean/@# takes the arithmetic mean of each list in the input, then those means are passed into Order, which returns -1 if the first list wins, 0 if there is a tie, and 1 if the second list wins.

JavaScript (ES6), 52 50 bytes

(Saved 2 bytes thanks to @Shaggy.)

Here are two 50-byte solutions:

f=(N,M,a=eval(N.join+)/N.length)=>M?(a-f(M))/0:a

(N,M,A=a=>eval(a.join+)/a.length)=>(A(N)-A(M))/0

Returns Infinity for N, -Infinity for M, and NaN for a tie.

The first solution may require a bit of explanation due to the recursion:

On the first call to the function, a is initialized as the average of the N array:

a=eval(N.join+)/N.length

M has a value at this point, so the first part of the conditional expression is called:

M ? (a-f(M))/0 : a  ----------

The function is called within this expression, this time substituting M for N.

On this second call to the function, a is initialized as the average of N –– which was M in the previous call.

Since there is no second parameter during this call to the function, the second part of the conditional expression is triggered, which returns the average:

M ? (a-f(M))/0 : a  --

We can now understand the expression better:

(a - f(M)) / 0

It's:

(the average of N  minus  the average of M) divided by 0

The difference between the averages will be a positive number, a negative number, or 0.

Dividing the difference by 0 results in Infinity, -Infinity, or NaN – providing the three distinct values as required.

Test Cases:

f=(N,M,a=eval(N.join+)/N.length)=>M?(a-f(M))/0:a

console.log(f(,                  )) // N wins  (N has 7, M has 6 )
console.log(f([4,5], [4,4]             )) // N wins  (N has 4.5, M has 4)
console.log(f([2,3,4], [4,5,6]         )) // M wins  (N has 3, M has 5)
console.log(f([4,1,3], [7,3,2,1,1,2]   )) // Tie     (both have 2.666...)
console.log(f([100,390,1], [89,82,89]  )) // N wins  (N has 163.666..., M has 86.666...)
console.log(f([92,892], [892,92]       )) // Tie     (lists are basically identical)
console.log(f([10,182], [12,78,203,91] )) // Tie     (both have 96)

• Could you save a couple of bytes by moving A to the function parameters? – Shaggy Jul 5 '17 at 22:56

Mathematica, 21 bytes

Sign[Mean@#-Mean@#2]&

1 for # wins, -1 for #2 wins, 0 for tie.

• or, equally long, Sign[#-#2&@@Mean/@#]& – Greg Martin Jul 6 '17 at 2:20

MATL, 8 bytes

Soooo many modifiers (Y and Z). I can't find a way to make it shorter. sum / number_of_elements is three bytes. It might be a better way to do -ZS, but I can't find one.

YmiYm-ZS

Try it online!

% Take first input implicitly
Ym         % Mean of that input
i        % Grab second input
Ym      % Mean of that input
-     % Subtract
ZS   % Sign

Returns 1 if the first input is larger, 0 if they tie, and -1 if the second input is larger.

05AB1E, 9 bytes

1 if M wins, -1 if N wins and 0 for a tie.

vyOyg/}.S

Try it online!

Explanation

v           # for each y in list of lists
yO         # sum y
yg       # get length of y
/      # divide
}     # end loop
.S   # compare

Julia, 27 bytes

(x,y)->cmp(mean(x),mean(y))

Try it online!

Returns 1 if the first average is larger, -1 if second is, and 0 if they tie.

Python 2, 43 bytes

lambda p:cmp(*[sum(l)*1./len(l)for l in p])

Try it online!

Octave, 27 bytes

@(x,y)sign(mean(x)-mean(y))

Try it online!

Takes two vectors x.y as input, takes the mean of both vectors, and subtract one from the other. Get the sign of this, to get 1, 0 and -1 for the three different alternatives.

Python 2, 49 bytes

lambda N,M:cmp(1.*sum(N)/len(N),1.*sum(M)/len(M))

Try it online

• "...[the three outputs] must be consistent between runs" – Jonathan Allan Jul 5 '17 at 18:20
• @JonathanAllan Fixed – mbomb007 Jul 5 '17 at 18:24

APL (Dyalog), 11 bytes

Prompts for a list of two lists. Prints 1 if the left has higher average, 0 if they have the same average, and ¯1 if the right has higher average.

×-/(+/÷≢)¨⎕

Try it online!

prompt

( apply the following tacit function to each:

+/ the sum

÷ divided by

the tally

-/ insert (and evaluate) a minus between them

× signum

Javascript, 816658 56 bytes

saved 15 bytes thanks to Luke

saved 2 bytes thanks to Justin Mariner

n=>m=>Math.sign((a=b=>eval(b.join+)/b.length)(m)-a(n))

Tie is 0, M is 1 and N is -1. Called using currying syntax, eg. f()()

• You can improve this by quite a few bytes: you can remove the variable assignment, you can use curry syntax, you can remove the alert, and you can easily sum arrays by using eval(a.join+). a=>(b=a.map(c=>eval(c.join+)/c.length))-b?b>b:0 for 61 bytes. It takes input as an array of arrays, and outputs 0 for a tie, true for M and false for N. – Luke Jul 5 '17 at 18:44
• why don't you post it as your own answer? – SuperStormer Jul 5 '17 at 18:52
• You could save two more bytes by inlining the function (a) the first time it's used: n=>m=>Math.sign((a=b=>eval(b.join+)/b.length)(m)-a(n)). – Justin Mariner Jul 5 '17 at 19:11

<?foreach($_GET as$v)$r[]=array_sum($v)/count($v);echo$r<=>$r; Try it online! PHP, 69 bytes <?=($s=array_sum)($a=$_GET)/count($a)<=>$s($b=$_GET)/count($b); Try it online! spaceship operator -1 less then , 0 tie , 1 greater then Haskell, 65 43 Bytes Saved 22 bytes thanks to nimi! a x=sum x/sum[1|_<-x] x#y=compare(a x)$a y

There has to be a much better way... But type conversions screwed me.

Usage

(#)  

Returns GT if the first argument wins, LT if the second argument wins, and EQ if they tie.

Try it online!

• No need to cast sum$x with f.. Also: length x can be replaced with sum[1|_<-x], so you can get rid off f completely: a x=sum x/sum[1|_<-x]. – nimi Jul 5 '17 at 21:46 • Ah nice! Didn't even think to do that. – Henry Jul 5 '17 at 21:47 • ... oh and in #: ...(a x)$a y. – nimi Jul 5 '17 at 21:49
• ... even better: go pointfree with your main function, then you can even save the name for it: (.a).compare.a. Usage : ( (.a).compare.a )  . – nimi Jul 5 '17 at 21:58

Perl 6, 25 bytes

{sign [-] .map:{.sum/$_}} Try it online! Takes a single argument, a two-element list of lists of numbers. Returns 1 if the first list has a greater average, -1 if the second list does, and 0 if the averages are equal. JavaScript (ES6), 60 bytes a=>(b=(c=a.map(d=>eval(d.join+)/d.length)))-c)?b>0:0 Outputs 0 for Tie, true for N and false for M. JavaScript (ES6), 60 54 bytes -6 bytes thanks to @Luke and @Neil (i,[x,y]=i.map(v=>eval(v.join+)/v.length))=>y-x&&x>y Takes input as a 2-element array [N, M]. Outputs true, 0, or false for N, Tie, or M, respectively. Explanation (i, // input array: [N, M] [x,y] = // destructure assignment: set x and y to... i.map(v=> // the input values mapped as... eval(v.join+) // the sum, by joining the array with + / v.length // divided by the length ) ) => y-x && x>y // return 0 for tie, or the result of avg(N) > avg(M) Test Snippet Input numbers separated by spaces/commas. f= (i,[x,y]=i.map(v=>eval(v.join+)/v.length))=>y-x&&x>y <div oninput="O.value=f([N.value,M.value].map(x=>x.split(/[ ,]+/)))">N <input id=N> M <input id=M></div> Out: <input id=O disabled> • You can probably save some bytes by replacing Math.sign(y-x) by y-x?x>y:0. Outputs 0 for Tie, true for N and false for M. – Luke Jul 5 '17 at 18:57 • x-y&&x>y perhaps? – Neil Jul 5 '17 at 18:59 • @Neil Nice, even better – Justin Mariner Jul 5 '17 at 19:03 Pip, 13 bytes {$CM$+*a/#*a} This is a function that takes a list of lists. Returns 1 if the first average is bigger, -1 if the second is bigger, 0 if tied. Run all test cases here. Background This solution makes heavy use of two of Pip's metaoperators: •$, fold. Take a binary operator and apply it between the elements of a list. For instance, + is addition, but $+ sums a list. Note that$ makes a binary operator into a unary operator.
• *, map. Take a unary operator and apply it to each element of a list. For instance, # gives the length of a list, but #* gives (a list of) the lengths of the list's items.
• These two metaoperators can be combined: $+* maps fold/plus over a list, summing each of the list's elements. The other thing to know about Pip is that a lot of operators work item-wise on lists by default. For instance, [1 2 3] * 5 gives [5 10 15]; [1 2 3] * [2 3 4] gives [2 6 12]; and [[1 2] [3 4]] * [5 6] gives [[5 10] [18 24]]. Explanation We'll use an example input of [[2 3 4] [2 3 4 6]]: • {...} Defines a function. The (first) argument is bound to the local variable a. • #*a Map # to the function's argument, getting the lengths of the sublists. Result: [3 4] • a/#*a Divide (the elements of) the sublists of a by their respective lengths. Result: [[0.667 1 1.333] [0.5 0.75 1 1.5]] •$+*a/#*a
Map $+ (fold on addition) to that result, summing the sublists. Result: [3 3.75] •$CM$+*a/#*a Fold on CM, which gives -1, 0, or 1 depending on the comparison of its two operands (like Python's cmp). Result: -1 (because 3 is smaller than 3.75). You can also define functions in Pip by writing expressions containing the identity function _. For example, _*_ is a function that squares its argument--syntactic sugar for {a*a}, and fewer bytes. However, there's a bug in the current version of the interpreter that prevents _ from working with the * metaoperator. Once that's fixed, this solution can be 11 bytes:$CM\$+*_/#*_.

C (gcc), 91 98 bytes

u,v,j;f(x,y,a,b)int*a,*b;{for(u=v=0;x--;u+=a[x])for(j=0;j<y;)v+=b[j++];j=u*y-v;x=j>0?2:!j;}

Wrong place for C and probably the only answer that doesn't need division. At least the code is displayed without a slider.

Return 0,1,2 for M>N, M=N, M<N respectively. Takes input as length of M, length of N, M, N.

• Is taking length as an argument within the specs? Cuts significant code from a lot of these if it is. – Henry Jul 5 '17 at 21:05
• I don't know if there's another way for C to retrieve the length of an array. The length itself is more like an intrinsic part of array. – Keyu Gan Jul 6 '17 at 4:47

Brachylog, 8 bytes

⟨+/l⟩ᵐ-ṡ

Try it online!

Outputs 1 if the first list has a bigger average, -1 is the second list has a bigger average, and 0 if they are tied.

Explanation

ᵐ        Map:
⟨   ⟩           Fork:
+                Sum…
/               …divided by…
l              …length
-      Subtract
ṡ     Sign

Java, 105 bytes

s->s.stream().map(l->l.stream().reduce((i,j)->i+j).get()/l.size()).reduce((i,j)->Math.signum(i-j)).get();

Lambda that takes a nested list, as per allowable inputs.

Streams the list of lists, converts both to their averages, then returns the sign of the difference. 1 if the first list is larger, -1 if the second list is larger, 0 for a tie.

• Since "anything can be an input", just use Streams directly, like I did. – Olivier Grégoire Jul 7 '17 at 12:10

R 38 34 bytes

function(a,b)sign(mean(a)-mean(b))

Function that takes as input two numeric vectors. Returns 1 if first list average is higher, 0 if they are the same and -1 if second list average is higher.

• Is this an anonymous function that can be called without assignment? I don't know R but if it is you don't need the f=. – Sriotchilism O'Zaic Jul 6 '17 at 12:26
• @WheatWizard you are correct; additionally you can remove the {} from the function body. – Giuseppe Jul 6 '17 at 15:21
• Thanks for the input. It's my first attempt at codegolf. – zelite Jul 6 '17 at 15:22

MATL, 6 bytes

Don't be so mean!*

!-ssZS

Input stack order:

M
N

Output:

1 = N wins
-1 = M wins
0 = tie

Try it online!

!-ssZS
========
!           % transpose M
-          % N - M^T using elementwise subtraction and implicit expansion
s         % sum columns of the result
s        % sum the resulting row vector
ZS      % sign of the sum

*This answer was golfed without being mean to any poor, defenseless numbers.

Java (OpenJDK 8), 76 62 bytes

a->b->Math.signum(a.average().orElse(0)-b.average().orElse(0))

Try it online!

Since the input can be anything, I decided to take IntStreams as input. You can get such an input from a standard int[] with Arrays.stream(array).

The output is 1 for "N wins", -1 for "M wins", and 0 for tie.

Saves

• -14 bytes from insights of both @Zircon and @Xanderhall!
• The way you've chosen to take the input is really clever! – David Conrad Jul 7 '17 at 12:29
• @DavidConrad I actually had the long version of this answer since yesterday (just prepend java.util.Arrays.stream(array).map(java.util.Arrays::stream)). It's only when I re-read the question today that I thought this input format is as valid as any. – Olivier Grégoire Jul 7 '17 at 12:35
• Would .orElse(0) be a viable shortening of .getAsDouble()? – Zircon Jul 7 '17 at 14:21
• If you instead just take 2 streams for input, (a,b)->Math.signum(a.average().orElse(0)-b.average().orElse(0)); is 64 bytes – Xanderhall Jul 7 '17 at 14:41
• These are only good ideas, guys! Continue :p – Olivier Grégoire Jul 7 '17 at 14:48

Dyalog APL, 14 bytes

×(-/(+/÷≢)¨∘⊢)

1 if the left is greater, ¯1 if the right is and 0 on tie.

How?

¨∘⊢ for each list

+/÷≢ calculate average (+/ sum ÷ divide by length)

-/ subtract the averages

× sign of the result

Common Lisp, 74 71 bytes

(defun g(x)(/(apply'+ x)(length x)))(defun f(x y)(signum(-(g x)(g y))))

Try it online!