Ответ 1
Вы можете написать свой метод:
def score(d1,d2,d3,d4,d5)
...
end
Первое, что вам нужно сделать, это определить, совпадают ли три из пяти значений. Если три одинаковые, вам нужно будет знать, все ли они 1
или какое-то другое значение, и вам нужно знать, что представляют собой два других значения. Если не более двух значений одинаковы, вам также нужно это знать. Это действительно суть проблемы. Поэтому давайте напишем метод:
def partition(d1,d2,d3,d4,d5)
...
end
который вызывается из score
следующим образом:
three_value, other_values = partition(d1,d2,d3,d4,d5)
где:
-
three_value
равно общему значению группы из трех равных значений (1-6
) или (скажем)nil
, если нет группы из трех равных значений; и -
other_values
- это массив из двух значений из[d1,d2,d3,d4,d5]
, которые исключают три равных значения (если существует группа из трех равных значений) или[d1,d2,d3,d4,d5]
(если нет группы из трех равных значений).
Например,
three_value, other_values = partition(1,3,4,3,6)
#=> [nil, [1, 3, 4, 3, 6]]
three_value, other_values = partition(1,3,4,3,3)
#=> [3, [1, 4]]
three_value, other_values = partition(1,3,3,3,3)
#=> [3, [1, 3]]
three_value, other_values = partition(3,3,3,3,3)
#=> [3, [3, 3]]
Как только у нас есть метод partition
, метод score
, если довольно простой:
def score(d1,d2,d3,d4,d5)
three_value, other_values = partition(d1,d2,d3,d4,d5)
total = case three_value
when 1 then 1000
when nil then 0
else three_value * 1000
end
other_values.each do |i|
total += case i
when ...
...
when ...
...
end
end
end
Прежде чем перейти к методу partition
, мы можем упростить score
следующим образом:
def score(*d)
three_value, other_values = partition(*d)
total = case three_value
when 1 then 1000
when nil then 0
else three_value * 1000
end
other_values.each do |i|
total += case i
when ...
...
when ...
...
end
end
end
Использование оператора "splat", *
, удобно, потому что нас не волнует порядок рулонов матрицы. При вызове метода score
или partition
, если d = [1,3,4,3,3]
, score(*d)
идентичен:
score(1,3,4,3,3)
(Делаем, чтобы понять, почему *
называется "splat"?)
В методе score
выше d
(not *d
) представляет собой массив из пяти значений.
Теперь рассмотрим метод partition
. Нам нужно подсчитать количество раз, когда каждый результат (1-6
). Это хорошая работа для хэша:
def partition(*d)
counts = {}
d.each do |i|
if counts.key?(i)
counts[i] += 1
else
counts[i] = 1
end
end
...
end
Предположим d = [1,3,4,3,3]
. Тогда
counts #=> {1=>1, 3=>3, 4=>1}
Теперь нам нужно найти ключ с наибольшим значением. Для этого мы могли бы использовать Enumerable # max_by:
k, v = counts.max_by { |k,v| v }
#=> [3, 3]
k #=> 3
v #=> 3
Затем мы можем вычислить other_values
следующим образом:
other_values = case v
when 3
d - [k]
when 4
(d - [k]) << k
when 5
(d - [k]) << k << k
else
d
end
Примечание Array # - - метод разности массивов.
Наконец,
three_value = (v >= 3) ? k : nil
и partition
вернутся:
[three_value, other_values]
Вы можете собрать все это вместе?
[Возможно, вы не захотите прочитать следующее, пока у вас не будет рабочего кода.]
Как только вы приобретете опыт работы с Ruby, вы сможете написать partition
следующим образом:
def partition(*d)
k,v = d.each_with_object(Hash.new(0)) { |i,h| h[i]+=1 }.max_by(&:last)
(v < 3)) ? [nil, d] : [k, d - [k] + [k]*(v-3)]
end
Помимо этого: Я бы хотел увидеть основной метод Array#difference
, который я определяю и разрабатываю здесь. Это позволило бы выразить последнюю строку тела partition
:
(v < 3)) ? [nil, d] : [k, d.difference([k,k,k])]