11
\$\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\$
  • 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 '15 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 '15 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 '15 at 19:28
  • 1
    \$\begingroup\$ @vihan1086 Why not take a single list as input then? Your presentation seems needlessly complicated. \$\endgroup\$ – xnor Jul 29 '15 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 '15 at 19:34
12
\$\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\$
  • 5
    \$\begingroup\$ Nice work, +1. But does Pyth really not have a built-in for computing the mean? \$\endgroup\$ – Alex A. Jul 29 '15 at 20:36
  • \$\begingroup\$ @AlexA. It now does have one (namely .O) \$\endgroup\$ – Mr. Xcoder Oct 15 '17 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, 22 bytes

FŒ!œs2ÆmE$$Ðf⁾:(ÆmX$Ṇ?

Try it online!

Done with help from Mr. Xcoder in chat

Explanation

FŒ!œs2ÆmE$$Ðf⁾:(ÆmX$Ṇ? - Main link, argument a (2D-array)

F                      - Flatten
 Œ!                    - All permutations
           Ðf          - Keep elements which are truthy when
   œs2    $            -   split into 2 parts and...
      Æm $             -   the means of each...
        E              -   are the same
                     ? - Ternary if
                    Ṇ  -   Condition: No lists remain
             ⁾:(       -   If so: Set the return value to ":("
                   $   -   Otherwise: 
                Æm     -     Get the mean of each list
                  X    -     Randomly choose one (all elements are the same)
\$\endgroup\$
  • \$\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\$ – Kevin Cruijssen Aug 10 '18 at 11:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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