3
\$\begingroup\$

I have simulated balancing a scale by having each side total the same weight.

The scale has two weights (left and right side) and some spare weights:

weights = [3, 4]
spare_weights = [1, 2, 7, 7]

A maximum of two weights can be used from the spare weights to balance the scale. The spare(s) may be on a single side or split between both.

The output should be the minimum number of weight needed to balance the scale.

import itertools

weights = [3, 4]
spare_weights = [1, 2, 7, 7]
c = enumerate([subset for l in range(0, 3) for subset in itertools.combinations(spare_weights, l)])

cc = cc = list(itertools.combinations(c, 2))

left, right = weights
qualifying_combos = []
for c in cc:
    l, r = c
    if sum(l[1]) + left == sum(r[1]) + right:
        qualifying_combos.append(list(l[1]) + list(r[1]))
    elif sum(l[1]) + right == sum(r[1]) + left:
        qualifying_combos.append(list(l[1]) + list(r[1]))
print(min(qualifying_combos, key=len))

output:

[1]

Is there a more elegant way to code this?

\$\endgroup\$
  • \$\begingroup\$ @close-voter&down-voter what code is missing from the question? The code runs as stated. This seems like a pretty ridiculous judgment, did you, the close voter, even try to run the code? \$\endgroup\$ – Peilonrayz Dec 16 '19 at 13:10
  • \$\begingroup\$ A made a few edits since they downvoted. \$\endgroup\$ – Dave Dec 16 '19 at 13:13
  • \$\begingroup\$ As the 3rd viewer, I'm guessing I saw the original. That didn't deserve a CV. Thank you for the edit, no-one should have any qualms with whether it's LCC now. \$\endgroup\$ – Peilonrayz Dec 16 '19 at 13:17
  • 1
    \$\begingroup\$ @Peilonrayz I don't know, but it may have something to do with the old first sentence which could, if you squint your eyes just right, may be misconstrued as a request for alternative implementations instead of reviews. \$\endgroup\$ – Mast Dec 16 '19 at 13:58
  • 1
    \$\begingroup\$ Can both spares be put on one side? \$\endgroup\$ – JollyJoker Dec 16 '19 at 14:18
7
\$\begingroup\$
  1. Write functions. Make this a balance_scale function, that returns the minimum.
  2. Your variable names are pretty poor, single letter variable names leave people guessing at what they mean.
  3. You should change cc = cc = ... to just one assignment.

Since you can use a maximum of two spare weights the solution can be a lot simpler than you've produced.

  1. \$W_1\$ is the smaller weight in weights and \$W_2\$ is the larger.
  2. If \$W_1 = W_2\$ then you return an empty list.
  3. We can determine what weight is needed when only one weight can be used.

    \$S = W_2 - W_1\$

    Therefore if \$S\$ is in spare_weights then we can return \$S\$.

  4. For each \$S_1\$ in spare_weights we can determine the weight needed, \$S_2\$.

    \$S_2 = |W_2 - W_1 - S_1|\$

    We take the absolute as this weight can be on either side of the scale. If the non-absolute value of \$S_2\$ is positive then we add it to \$W_1 + S_1\$ if it's negative then we add it to \$W_2\$.

If we add \$0\$ twice to spare_weights, then we can see that (4), (3) and (2) are all roughly the same equation.

We don't need to check if \$S_1\$ and \$S_2\$ both exist in spare_weights, as the only time they are the same is if \$W_1 = W_2\$, and so they would both be 0. We however have to assign \$S_1\$ to 0 first.

def balance_scale(scale, spares):
    w1, w2 = sorted(scale)
    spare_set = set(spares) | {0}
    for s1 in [0] + spares:
        s2 = abs(w2 - w1 - s1)
        if s2 in spare_set:
            return [i for i in [s1, s2] if i]
    return None


print(balance_scale([4, 3], [1, 2, 7, 7]))
[1]
| improve this answer | |
\$\endgroup\$

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.