12
\$\begingroup\$

Average out two lists

Challenge

Given two lists of positive integers, determine whether it is possible to rearrange the elements into two new lists such that the new lists have the same arithmetic mean (average).

Input

The input can be taken through STDIN or as function arguments. Input can be taken as a list, or if your language doesn't support lists (or anything similar such as arrays/dictionaries) then the input can be taken as a comma- or space-delimited string. That is,

"1 4 8 2 5,3 1 5 2 5"

is the same as:

[ [1,4,8,2,5], [3,1,5,2,5] ]

All input lists will be the same length.

Output

If you can create two new lists with the same average, your program/function should print or return the mean. If you can't, your program should output a sad face :(.

Note that the rearranged lists with equal means, if they exist, need not has the same length. Any number of swaps can be made to create the new lists.

Examples

1 4 8 2 5,3 1 5 2 5 -> 1 4 8 2 3,5 1 5 2 5 (swapped 3 and 5) -> 3.6
1 3 6 2,16 19 19 14 -> [[1,6,19,14],[3,2,16,19]] -> 10
2 6 2,6 3 5 -> 2 6,2 6 3 5 (moved 2) -> 4
90 80 20 1,40 60 28 18 -> :(

This is so shortest code in bytes wins. As always, standard loopholes are disallowed.

\$\endgroup\$
12
  • 2
    \$\begingroup\$ Can we swap any number of elements from each list? Can one list just give elements to the other? I don't understand what you mean by "valid permutation exists". Also, this needs more test cases. \$\endgroup\$
    – xnor
    Jul 29, 2015 at 19:26
  • \$\begingroup\$ @xnor you can just move one element, to another. I'll add a few more test cases \$\endgroup\$
    – Downgoat
    Jul 29, 2015 at 19:27
  • \$\begingroup\$ So, is this equivalent to, "Given a single list (their union), can in be partitioned into two nonempty lists with the same average ?" \$\endgroup\$
    – xnor
    Jul 29, 2015 at 19:28
  • 1
    \$\begingroup\$ @vihan1086 Why not take a single list as input then? Your presentation seems needlessly complicated. \$\endgroup\$
    – xnor
    Jul 29, 2015 at 19:30
  • 2
    \$\begingroup\$ @vihan1086 Looking at your Sandbox post, many of these same requests for clarification were made there, and you said you clarified many of these points, but your edits didn't really make them clearer. You would have been better off replacing the confusing text rather than adding further text. \$\endgroup\$
    – xnor
    Jul 29, 2015 at 19:34

5 Answers 5

13
\$\begingroup\$

Pyth, 24 bytes

?}KcsJsQlJmcsdldtPyJK":(

Try it online: Demonstration

Thanks to Dennis for noticing an error and golfing one byte.

Explanation:

?}KcsJsQlJmcsdldtPyJK":(   implicit: Q = evaluated input
      sQ                   all numbers of Q
     J                     save them in J
  KcsJ  lJ                 average of J (sum(J) / len(J))
                           store in K
          m     tPyJ       map each nonempty subset d of J to:
           csdld             average of d
?}                         if K in ^:
                    K        print K
                     ":(   else print sad-face
\$\endgroup\$
2
  • 5
    \$\begingroup\$ Nice work, +1. But does Pyth really not have a built-in for computing the mean? \$\endgroup\$
    – Alex A.
    Jul 29, 2015 at 20:36
  • \$\begingroup\$ @AlexA. It now does have one (namely .O) \$\endgroup\$
    – Mr. Xcoder
    Oct 15, 2017 at 19:53
6
\$\begingroup\$

SWI-Prolog, 159 bytes

a(A,B):-append([A,B],R),permutation(R,S),append([Y,Z],S),sum_list(Y,I),sum_list(Z,J),length(Y,L),length(Z,M),L\=0,M\=0,I/L=:=J/M,W is J/M,write(W);write(':(').

Called as a([1,4,8,2,5],[3,1,5,2,5]).

\$\endgroup\$
5
\$\begingroup\$

Julia, 101 bytes

f(a,b)=(m=mean;p=filter(i->m(i[1])==m(i[2]),partitions([a,b],2));isempty(p)?":(":m(collect(p)[1][1]))

This creates a function that accepts two arrays and returns a string or a float accordingly.

Ungolfed + explanation:

function f(a,b)
    # Get the set of all 2-way partitions of the array [a,b]
    l = partitions([a,b], 2)

    # Filter the set of partitions to those where the two
    # contained arrays have equal means
    p = filter(i -> mean(i[1]) == mean(i[2]), l)

    # Return a frown if p is empty, otherwise return a mean
    isempty(p) ? ":(" : mean(collect(p)[1][1])
end
\$\endgroup\$
2
\$\begingroup\$

R, 94 Bytes

Basically the same as Jakubes I think. If the mean of both lists matches the mean of any combination of the values in lists up to but not including the combined length of the list, output the mean otherwise the sad face.

if(mean(l<-scan())%in%unlist(sapply(2:length(l)-1,function(x)combn(l,x,mean))))mean(l)else':('

Test run

> if(mean(l<-scan())%in%unlist(sapply(2:length(l)-1,function(x)combn(l,x,mean))))mean(l)else':('
1: 1 4 8 2 5
6: 3 1 5 2 5
11: 
Read 10 items
[1] 3.6
> if(mean(l<-scan())%in%unlist(sapply(2:length(l)-1,function(x)combn(l,x,mean))))mean(l)else':('
1: 90 80 20 1
5: 40 60 28 18
9: 
Read 8 items
[1] ":("
\$\endgroup\$
0
\$\begingroup\$

Jelly, 23 bytes

FŒ!ŒṖL=2ƊƇÆmEƇƲ€ṀṀṀȯ⁾:(

Try it online!

Wildly inefficient, times out when the lengths of the input lists are \$\ge4\$

How it works

FŒ!ŒṖL=2ƊƇÆmEƇƲ€ṀṀṀȯ⁾:( - Main link. Takes a list of lists, l = [a,b]
F                       - Flatten
 Œ!                     - Yield all permutations
              Ʋ€        - Over each permutation, p:
   ŒṖ                   -   Yield all partitions of p
     L=2ƊƇ              -   Only keep those of length 2
          Æm            -   Take the mean of each
            EƇ          -   Only keep those where the means are equal
                ṀṀṀ     - Take the maximum three times. This yields 0 for impossible inputs and the mean for possible ones
                    ⁾:( - Yield the string ":("
                   ȯ    - Replace 0 with this string, or do nothing if not 0
\$\endgroup\$
2
  • \$\begingroup\$ Fails for 2 6 2,6 3 5 -> 2 6,2 6 3 5 (moved 2) -> 4. You're only splitting it into two parts of equal length now. \$\endgroup\$ Aug 10, 2018 at 11:13
  • \$\begingroup\$ @KevinCruijssen very late, but fixed \$\endgroup\$ Oct 5, 2020 at 21:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.