Clojure 组合两个载体(用几个罐的内容物填充容器)
我有两个向量Clojure 组合两个载体(用几个罐的内容物填充容器),clojure,Clojure,我有两个向量 (def container [{:no 1 :volume 10} {:no 2 :volume 20}]) (def cans [{:no 1 :volume 2} {:no 2 :volume 8} {:no 1 :volume 5} {:no 2 :volume 8}]) 我想把罐子装满容器,这样可以退回这样的东西: [{:no 1 :volume 10 :cans [{:no 1 :volume 2} {:no 2 :volume 8}]} {:no 2 :vol
(def container [{:no 1 :volume 10} {:no 2 :volume 20}])
(def cans [{:no 1 :volume 2} {:no 2 :volume 8} {:no 1 :volume 5} {:no 2 :volume 8}])
我想把罐子装满容器,这样可以退回这样的东西:
[{:no 1 :volume 10
:cans [{:no 1 :volume 2} {:no 2 :volume 8}]}
{:no 2 :volume 20
:cans [{:no 1 :volume 5} {:no 2 :volume 8}]}]
这样就可以跟踪哪个罐子进了哪个容器。我开始使用reduce,但如果不使用变异商店来存放剩余的罐头,我就无法了解如何做到这一点。有什么想法吗
更新
所谓装满,我的意思是在第一个容器中装入尽可能多的罐,直到装满或接近(罐的总体积不超过容器的体积),然后开始装满第二个容器,直到装满或接近,依此类推。我们不需要为剩余的罐使用变异存储,因为reduce将序列作为参数,并通过累加函数进行reduce,在序列的每个元素上调用它 在下文中,我将容器分为已装/未装,并将每个罐插入最紧密的容器中(这有助于优化包装)
user>(def容器[{:编号1:卷10}{:编号2:卷20}])
#'用户/容器
用户>(def罐[{:编号1:卷2}{:编号2:卷8}{:编号1:卷5}{:编号2:卷8}])
#“用户/易拉罐
用户>
(def)集装箱运输
(让[容器(映射#(关联%:容量%:罐[])容器)
插入(fn[容器罐]
(->容器
(在[:容量](:卷can)中更新)
(在[:cans]conj-can]中更新)
蓄能器(fn[[填充]罐]
(让[[不匹配[拾取和取消拾取]]
(拆分为#)(<(:容量%)
(:容积罐)
(排序方式:容量填充)
拾取(插入拾取的罐)
仍在填充(混凝土未填充)]
(如果(那些def
调用无效-我想你想让容器和罐子成为向量或列表?啊,对不起。填充,我的意思是在第一个容器中装入尽可能多的罐子,直到装满或尽可能接近,然后开始填充第二个容器,直到装满或尽可能接近,依此类推。我更新了这个问题。它有点复杂,w重新阅读这个问题-你喜欢在使用第二个容器之前完全填充第一个容器,还是更喜欢获得最佳包装?这些是不同的任务,我可能错误地假设了后者
user> (def container [{:no 1 :volume 10} {:no 2 :volume 20}])
#'user/container
user> (def cans [{:no 1 :volume 2} {:no 2 :volume 8} {:no 1 :volume 5} {:no 2 :volume 8}])
#'user/cans
user>
(def containerized
(let [containers (map #(assoc % :capacity (:volume %) :cans []) container)
insert (fn [container can]
(-> container
(update-in [:capacity] - (:volume can))
(update-in [:cans] conj can)))
accumulator (fn [[filled filling] can]
(let [[non-fits [picked & unpicked]]
(split-with #(< (:capacity %)
(:volume can))
(sort-by :capacity filling))
picked (insert picked can)
still-filling (concat non-fits unpicked)]
(if (<= (:capacity picked) 0)
[(conj filled picked) still-filling]
[filled (conj still-filling picked)])))
filled (reduce accumulator
[[] containers]
cans)]
(map #(dissoc % :capacity) (apply concat filled))))
#'user/containerized
user> (clojure.pprint/pprint containerized)
({:cans [{:volume 2, :no 1} {:volume 8, :no 2}], :volume 10, :no 1}
{:cans [{:volume 5, :no 1} {:volume 8, :no 2}], :volume 20, :no 2})
nil