Итак, у меня есть код, который дает мне комбинации. Я хотел бы найти наибольшее значение driver_points из каждой комбинации, а затем удвоить его значение.
Вот мой код в настоящее время:
# DRIVER AND TEAM ARRAYS
driver_points = { "john" => 18.1, "mike" => 19.3, "paul" => 15.6, "mark" => 1.1 }
driver_price = { "john" => 4.0, "mike" => 5.0, "paul" => 6.0, "mark" => 2.1 }
team_points = { "cowboys" => 20.1, "bears" => 19.3, "lions" => 15.6, "united" => 2.8 }
team_price = { "cowboys" => 1.0, "bears" => 2.0, "lions" => 3.0, "united" => 2.4 }
# DEFINE VARIABLE AND TARGET
teams = team_price.keys
drivers = driver_price.keys
target = 13.5
# CREATE METHOD TO SUM BOTH PRICES AND POINTS FOR GIVEN COMBINATION
def add_up(combo, ht, hd)
t, d = combo
ht[t] + hd.values_at(*d).sum
end
# ALL POSSIBLE COMBINATIONS OF TEAM AND DRIVERS
all_driver_combos = drivers.combination(3).to_a
all_combos = teams.product(all_driver_combos)
# SHOW ALL COMBOS WHERE SUM DOES NOT EXCEED TARGET
valid_combos = all_combos.select do |c|
add_up(c, team_price, driver_price) <= target
end
# SORT VALID COMBOS BY SUM OF POINTS FOR EACH ELEMENT
ordered = valid_combos.sort_by do |c|
-add_up(c, team_points, driver_points)
end
#OUTPUT
@combo = ordered.map do |c|
{ c.join(" ")=>{ price: add_up(c, team_price, driver_price),
points: add_up(c, team_points, driver_points).round(2) } }
end
Который в настоящее время выводит комбинации (1 команда и 3 гонщика) на основе целевого значения, но отсортированные по наивысшим баллам:
[{"cowboys john mike mark"=>{:price=>12.1, :points=>58.6}}, {"bears john mike mark"=>{:price=>13.1, :points=>57.8}}, {"cowboys john paul mark"=>{:price=>13.1, :points=>54.9}}, {"united john mike mark"=>{:price=>13.5, :points=>41.3}}]
Я хотел бы иметь возможность найти самого высокого водителя на основе самых высоких точек driver_points из каждой комбинации и удвоить значение его очков.
Например, в моей первой выведенной комбинации: {"cowboys john mike mark"=>{:price=>12.1, :points=>58.6}}
Я хочу иметь возможность найти гонщика с наибольшим количеством очков из трех - это будет один из Джона, Майка и Марка, поскольку я не хочу включать команду. Ответ - Майк, так как у него 19,3 очка. А затем удвойте очки водителя Майка, что должно обновить сумму :points=>. Давая новый общий балл 77,9. Кроме того, я хотел бы иметь возможность перемещать драйвер с наивысшими точками в начало комбинации драйверов для целей стилизации в представлении.
Итак, мой желаемый результат таков:
🤔 А знаете ли вы, что...
Этот веб-фреймворк использует концепцию 'конвенции выше конфигураций' (Convention over Configuration), что упрощает разработку.
Вы вычислили
valid_combos
#=> [["cowboys", ["john", "mike", "mark"]],
# ["cowboys", ["john", "paul", "mark"]],
# ["bears", ["john", "mike", "mark"]],
# ["united", ["john", "mike", "mark"]]]
Рассмотрите комбо
c = ["cowboys", ["john", "mike", "mark"]]
20.1 18.1 19.3 1.1
где очки команды для "cowboys"
и очки водителя для каждого из трех водителей в этой комбинации показаны выше. (Кто-то должен поговорить с Марком.)
Общее количество очков за эту комбинацию равно
add_up(c, team_points, driver_points)
#=> 58.6
К этому мы хотим добавить 19.3
очки, которые являются очками водителя для "Mike"
, поскольку у него больше всего очков среди трех водителей комбинации:
58.6 + 19.3
#=> 77.9
Мы можем сделать это в коде следующим образом.
def add_dbl(combo, team_points, driver_points)
t, ds = combo
dmax = ds.max_by { |d| driver_points[d] }
driver_points[dmax] + add_up(combo, team_points, driver_points)
end
Для комбинации c
, определенной выше,
add_dbl(c, team_points, driver_points)
#=> 77.9
как и ожидалось. Теперь мы можем использовать add_dbl
вместо add_up
для сортировки комбинаций.
ordered = valid_combos.sort_by do |c|
-add_dbl(c, team_points, driver_points)
end
#=> [["cowboys", ["john", "mike", "mark"]],
# ["bears", ["john", "mike", "mark"]],
# ["cowboys", ["john", "paul", "mark"]],
# ["united", ["john", "mike", "mark"]]]
Следующий код переставляет водителей таким образом, чтобы водитель с наибольшим количеством очков водителей отображался первым в каждом массиве водителей в ordered
.
ordered.each do |_t,ds|
imax = ds.each_index.max_by { |i| driver_points[ds[i]] }
ds.unshift(ds.delete_at(imax))
end
#=> [["cowboys", ["mike", "john", "mark"]],
# ["bears", ["mike", "john", "mark"]],
# ["cowboys", ["john", "paul", "mark"]],
# ["united", ["mike", "john", "mark"]]]
См. Array#each_index , Enumerable#max_by , Array#unshift и Array#delete_at . Обратите внимание, что Array#each возвращает свой получатель (ordered
), но мы модифицируем этот массив.
Чтобы просто отсортировать драйверы от самой высокой до самой низкой точки драйвера, измените приведенное выше выражение следующим образом.
ordered.each do |_t,ds|
ds.sort_by! { |d| -driver_points[d] }
end
#=> [["cowboys", ["mike", "john", "mark"]],
# ["bears", ["mike", "john", "mark"]],
# ["cowboys", ["john", "paul", "mark"]],
# ["united", ["mike", "john", "mark"]]]
По совпадению, эти массивы драйверов ничем не отличаются от приведенных выше.
Смотрите Массив#sort_by!.