class Person
  def initialize(name)
    @name = name
    @fiance = nil
    @preferences = []
    @proposals = []
  end
  attr_reader :name, :proposals
  attr_accessor :fiance, :preferences

  def to_s
    @name
  end

  def free
    @fiance = nil
  end

  def single?
    @fiance == nil
  end

  def engage(person)
    self.fiance = person
    person.fiance = self
  end

  def better_choice?(person)
    @preferences.index(person) < @preferences.index(@fiance)
  end

  def propose_to(person)
    puts  if $DEBUG
    @proposals << person
    person.respond_to_proposal_from(self)
  end

  def respond_to_proposal_from(person)
    if single?
      puts  if $DEBUG
      engage(person)
    elsif better_choice?(person)
      puts  if $DEBUG
      @fiance.free
      engage(person)
    else
      puts  if $DEBUG
    end
  end
end




prefs = {
  'abe'  => %w[abi eve cath ivy jan dee fay bea hope gay],
  'bob'  => %w[cath hope abi dee eve fay bea jan ivy gay],
  'col'  => %w[hope eve abi dee bea fay ivy gay cath jan],
  'dan'  => %w[ivy fay dee gay hope eve jan bea cath abi],
  'ed'   => %w[jan dee bea cath fay eve abi ivy hope gay],
  'fred' => %w[bea abi dee gay eve ivy cath jan hope fay],
  'gav'  => %w[gay eve ivy bea cath abi dee hope jan fay],
  'hal'  => %w[abi eve hope fay ivy cath jan bea gay dee],
  'ian'  => %w[hope cath dee gay bea abi fay ivy jan eve],
  'jon'  => %w[abi fay jan gay eve bea dee cath ivy hope],
  'abi'  => %w[bob fred jon gav ian abe dan ed col hal],
  'bea'  => %w[bob abe col fred gav dan ian ed jon hal],
  'cath' => %w[fred bob ed gav hal col ian abe dan jon],
  'dee'  => %w[fred jon col abe ian hal gav dan bob ed],
  'eve'  => %w[jon hal fred dan abe gav col ed ian bob],
  'fay'  => %w[bob abe ed ian jon dan fred gav col hal],
  'gay'  => %w[jon gav hal fred bob abe col ed dan ian],
  'hope' => %w[gav jon bob abe ian dan hal ed col fred],
  'ivy'  => %w[ian col hal gav fred bob abe ed jon dan],
  'jan'  => %w[ed hal gav abe bob jon col ian fred dan],
}

@men = Hash[
  %w[abe bob col dan ed fred gav hal ian jon].collect do |name|
    [name, Person.new(name)]
  end
]

@women = Hash[
  %w[abi bea cath dee eve fay gay hope ivy jan].collect do |name|
    [name, Person.new(name)]
  end
]

@men.each {|name, man| man.preferences = @women.values_at(*prefs[name])}
@women.each {|name, woman| woman.preferences = @men.values_at(*prefs[name])}




def match_couples(men, women)
  men.each_value {|man| man.free}
  women.each_value {|woman| woman.free}

  while m = men.values.find {|man| man.single?} do
    puts  if $DEBUG
    w = m.preferences.find {|woman| not m.proposals.include?(woman)}
    m.propose_to(w)
  end
end

match_couples @men, @women

@men.each_value.collect {|man| puts }




class Person
  def more_preferable_people
    ( @preferences.partition {|p| better_choice?(p)} ).first
  end
end

require 'set'

def stability(men)
  unstable = Set.new
  men.each_value do |man|
    woman = man.fiance
    puts  if $DEBUG

    man.more_preferable_people.each do |other_woman|
      if other_woman.more_preferable_people.include?(man)
        puts  if $DEBUG
        unstable << [man, other_woman]
      end
    end
    woman.more_preferable_people.each do |other_man|
      if other_man.more_preferable_people.include?(woman)
        puts  if $DEBUG
        unstable << [other_man, woman]
      end
    end
  end

  if unstable.empty?
    puts 
  else
    puts 
    unstable.each do |a,b|
      puts 
    end
  end
end

stability @men




puts 

def swap(m1, m2)
  w1 = m1.fiance
  w2 = m2.fiance
  m1.fiance = w2
  w1.fiance = m2
  m2.fiance = w1
  w2.fiance = m1
end

swap *@men.values_at('abe','bob')

@men.each_value.collect {|man| puts }
stability @men