129 lines
4.4 KiB
CoffeeScript
129 lines
4.4 KiB
CoffeeScript
class Person
|
|
constructor: (@name, @preferences) ->
|
|
@mate = null
|
|
@best_mate_rank = 0
|
|
@rank = {}
|
|
for preference, i in @preferences
|
|
@rank[preference] = i
|
|
|
|
preferred_mate_name: =>
|
|
@preferences[@best_mate_rank]
|
|
|
|
reject: =>
|
|
@best_mate_rank += 1
|
|
|
|
set_mate: (mate) =>
|
|
@mate = mate
|
|
|
|
offer_mate: (free_mate, reject_mate_cb) =>
|
|
if @mate
|
|
if @covets(free_mate)
|
|
console.log "#{free_mate.name} steals #{@name} from #{@mate.name}"
|
|
reject_mate_cb @mate
|
|
free_mate.set_mate @
|
|
@set_mate free_mate
|
|
else
|
|
console.log "#{free_mate.name} cannot steal #{@name} from #{@mate.name}"
|
|
reject_mate_cb free_mate
|
|
else
|
|
console.log "#{free_mate.name} gets #{@name} first"
|
|
free_mate.set_mate @
|
|
@set_mate free_mate
|
|
|
|
happiness: =>
|
|
@rank[@mate.name]
|
|
|
|
covets: (other_mate) =>
|
|
@rank[other_mate.name] <= @rank[@mate.name]
|
|
|
|
persons_by_name = (persons) ->
|
|
hsh = {}
|
|
for person in persons
|
|
hsh[person.name] = person
|
|
hsh
|
|
|
|
mate_off = (guys, gals) ->
|
|
free_pursuers = (guy for guy in guys)
|
|
guys_by_name = persons_by_name guys
|
|
gals_by_name = persons_by_name gals
|
|
|
|
while free_pursuers.length > 0
|
|
free_pursuer = free_pursuers.shift()
|
|
gal_name = free_pursuer.preferred_mate_name()
|
|
gal = gals_by_name[gal_name]
|
|
reject_mate_cb = (guy) ->
|
|
guy.reject()
|
|
free_pursuers.push guy
|
|
gal.offer_mate free_pursuer, reject_mate_cb
|
|
|
|
|
|
report_on_mates = (guys) ->
|
|
console.log "\n----Marriage Report"
|
|
for guy, i in guys
|
|
throw Error("illegal marriage") if guy.mate.mate isnt guy
|
|
console.log guy.name, guy.mate.name, \
|
|
"(his choice #{guy.happiness()}, her choice #{guy.mate.happiness()} )"
|
|
|
|
report_potential_adulteries = (guys) ->
|
|
for guy1, i in guys
|
|
gal1 = guy1.mate
|
|
for j in [0...i]
|
|
guy2 = guys[j]
|
|
gal2 = guy2.mate
|
|
if guy1.covets(gal2) and gal2.covets(guy1)
|
|
console.log "#{guy1.name} and #{gal2.name} would stray"
|
|
if guy2.covets(gal1) and gal1.covets(guy2)
|
|
console.log "#{guy2.name} and #{gal1.name} would stray"
|
|
|
|
perturb = (guys) ->
|
|
# mess up marriages by swapping two couples...this is mainly to drive
|
|
# out that report_potential_adulteries will actually work
|
|
guy0 = guys[0]
|
|
guy1 = guys[1]
|
|
gal0 = guy0.mate
|
|
gal1 = guy1.mate
|
|
console.log "\nPerturbing with #{guy0.name}, #{gal0.name}, #{guy1.name}, #{gal1.name}"
|
|
guy0.set_mate gal1
|
|
guy1.set_mate gal0
|
|
gal1.set_mate guy0
|
|
gal0.set_mate guy1
|
|
|
|
|
|
Population = ->
|
|
guy_preferences =
|
|
abe: ['abi', 'eve', 'cath', 'ivy', 'jan', 'dee', 'fay', 'bea', 'hope', 'gay']
|
|
bob: ['cath', 'hope', 'abi', 'dee', 'eve', 'fay', 'bea', 'jan', 'ivy', 'gay']
|
|
col: ['hope', 'eve', 'abi', 'dee', 'bea', 'fay', 'ivy', 'gay', 'cath', 'jan']
|
|
dan: ['ivy', 'fay', 'dee', 'gay', 'hope', 'eve', 'jan', 'bea', 'cath', 'abi']
|
|
ed: ['jan', 'dee', 'bea', 'cath', 'fay', 'eve', 'abi', 'ivy', 'hope', 'gay']
|
|
fred: ['bea', 'abi', 'dee', 'gay', 'eve', 'ivy', 'cath', 'jan', 'hope', 'fay']
|
|
gav: ['gay', 'eve', 'ivy', 'bea', 'cath', 'abi', 'dee', 'hope', 'jan', 'fay']
|
|
hal: ['abi', 'eve', 'hope', 'fay', 'ivy', 'cath', 'jan', 'bea', 'gay', 'dee']
|
|
ian: ['hope', 'cath', 'dee', 'gay', 'bea', 'abi', 'fay', 'ivy', 'jan', 'eve']
|
|
jon: ['abi', 'fay', 'jan', 'gay', 'eve', 'bea', 'dee', 'cath', 'ivy', 'hope']
|
|
|
|
gal_preferences =
|
|
abi: ['bob', 'fred', 'jon', 'gav', 'ian', 'abe', 'dan', 'ed', 'col', 'hal']
|
|
bea: ['bob', 'abe', 'col', 'fred', 'gav', 'dan', 'ian', 'ed', 'jon', 'hal']
|
|
cath: ['fred', 'bob', 'ed', 'gav', 'hal', 'col', 'ian', 'abe', 'dan', 'jon']
|
|
dee: ['fred', 'jon', 'col', 'abe', 'ian', 'hal', 'gav', 'dan', 'bob', 'ed']
|
|
eve: ['jon', 'hal', 'fred', 'dan', 'abe', 'gav', 'col', 'ed', 'ian', 'bob']
|
|
fay: ['bob', 'abe', 'ed', 'ian', 'jon', 'dan', 'fred', 'gav', 'col', 'hal']
|
|
gay: ['jon', 'gav', 'hal', 'fred', 'bob', 'abe', 'col', 'ed', 'dan', 'ian']
|
|
hope: ['gav', 'jon', 'bob', 'abe', 'ian', 'dan', 'hal', 'ed', 'col', 'fred']
|
|
ivy: ['ian', 'col', 'hal', 'gav', 'fred', 'bob', 'abe', 'ed', 'jon', 'dan']
|
|
jan: ['ed', 'hal', 'gav', 'abe', 'bob', 'jon', 'col', 'ian', 'fred', 'dan']
|
|
|
|
guys = (new Person(name, preferences) for name, preferences of guy_preferences)
|
|
gals = (new Person(name, preferences) for name, preferences of gal_preferences)
|
|
[guys, gals]
|
|
|
|
do ->
|
|
[guys, gals] = Population()
|
|
mate_off guys, gals
|
|
report_on_mates guys
|
|
report_potential_adulteries guys
|
|
perturb guys
|
|
report_on_mates guys
|
|
report_potential_adulteries guys
|