-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproficiency_finder.rb
76 lines (67 loc) · 1.83 KB
/
proficiency_finder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
require 'csv'
class ProficiencyFinder
Workout = Struct.new(:score, :categories)
def initialize(workouts_csv, categories)
@categories = categories
@members = {}
create_member_workouts_hash(workouts_csv)
end
def find_least_proficient
solution = least_proficient_member_and_score
if solution.length > 0
puts solution.join(', ')
else
puts "No solution"
end
end
private
def create_member_workouts_hash(csv_file)
CSV.foreach(csv_file) do |row|
row = row.map{ |i| i.gsub(/\s+/, '') }
member = row[0].to_sym
workout = Workout.new(row[1].to_f, row[2..-1])
if @members.include?(member)
@members[member].push(workout)
else
@members[member] = [workout]
end
end
end
def least_proficient_member_and_score
least = []
@members.each do |name, v|
puts "Selecting minimum workout score combinations for #{name}"
min_score_combo = get_min_score_combo(v)
puts()
if !min_score_combo.nil?
least = [name, min_score_combo.to_i] if least[1].nil? || (min_score_combo < least[1])
end
end
return least
end
def get_min_score_combo(workouts)
desired = @categories
best_choices = []
while desired.any?
best = min(workouts, desired)
return nil unless best
puts "Choosing #{best.categories.join(' & ')} for #{best.score}"
best_choices = best_choices | [best]
desired = desired - best.categories
end
return best_choices.map(&:score).reduce(&:+)
end
def min(workouts, desired)
min = 1.0/0
min_workout = nil
workouts.each do |workout|
intersection = workout.categories & desired
value = workout.score / intersection.length
if value < min
min = value
min_workout = workout
end
end
return min_workout
end
end