Alex Martelli alludes to an algebraic solution which I'll include here for completeness. It can be worked out with the use of simultaneous equations. Being a simple mathematical solution, it's possibly faster, at least for large numbers of legs and heads :-)
Let:
H
be the number of heads;
L
be the number of legs;
C
be the number of chicks; and
P
be the number of pigs.
Given C
and P
, we can calculate the other two variables with:
H = C + P (1)
L = 2C + 4P (2)
I'll detail every step in the calculations below. The mathematically inclined can no doubt point out that steps could be combined but I'd prefer to be explicit. From (1), we can calculate:
H = C + P
=> 0 = C + P - H [subtract H from both sides]
=> 0 = H - C - P [multiply both sides by -1]
=> P = H - C [add P to both sides] (3)
and substitute that into (2):
L = 2C + 4P
=> L = 2C + 4(H - C) [substitute H-C for P]
=> L = 2C + 4H - 4C [expand 4(H-C) to 4H-4C]
=> L = 4H - 2C [combine 2C-4C into -2C]
=> 0 = 4H - 2C - L [subtract L from both sides]
=> 2C = 4H - L [add 2C to both sides]
=> C = 2H - L/2 [divide both sides by 2] (4)
Now you have two formulae, one that can calculate the number of chicks from head and legs (4)
, the other which can calculate number of pigs from chicks and heads (3)
.
So here's the Python code to do it, with appropriate checks to ensure you don't allow some of the more bizarre mathematical solutions, like 2 heads and 7 legs giving us a pig and a half along with half a chick, or 1 head and 12 legs giving 5 pigs and -4 chicks :-)
def solve (numLegs, numHeads):
# Use the formulae (these make integers).
chicks = numHeads * 2 - int (numLegs / 2)
pigs = numHeads - chicks
# Don't allow negative number of animals.
if chicks < 0 or pigs < 0:
return [None, None]
# Don't allow fractional animals.
if chicks * 2 + pigs * 4 != numLegs:
return [None, None]
if chicks + pigs != numHeads:
return [None, None]
return [pigs, chicks]
Of course, if you pass in fractional numbers of head or legs, all bets are off. Here's a complete test program so you can try out various values to ensure both methods return the same values:
import sys
def usage (reason):
print "Error: %s"%(reason)
print "Usage: solve <numHeads> <numLegs>"
sys.exit (1);
def solve1 (numLegs, numHeads):
for numChicks in range (0, numHeads + 1):
numPigs = numHeads - numChicks
totLegs = 4 * numPigs + 2 * numChicks
if totLegs == numLegs:
return [numPigs, numChicks]
return [None, None]
def solve2 (numLegs, numHeads):
chicks = numHeads * 2 - int (numLegs / 2)
pigs = numHeads - chicks
if chicks < 0 or pigs < 0: return [None, None]
if chicks * 2 + pigs * 4 != numLegs: return [None, None]
if chicks + pigs != numHeads: return [None, None]
return [pigs, chicks]
if len (sys.argv) != 3:
usage ("Wrong number of parameters (%d)"%(len (sys.argv)))
try: heads = int (sys.argv[1])
except: usage ("Invalid <numHeads> of '%s'"%(sys.argv[1]))
try: legs = int (sys.argv[2])
except: usage ("Invalid <numLegs> of '%s'"%(sys.argv[2]))
print "[pigs, chicks]:"
print " ", solve1 (legs, heads)
print " ", solve2 (legs, heads)