Рассчитать Winrate с циклом повторения - PullRequest
0 голосов
/ 27 января 2019
(defn to-percentage [wins total]
  (if (= wins 0) 0
      (* (/ wins total) 100)))

(defn calc-winrate [matches]
  (let [data (r/atom [])]
    (loop [wins 0
           total 0]
      (if (= total (count matches))
        @data
        (recur (if (= (get (nth matches total) :result) 1)
                 (inc wins))
               (do
                 (swap! data conj (to-percentage wins total))
                 (inc total)))))))

(calc-winrate [{:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])

Я получил следующий код, calc-winrate в последней строке возвращает [0 0 50 0 25].Я пытаюсь заставить его вернуться [0 50 33.33333333333333 50 60].

Я делаю приращение для wins неправильно?Когда я печатаю значение wins для каждой итерации, я получаю

0
nil
1
nil
1

, поэтому я предполагаю, что я как-то сбрасываю или nil wins как-то?

Кроме того, можно ли заменить весь этот цикл на map / map-indexed или что-то в этом роде?Такое ощущение, что карта была бы идеальной для использования, но мне нужно помнить о победах и итогах предыдущей итерации для каждой итерации.

Спасибо!

Ответы [ 4 ]

0 голосов
/ 30 января 2019

Вы можете рассчитать текущие ставки выигрыша следующим образом:

(defn calc-winrate [matches]
  (map
    (comp float #(* 100 %) /)
    (reductions + (map :result matches))
    (rest (range))))

Например,

=> (calc-winrate [{:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])
(0.0 50.0 33.333332 50.0 60.0)

map работает в двух последовательностях:

  • (reductions + (map :result matches)) - промежуточный итог побед;
  • (rest (range)))) - (1 2 3 ... ), соответствующее количество совпадений.

Функция ping map, (comp float #(* 100 %) /),

  • делит соответствующие элементы последовательностей,
  • умножает ее на 100 и
  • превращает его в число с плавающей точкой.
0 голосов
/ 27 января 2019
 (if (= (get (nth matches total) :result) 1)
             (inc wins))

ваш if должен быть записан следующим образом:

 (if (= (get (nth matches total) :result) 1)
             (inc wins)
             wins  ; missing here , other wise it will return a nil, binding to wins in the loop
)

, если вы идете с сокращениями,

(defn calc-winrate2 [ x y ]
  (let [ {total :total r :wins  } x
        {re :result } y]
    (if (pos? re )
      {:total (inc total) :wins (inc r)}
      {:total (inc total) :wins r}
      )
    )
  )

(reductions calc-winrate2 {:total 0 :wins 0} [   {:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])
0 голосов
/ 27 января 2019

Вот ленивое решение, использующее reductions для получения последовательности промежуточных итоговых выигрышей и преобразователей в 1) объединение круглых чисел с промежуточными итоговыми значениями 2) деление пар 3) преобразование дробей в проценты:

(defn calc-win-rate [results]
  (->> results
       (map :result)
       (reductions +)
       (sequence
         (comp
           (map-indexed (fn [round win-total] [win-total (inc round)]))
           (map (partial apply /))
           (map #(* 100 %))
           (map float)))))

(calc-win-rate [{:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])
=> (0.0 50.0 33.333332 50.0 60.0)
0 голосов
/ 27 января 2019

Вот решение с уменьшением:

(defn calc-winrate [matches]
  (let [total-matches (count matches)]
    (->> matches
         (map :result)
         (reduce (fn [{:keys [wins matches percentage] :as result} match]
                  (let [wins (+ wins match)
                        matches (inc matches)]
                    {:wins wins
                     :matches matches
                     :percentage (conj percentage (to-percentage wins matches))}))
                 {:wins 0 
                  :matches 0
                  :percentage []}))))

Таким образом, задача состоит в том, чтобы поддерживать (и обновлять) состояние вычислений до сих пор.Мы делаем это на карте, которая

 {:wins 0
  :matches 0
  :percentage []}

Победы будут содержать выигрыши на данный момент, совпадения - это количество совпадений, которые мы проанализировали, а процент - это процент на данный момент.

...