Class: Drawy::Engine

Inherits:
Object
  • Object
show all
Defined in:
lib/drawy/engine.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.couplesObject

Returns the value of attribute couples.



4
5
6
# File 'lib/drawy/engine.rb', line 4

def couples
  @couples
end

.peopleObject

Returns the value of attribute people.



4
5
6
# File 'lib/drawy/engine.rb', line 4

def people
  @people
end

.resultObject

Returns the value of attribute result.



4
5
6
# File 'lib/drawy/engine.rb', line 4

def result
  @result
end

Class Method Details

.add_people(names) ⇒ Object



6
7
8
9
10
11
12
13
14
15
# File 'lib/drawy/engine.rb', line 6

def add_people(names)
  self.people  ||= []
  self.couples ||= {}

  names.delete_if(&:empty?)
  names.map!(&:downcase)

  couples[names.first] = names.last if names.size == 2
  self.people += names
end

.build_listObject

This probably deserves a bit of insight on what’s going on Basically we just build a list from people names keeping the order (note that people array has been shuffled) If we encounter a person following its partner we just take the next person first and add the partner after

Example: We have %w(john anna dan camille henrik) in names and we have { ‘john’ => ‘anna’ } in couples Step 1: remove john and put him in the list => list = %w(john) Step 2: remove anna, she’s in couple with john so remove dan and put him in the list => list = %w(john dan) Step 3: now anna is not in couple with dan so add her to the list => list = %w(john dan anna) Step 4: remove camille and put her in the list => list = %w(john dan anna camille) Step 5: remove henrik and put him in the list => list = %w(john dan anna camille henrik) An extra step is sometimes needed if the last person is in couple with the previous one because there’s nobody left to add in between the two so we just arbitrarily put him at position 1

The complexity is O(n), n representing the number of people



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/drawy/engine.rb', line 45

def build_list
  list = []
  names = people.dup

  while names.any?
    if is_couple?(list[-1], names[0])
      aside = names.shift
      break if names.empty?
      list << names.shift
      list << aside
      aside = nil
    else
      list << names.shift
    end
  end

  list.insert(1, aside) if aside

  list
end

.draw(options = {}) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/drawy/engine.rb', line 17

def draw(options = {})
  # shuffle: false option is used for testing purposes
  people.shuffle! unless options[:shuffle] == false
  list = build_list

  # Here build_list returns a list like so: %w(john dan anna camille)
  # Now we want to have direct access to a person's associated person so that
  # looking up the result for "john" returns "dan" without having to go through the array for every requested name
  # Therefore we need result to be { 'john' => 'dan', 'dan' => 'anna', 'anna' => 'camille', 'camille' => 'john' }
  self.result = Hash[list.zip(list.rotate)]
end

.is_couple?(x, y) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
# File 'lib/drawy/engine.rb', line 66

def is_couple?(x, y)
  return false if [x, y].include?(nil)
  couples[x] == y || couples[y] == x
end