main
  1require 'set'
  2
  3class SocialGraph
  4  attr_reader :reader, :writer
  5
  6  def initialize(reader, writer)
  7    @reader, @writer = reader, writer
  8    @members = Hash.new { |hash, key| hash[key] = Member.new(key) }
  9  end
 10
 11  def run(traversal = Traversal.new(writer))
 12    (reader.readline.to_i - 1).times do
 13      add_to_graph(reader.readline.strip)
 14    end
 15
 16    member_for(reader.readline).tap do |root|
 17      traversal.traverse(root)
 18    end
 19  end
 20
 21  private
 22
 23  def add_to_graph(line)
 24    key, friend_keys = line.split(':')
 25    friend_keys.split(',').each do |friend|
 26      member_for(key).add_friend(member_for(friend))
 27    end unless friend_keys.nil?
 28  end
 29
 30  def member_for(key)
 31    @members[key.strip]
 32  end
 33end
 34
 35class Member
 36  include Enumerable
 37
 38  attr_reader :name
 39
 40  def initialize(name)
 41    @name = name
 42    @friends = []
 43  end
 44
 45  def add_friend(friend)
 46    @friends << friend
 47  end
 48
 49  def each
 50    @friends.each do |friend|
 51      yield friend
 52    end
 53  end
 54
 55  def to_s
 56    name
 57  end
 58
 59  def inspect
 60    name
 61  end
 62
 63  def ==(other)
 64    name == other.name
 65  end
 66end
 67
 68class Traversal
 69  attr_reader :writer
 70
 71  def initialize(writer)
 72    @writer = writer
 73    @visited = { }
 74    @queue = []
 75  end
 76
 77  def traverse(member)
 78    @queue = []
 79    @root = member
 80    @queue.push(member)
 81    until @queue.empty? do
 82      member = @queue.shift
 83      write(newline) if member.nil? && @queue.first
 84      next if member.nil?
 85
 86      visit(member)
 87      added = false
 88      member.each do |friend|
 89        @queue.push(friend) if eligible?(friend)
 90        added = true
 91      end
 92
 93      @queue.push(nil) if added
 94    end
 95  end
 96
 97  private
 98
 99  def eligible?(member)
100    !visited?(member) && !root?(member) && !queued?(member)
101  end
102
103  def newline
104    "\n"
105  end
106
107  def queued?(friend)
108    @queue.find { |x| x == friend }
109  end
110
111  def visit(member)
112    return if visited?(member) || root?(member)
113    write(member.name) unless root?(member)
114    write(",") unless @queue.first.nil?
115    @visited[member.name] = true
116  end
117
118  def visited?(member)
119    @visited.key?(member.name)
120  end
121
122  def root?(member)
123    @root.name == member.name
124  end
125
126  def write(value)
127    writer.write(value)
128  end
129end