Created
February 19, 2015 13:21
-
-
Save zachwhaley/c1aae7f72f2d8f137922 to your computer and use it in GitHub Desktop.
Pair mating bears and avoid common ancestors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import re | |
class Bear: | |
def __init__(self, attrs): | |
self.parents = [] | |
self.name = attrs[0] | |
if len(attrs) > 1: | |
self.sex = attrs[1] | |
self.parents = attrs[2:4] | |
self.age = float(attrs[4]) | |
def read_file(file_): | |
with open(file_) as f: | |
for line in f: | |
yield [b.strip() for b in line.split(':')] | |
def norml(name): | |
return ' '.join(name.split()).upper() | |
def create_bears(file_): | |
pnts = set() | |
bears = {} | |
for line in read_file(file_): | |
# create bear for each line | |
name = norml(line[0]) | |
bears[name] = Bear(line) | |
# create parents if they don't exist | |
pnts = pnts | set(map(norml, line[2:4])) | |
for pnt in [p for p in line[2:4] if norml(p) not in bears]: | |
bears[norml(pnt)] = Bear([pnt]) | |
# set bear parents | |
set_parents(bears) | |
return [b for n, b in bears.iteritems() if n not in pnts] | |
def set_parents(bears): | |
for bear in bears.itervalues(): | |
bear.parents = [bears[norml(pnt)] for pnt in bear.parents if pnt] | |
def mate_bears(bears): | |
boys, girls = find_mates(bears) | |
return [(b, g) for b in boys for g in girls if can_mate(b, g)] | |
def find_mates(bears): | |
boys = [] | |
girls = [] | |
for b in bears: | |
if b.age > 2.0 and b.age < 6.0: | |
if b.sex == 'M': | |
boys.append(b) | |
else: | |
girls.append(b) | |
return boys, girls | |
def can_mate(boy, girl): | |
return not are_related(boy, girl) and abs(boy.age - girl.age) <= 1.0 | |
def are_related(boy, girl): | |
bped = pedigree(boy, []) | |
gped = pedigree(girl, []) | |
return len(bped & gped) > 0 | |
def pedigree(bear, ped=[], gen=0): | |
pnts = bear.parents | |
if gen < 2: | |
ped += pnts | |
for p in pnts: | |
pedigree(p, ped, gen+1) | |
return set(ped) | |
def main(file_): | |
chldn = create_bears(file_) | |
mates = mate_bears(chldn) | |
for boy, girl in mates: | |
print ' + '.join([boy.name, girl.name]) | |
if __name__=='__main__': | |
main(sys.argv[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment