[Question]
  [
You are given a bunch of weights, and your task is to build a small balanced mobile using those weights.
The input is a list of integer weights in the range 1 through 9, inclusive. There may be duplicates.
The output is an ascii picture of a mobile that, when hung, would balance. Perhaps best shown by example:
**input**
```
3 8 9 7 5
```
**possible output**
```
         |
   +-----+---------+
   |               |
+--+-+        +----+------+
|    |        |           |
8   ++--+     7           5
    |   |
    9   3
```
You must use the ascii characters as shown. The horizontal and vertical segments may be of any length. No part of the mobile may touch (horizontally or vertically) another unconnected part of the mobile. All weights must be hung from a vertical segment of length at least 1, and there must be a vertical segment from which the whole mobile is hung.
The size of a mobile is the total number of `+`,`-`,and `|` characters required to build it. Lower sizes are better.
You may put as many connections on a segment as you would like. For example:
**input**
```
2 3 3 5 3 9
```
**possible output**
```
           |
   +---+---+-----------+
   |   |               |
+--+-+ 5               9
|  | |
2  | 3
   |
  +++
  | |
  3 3
```
The winning program is the one that can generate the lowest average of mobile sizes for a test set of inputs. The real test is super-secret to prevent hard-coding, but it will be something like this:
```
8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 7 7
3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7
```
  
[Answer]
Python 2.
I'm cheating a ~~little~~ bit:
* I only construct mobiles with one horizontal. ~~I have a feeling (but I haven't proven it) that the optimal mobile under the given conditions actually always *does* only have one horizontal.~~ **Edit:** Not always true; with `2 2 9 1` Nabb has found a counter-example in the comments below:
```
Size 18:                Size 16:
   |                        |
+-++--+-----+            +--++-+
| |   |     |            |   | |
2 9   2     1           -+-  9 1
                        | |
                        2 2
```
* I just do stupid brute-forcing:
	1. The given weights are shuffled randomly.
	2. Two weights at a time are placed on the mobile in the best positions such that it stays balanced.
	3. If the resulting mobile is better than any that we had before, remember it.
	4. Rinse and repeat, until a pre-defined number of seconds is up.
My results for your sample inputs; each was run for 5 seconds (I'm aware that this is ridiculous for the small ones – just going through all possible permutations would be faster). Note that since there's a random element, subsequent runs may find better or worse results.
```
3 8 9 7 5
Tested 107887 mobiles, smallest size 20:
        |
+-+-----+-+--+
| |     | |  |
5 3     7 9  8
2 3 3 5 3 9
Tested 57915 mobiles, smallest size 23:
      |
+--+-++--+-+---+
|  | |   | |   |
3  5 9   3 3   2
8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7
Tested 11992 mobiles, smallest size 50:
                |
+-+-+-+--+-+-+-+++-+-+--+-+-+-+-+
| | | |  | | | | | | |  | | | | |
8 8 8 8  8 8 8 8 8 8 8  7 8 8 8 8
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 7 7
Tested 11119 mobiles, smallest size 62:
                    |
+-+-+-+-+-+--+-+-+-+++-+-+-+--+-+-+-+-+-+
| | | | | |  | | | | | | | |  | | | | | |
2 7 5 6 6 8  3 2 3 7 9 7 8 1  1 7 9 5 4 4
3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7
Tested 16301 mobiles, smallest size 51:
                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |
4 6 5 7 7 4 6 5 3 5 6 4 7 6 7 5 4
```
The code (verbose, as this isn't code golf):
```
import time, random
def gcd(a, b):
    while b > 0:
        a, b = b, a % b
    return a
class Mobile(object):
    def __init__(self):
        self.contents = [None];
        self.pivot = 0;
    def addWeights(self, w1, w2):
        g = gcd(w1, w2)
        m1 = w2 / g
        m2 = w1 / g
        mul = 0
        p1 = -1
        while True:
            if p1 < 0:
                mul += 1
                p1 = mul * m1
                p2 = -mul * m2
            else:
                p1 *= -1
                p2 *= -1
            if self.free(p1) and self.free(p2):
                self.add(w1, p1)
                self.add(w2, p2)
                return
    def add(self, w, pos):
        listindex = self.pivot - pos 
        if listindex < 0:
            self.contents = [w] + (abs(listindex) - 1) * [None] + self.contents
            self.pivot += abs(listindex)
        elif listindex >= len(self.contents):
            self.contents += (listindex - len(self.contents)) * [None] + [w]
        else:
            self.contents[listindex] = w
    def at(self, pos):
        listindex = self.pivot - pos
        if 0 <= listindex < len(self.contents):
            return self.contents[listindex]
        return None
    def free(self, pos):
        return all(self.at(pos + d) is None for d in (-1, 0, 1))
    def score(self):
        return 1 + 2 * len(self.contents) - self.contents.count(None)
    def draw(self):
        print self.pivot * " " + "|"
        print "".join("+" if c is not None or i == self.pivot else "-" for i, c in enumerate(self.contents))
        print "".join("|" if c is not None else " " for c in self.contents)
        print "".join(str(c) if c is not None else " " for c in self.contents)
    def assertBalance(self):
        assert sum((i - self.pivot) * (c or 0) for i, c in enumerate(self.contents)) == 0
weights = map(int, raw_input().split())
best = None
count = 0
# change the 5 to the number of seconds that are acceptable
until = time.time() + 5
while time.time() < until:
    count += 1
    m = Mobile()
    # create a random permutation of the weights
    perm = list(weights)
    random.shuffle(perm)
    if len(perm) % 2:
        # uneven number of weights -- place one in the middle
        m.add(perm.pop(), 0)
    while perm:
        m.addWeights(perm.pop(), perm.pop())
    m.assertBalance() # just to prove the algorithm is correct :)
    s = m.score()
    if best is None or s < bestScore:
        best = m
        bestScore = s
print "Tested %d mobiles, smallest size %d:" % (count, best.score())
best.draw()
```
[Answer]
Well this is an old question, but I just saw it appear in the top questions tab so here's my (optimal) solution:
```
#include <stdio.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
int main(int argc, const char *const *argv) {
    if(argc < 2) {
        fprintf(stderr,
            "Balances weights on a hanging mobile\n\n"
            "Usage: %s <weight1> [<weight2> [...]]\n",
            argv[0]
        );
        return 1;
    }
    int total = argc - 1;
    int values[total];
    int maxval = 0;
    for(int n = 0; n < total; ++ n) {
        char *check = NULL;
        long v = strtol(argv[n+1], &check, 10);
        if(v <= 0 || v > INT_MAX || *check != '\0') {
            fprintf(stderr,
                "Weight #%d (%s) is not an integer within (0 %d]\n",
                n + 1, argv[n+1], INT_MAX
            );
            return 1;
        }
        values[n] = (int) v;
        if(values[n] > maxval) {
            maxval = values[n];
        }
    }
    int maxwidth = (int) log10(maxval) + 1;
    for(int n = 0; n < total; ++ n) {
        int width = (int) log10(values[n]) + 1;
        fprintf(stdout,
            "%*s\n%*d\n",
            (maxwidth + 1) / 2, "|",
            (maxwidth + width) / 2, values[n]
        );
    }
    return 0;
}
```
From looking at the rules I'm pretty sure it isn't cheating, although it feels like it is. This will just output all the given numbers in a vertical chain, for a total cost of 2\*number\_of\_inputs (which is the minimum possible because each number must have a bar above it no matter what the layout). Here's an example:
```
./mobile 3 8 9 7 5
```
Produces:
```
|
3
|
8
|
9
|
7
|
5
```
Which is of course in perfect balance.
---
I was originally going to try something more in the spirit of this challenge, but it quickly turned out that it just optimised away to this structure anyway
[Answer]
Here is a solution that brute forces the smallest single row solution.
The code iterates over all permutations and compute the center of mass for each. If the center of mass has integer coordinates, we've found a solution.
After all permutations have been tried, we add a segment to the mix (equivalent to a weight of mass 0) in our current set of weights and retry.
To run the program, do `python balance.py 1 2 2 4`.
```
#!/usr/bin/env python3
import itertools, sys
# taken from http://stackoverflow.com/a/30558049/436792
def unique_permutations(elements):
    if len(elements) == 1:
        yield (elements[0],)
    else:
        unique_elements = set(elements)
        for first_element in unique_elements:
            remaining_elements = list(elements)
            remaining_elements.remove(first_element)
            for sub_permutation in unique_permutations(remaining_elements):
                yield (first_element,) + sub_permutation
def print_solution(cm, values):
    print(('  ' * cm) + '|')
    print('-'.join(['-' if v == 0 else '+'  for v in values]))
    print(' '.join([' ' if v == 0 else '|'  for v in values]))
    print(' '.join([' ' if v == 0 else str(v) for v in values]))
input = list(map(int, sys.argv[1:]))
mass = sum(input)
while True:
    n = len(input)
    permutations = filter(lambda p: p[0] != 0 and p[n-1] != 0, unique_permutations(input))
    for p in permutations:
        cm = 0
        for i in range(n):
            cm += p[i] * i;
        if (cm % mass == 0):
            print_solution(cm//mass, p)
            sys.exit(0)
    input.append(0)
```
which produces these best solutions :
```
    |
+-+-+-+-+
| | | | |
8 3 9 5 7
    |
+-+-+-+-+-+
| | | | | |
9 2 3 5 3 3
                |
+-+-+-+-+-+-+---+-+-+-+-+-+-+-+-+
| | | | | | |   | | | | | | | | |
8 8 8 8 8 8 8   8 8 8 8 8 8 8 8 7
                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | | | | |
1 1 2 2 3 3 4 4 8 8 5 5 6 6 7 7 7 7 9 9
                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |
3 4 4 4 4 5 5 5 5 6 7 6 7 7 7 6 6
```
[Answer]
# Python 3
This does no worse than 1 more than optimal on any of the test cases, I believe, and does so in 5 seconds.
Basically, I use a single bar approach. I randomly order the input, then insert the weights onto the bar one at a time. Each element is either put in the position that minimizes the excess weight on either side, or the second best position from that perspective, using the former 75% of the time and the latter 25% of the time. Then, I check whether the mobile is balanced at the end, and is better than the best mobile found so far. I store the best one, then halt and print it out after 5 seconds of searching.
Results, in 5 second runs:
```
py mobile.py <<< '3 8 7 5 9'
Best mobile found, score 15:
    |    
+-+-+-+-+
| | | | |
8 7 3 5 9
py mobile.py <<< '2 2 1 9'
Best mobile found, score 13:
   |    
+-++-+-+
| |  | |
1 9  2 2
py mobile.py <<< '2 3 3 5 3 9'
Best mobile found, score 18:
      |    
+-+-+-+-+-+
| | | | | |
2 3 3 5 9 3
py mobile.py <<< '8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7'
Best mobile found, score 49:
                |               
+-+--+-+-+-+-+-+++-+-+-+-+-+-+-+
| |  | | | | | | | | | | | | | |
7 8  8 8 8 8 8 8 8 8 8 8 8 8 8 8
\py mobile.py <<< '1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 7 7'
Best mobile found, score 61:
                    |                   
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
| | | | | | | | | | | | | | | | | | |  |
1 7 7 5 4 3 1 9 6 7 8 2 2 9 3 7 6 5 8  4
py mobile.py <<< '3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7'
Best mobile found, score 51:
                |                
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |
4 4 6 7 7 4 5 7 6 6 5 4 6 3 5 5 7
```
Code:
```
import random
import time
class Mobile:
    def __init__(self):
        self.contents = {}
        self.lean = 0
    def usable(self, loc):
        return not any(loc + k in self.contents for k in (-1,0,1))
    def choose_point(self, w):
        def goodness(loc):
            return abs(self.lean + w * loc)
        gl = sorted(list(filter(self.usable,range(min(self.contents.keys() or [0]) - 5,max(self.contents.keys() or [0]) + 6))), key=goodness)
        return random.choice((gl[0], gl[0], gl[0], gl[1]))
    def add(self, w, loc):
        self.contents[loc] = w
        self.lean += w*loc
    def __repr__(self):
        width = range(min(self.contents.keys()), max(self.contents.keys()) + 1)
        return '\n'.join((''.join(' ' if loc else '|' for loc in width),
                          ''.join('+' if loc in self.contents or loc == 0 else '-' for loc in width),
                          ''.join('|' if loc in self.contents else ' ' for loc in width),
                          ''.join(str(self.contents.get(loc, ' ')) for loc in width)))
    def score(self):
        return max(self.contents.keys()) - min(self.contents.keys()) + len(self.contents) + 2
    def my_score(self):
        return max(self.contents.keys()) - min(self.contents.keys()) + 1
best = 1000000
best_mob = None
in_weights = list(map(int,input().split()))
time.clock()
while time.clock() < 5:
    mob = Mobile()
    for insert in random.sample(in_weights, len(in_weights)):
        mob.add(insert, mob.choose_point(insert))
    if not mob.lean:
        if mob.score() < best:
            best = mob.score()
            best_mob = mob
print("Best mobile found, score %d:" % best_mob.score())
print(best_mob)
```
The only one of these solutions which I believe is suboptimal is the longest one, which has this solution, which I found after a 10 minute run:
```
Best mobile found, score 60:
                   |                   
+-+-+-+-+-+-+-+-+-+++-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | | | | |
3 2 9 4 7 8 1 6 9 8 7 1 6 2 4 5 7 3 5 7
```
]