2015-12-03 92 views
2

要規劃晚餐菜單,用戶需要旋轉3天的肉,然後再進行一次素食主菜。肉的輪換是牛肉,雞肉,魚肉,豬肉。蔬菜旋轉是stirfry,然後豆腐。是否有更好的(更優雅,簡潔或可讀的)生成膳食序列的方式比我下面的要少?如何生成在Clojure中編寫的循環中循環的循環順序

(defn menu [n] (let [meat (cycle '[:beef :chicken :fish :pork]) 
        veg (cycle '[:stirfry :tofu])] 
       (take n (mapcat seq (interleave (partition 3 meat) (partition 1 veg)))))) 

回答

0

我會忍不住來概括問題:

  • 接受以任何比例的任何數種主菜交錯的。
  • 生成整個懶惰序列,將客戶端截留爲 許多根據需要。

您可以提供數據作爲備用數量和菜餚順序。對於你的榜樣,我們有

(def dishes [3 [:beef :chicken :fish :pork] 
      1 [:stirfry :tofu]]) 

我們可以適應您的解決方案產生的菜餚無盡的慵懶序列:

(defn rotate [nlist-pairs] 
    (let [pairs (partition 2 nlist-pairs) 
     sources (map (fn [[n xs]] (partition n (cycle xs))) 
        pairs)] 
    (apply concat (apply interleave sources)))) 

爲了得到前十...

(take 10 (rotate dishes)) 
;(:beef :chicken :fish :stirfry :pork :beef :chicken :tofu :fish :pork) 
+0

這真的很聰明。我喜歡如何添加許多收藏並控制比例,以及如何將菜餚的定義和比例與選擇分開。我對此的動機並非真正的菜餚,而是許多球隊之間分享的一種責任陣容,一些大的,一些小的,我想盡可能減輕他們的負擔。 – sankyo

1

這是略短,更易於閱讀我猜(也許更快):

在REPL
(defn menu [n] 
    (let [meat (cycle '[:beef :chicken :fish :pork]) 
     veg (cycle '[:stirfry :tofu])] 
    (take n (rest (mapcat conj (partition 3 meat) veg))))) 

user> (menu 10) 
(:beef :chicken :fish :tofu :pork :beef :chicken :stirfry :fish :pork) 

mapcat可以採取一些集合,它會做

(conj (:beef :chicken :fish) :stirfry)

(conj (:pork :beef :chicken) :tofu)

你只需要列出下降的第一個值,作爲conj將一個元素添加到開始。

如果有可能以veg餐開始,那麼你也可以輸掉rest,使它更短。

(take n (mapcat conj (partition 3 meat) veg))

+0

不太。你的第一個蔬菜是豆腐。它應該是stirfry。 ''mapcat'中的'veg'替換爲'(cons:扔掉蔬菜)'? – Thumbnail