Clojure中平衡两个向量的功能方法

时间:2019-02-06 15:08:50

标签: clojure functional-programming

我将平衡代表产品需求和可用性的两个向量。

这是材料需求计划中的一个典型问题,非常容易以命令式进行。函数编程中可能吗?

我必须以下列优先级从A1传递到A2:首先为具有相同:cat的记录分配aval qty,然后在:day早期分配给需求。

:day的格式为AAAAMMDD

(def A1
  {:avail [{:day 20190101 :qty  10  :mkey "AAABB" :cat "CO1"}
           {:day 20190101 :qty  20  :mkey "OS100" :cat "CO1"}
           {:day 20190102 :qty  50  :mkey "OS200" :cat "   "}
           {:day 20190103 :qty  50  :mkey "OS300" :cat "   "}
           {:day 20190104 :qty  40  :mkey "OS400" :cat "   "}]

   :needs [{:day 20190107 :qty -100 :mkey "OS200" :cat "   "}
           {:day 20190108 :qty  -50 :mkey "OS300" :cat "   "}
           {:day 20190109 :qty -100 :mkey "OS400" :cat "   "}
           {:day 20190217 :qty -100 :mkey "OS100" :cat "CO1"}]})


(def A2
  {:avail [{:day 20190101 :qty  0   :mkey "AAABB" :cat "CO1"}
           {:day 20190101 :qty  0   :mkey "OS100" :cat "CO1"}
           {:day 20190102 :qty  0   :mkey "OS200" :cat "   "}
           {:day 20190103 :qty  0   :mkey "OS300" :cat "   "}
           {:day 20190104 :qty  0   :mkey "OS400" :cat "   "}]

   :needs [{:day 20190107 :qty 0    :mkey "OS200" :cat "   "}
           {:day 20190108 :qty -10  :mkey "OS300" :cat "   "}
           {:day 20190109 :qty -100 :mkey "OS400" :cat "   "}
           {:day 20190217 :qty -70  :mkey "OS100" :cat "CO1"}]})

从A1获取A2的可能的Java算法

ArrayList avail = new ArrayList();
ArrayList needs = new ArrayList();
/* first assign based on same :cat */
for (int i=0;i< needs.size();i++) {
    // get needs record of index i..
    for (int j=0;j< avail.size();j++) {
         // get avail record of index j..
         if (need.cat != avail.cat)  // only same same cat ! 
                continue;
         balance the actuals records needs and avail
         updating relative qty, 
         trying to set need qty to zero decrementing avail
    }
}
/* now again without test on cat */
for (int i=0;i< needs.size();i++) {
    // get needs record of index i..
    for (int j=0;j< avail.size();j++) {
         // get avail record of index j..
         balance the actuals records needs and avail
         updating relative qty 
         trying to set need qty to zero decrementing avail
    }
}

1 个答案:

答案 0 :(得分:0)

我将通过两个功能来做到这一点:

  1. 第一个功能是基于一个供应来减少需求
  2. 第二个函数使用上面的函数消耗耗材列表
(defn consume
  "Reduce demands base on one supply"
  [can-consume? demands supply]
  (reduce (fn [{:keys [supply] :as ans} d]
            (let [qty (:qty supply)]
              (if (can-consume? d supply)
                (let [used (-> d :qty (+ qty))]
                  (-> ans
                      (update :needs conj (assoc d :qty (min 0 used)))
                      (assoc-in [:supply :qty] (max 0 used))))
                (update ans :needs conj d))))
          ;; initial state - no demands just one supply
          {:needs  []
           :supply supply}
          ;; feed demands into reducing function
          demands))

(defn consume-all
  "Reduce demands with a list of supplies"
  [{:keys [needs avails]}]
  (->> (reduce (fn [ans s]
                 (let [{:keys [supply needs]
                        :as   same-cat}      (consume (fn [d s] (and (<= (:day s) (:day d))
                                                                     (= (:cat s) (:cat d))))
                                                      (:needs ans)
                                                      s)
                       {:keys [supply needs]} (if supply ;; supply of same cat is consumed
                                                same-cat
                                                (consume (fn [d s] (<= (:day s) (:day d)))
                                                         (:needs ans)
                                                         s))]
                   (-> ans
                       (assoc :needs needs)
                       (update :avails conj supply))))
               ;; initial state - no supply only demands
               {:needs  needs
                :avails []}
               ;; feed supplies into reducing function
               avails)))

运行样品

(consume-all {:needs [{:day 20190107 :qty -100 :mkey "OS200" :cat "   "}
                       {:day 20190108 :qty -50 :mkey "OS300" :cat "   "}
                       {:day 20190109 :qty -100 :mkey "OS400" :cat "   "}
                       {:day 20190217 :qty -100 :mkey "OS100" :cat "CO1"}]
              :avails  [{:day 20190101 :qty 10 :mkey "AAABB" :cat "CO1"}
                       {:day 20190101 :qty 20 :mkey "OS100" :cat "CO1"}
                       {:day 20190102 :qty 50 :mkey "OS200" :cat "   "}
                       {:day 20190103 :qty 50 :mkey "OS300" :cat "   "}
                       {:day 20190104 :qty 40 :mkey "OS400" :cat "   "}]})

==>
{:needs
 [{:day 20190107, :qty 0, :mkey "OS200", :cat "   "}
  {:day 20190108, :qty -10, :mkey "OS300", :cat "   "}
  {:day 20190109, :qty -100, :mkey "OS400", :cat "   "}
  {:day 20190217, :qty -70, :mkey "OS100", :cat "CO1"}],
 :avails
 [{:day 20190101, :qty 0, :mkey "AAABB", :cat "CO1"}
  {:day 20190101, :qty 0, :mkey "OS100", :cat "CO1"}
  {:day 20190102, :qty 0, :mkey "OS200", :cat "   "}
  {:day 20190103, :qty 0, :mkey "OS300", :cat "   "}
  {:day 20190104, :qty 0, :mkey "OS400", :cat "   "}]}