Lots of debugging and new unit tests, results in something which seems
to perform as specified.
This commit is contained in:
parent
c4fc2fcdd0
commit
ef5c6e9dc6
|
@ -1,4 +1,5 @@
|
||||||
(ns vending.core)
|
(ns vending.core
|
||||||
|
(:use clojure.set))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@
|
||||||
|
|
||||||
(defn sum-coins
|
(defn sum-coins
|
||||||
"takes a list in the form (:merk :merk :bawbee :plack :bodle) and returns
|
"takes a list in the form (:merk :merk :bawbee :plack :bodle) and returns
|
||||||
a map {:merk 2 :plack 1 :bawbee 1 :bodle 1}. Optional second argument: an
|
a wallet {:merk 2 :plack 1 :bawbee 1 :bodle 1}. Optional second argument: an
|
||||||
existing map in that general form."
|
existing map in that general form."
|
||||||
([coins]
|
([coins]
|
||||||
(sum-coins coins {}))
|
(sum-coins coins {}))
|
||||||
|
@ -83,7 +84,7 @@
|
||||||
(defn subtract-merk [list]
|
(defn subtract-merk [list]
|
||||||
(subtract-denomination list 4))
|
(subtract-denomination list 4))
|
||||||
|
|
||||||
(defn in-make-change [amount merk plack bawbee bodle]
|
(defn- in-make-change [amount merk plack bawbee bodle]
|
||||||
"Given this amount of change to make, and this number each of merks, placks, bawbees
|
"Given this amount of change to make, and this number each of merks, placks, bawbees
|
||||||
and bodles, return a tuple (merk plack bodle bawbee) which indicates the number remaining
|
and bodles, return a tuple (merk plack bodle bawbee) which indicates the number remaining
|
||||||
after making change, or nil if not possible"
|
after making change, or nil if not possible"
|
||||||
|
@ -117,7 +118,7 @@
|
||||||
|
|
||||||
(defn make-change [amount coins]
|
(defn make-change [amount coins]
|
||||||
"Given this amount of change to make, and this number each of merks, placks, bawbees
|
"Given this amount of change to make, and this number each of merks, placks, bawbees
|
||||||
and bodles, return a map with keys (:merk :plack :bawbee :bodle) which indicates the
|
and bodles, return a wallet (a map with keys (:merk :plack :bawbee :bodle)) which indicates the
|
||||||
number of each remaining after making change, or nil if not possible"
|
number of each remaining after making change, or nil if not possible"
|
||||||
(to-coins
|
(to-coins
|
||||||
(let [merk (:merk coins)
|
(let [merk (:merk coins)
|
||||||
|
@ -131,10 +132,29 @@
|
||||||
|
|
||||||
(defn subtract-change [coin-stacks change]
|
(defn subtract-change [coin-stacks change]
|
||||||
"Return a copy of these coin-stacks with this change removed"
|
"Return a copy of these coin-stacks with this change removed"
|
||||||
{:merk (- (:merk coin-stacks) (:merk change))
|
(let [change-map (sum-coins change)]
|
||||||
:plack (- (:plack coin-stacks) (:plack change))
|
{:merk (- (:merk coin-stacks) (or (:merk change-map) 0))
|
||||||
:bawbee (- (:bawbee coin-stacks) (:bawbee change))
|
:plack (- (:plack coin-stacks) (or (:plack change-map) 0))
|
||||||
:bodle (- (:bodle coin-stacks) (:bodle change))})
|
:bawbee (- (:bawbee coin-stacks) (or (:bawbee change-map) 0))
|
||||||
|
:bodle (- (:bodle coin-stacks) (or (:bodle change-map) 0))}))
|
||||||
|
|
||||||
|
|
||||||
|
(defn in-op-maps [op kys map1 map2 dflt]
|
||||||
|
(cond (empty? kys) {}
|
||||||
|
true
|
||||||
|
(let [ky (first kys)]
|
||||||
|
(assoc (in-op-maps op (rest kys) map1 map2 dflt)
|
||||||
|
ky
|
||||||
|
(apply op (list (or (map1 ky) dflt) (or (map2 ky) dflt)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn op-maps [op map1 map2 dflt]
|
||||||
|
"return a new map composed by applying this op to the values of
|
||||||
|
the keys of these maps, using this default when no value present"
|
||||||
|
(in-op-maps op (union (keys map1) (keys map2)) map1 map2 dflt))
|
||||||
|
|
||||||
|
(defn add-wallets [wallet1 wallet2]
|
||||||
|
(op-maps + wallet1 wallet2 0))
|
||||||
|
|
||||||
(defn subtract-change-machine [machine change]
|
(defn subtract-change-machine [machine change]
|
||||||
"return a copy of this machine which has this amount of change removed from its coins"
|
"return a copy of this machine which has this amount of change removed from its coins"
|
||||||
|
@ -144,36 +164,50 @@
|
||||||
(defn make-change-machine [machine change]
|
(defn make-change-machine [machine change]
|
||||||
"given this machine and these numbers of coins to remove, return a copy of the machine
|
"given this machine and these numbers of coins to remove, return a copy of the machine
|
||||||
with the coins removed"
|
with the coins removed"
|
||||||
(let [tend (sum-coins (:tendered machine))]
|
(cond (empty? change) machine
|
||||||
(cond (= change '(0 0 0 0)) machine)
|
true (assoc (dissoc (subtract-change-machine machine change) :change ) :change change )))
|
||||||
true (assoc (dissoc (subtract-change-machine machine change) :change ) :change change )))
|
|
||||||
|
|
||||||
(defn remove-from-stock [machine item]
|
(defn remove-from-stock [machine item]
|
||||||
"return a copy of this machine with one fewer of this item in stock"
|
"return a copy of this machine with one fewer of this item in stock"
|
||||||
(update-in machine [:stock item] dec))
|
(update-in machine [:stock item] dec))
|
||||||
|
|
||||||
(defn deliver-item [machine item change]
|
(defn deliver-item [machine item]
|
||||||
(make-change-machine
|
"Remove an item matching this item from stock and add it to the output hopper"
|
||||||
(remove-from-stock
|
(remove-from-stock
|
||||||
(assoc (dissoc machine :output) :output (cons item (:output machine)))
|
(assoc (dissoc machine :output) :output (cons item (:output machine)))
|
||||||
item)
|
item))
|
||||||
change))
|
|
||||||
|
|
||||||
|
(defn store-coins-machine [machine]
|
||||||
|
;; add the tendered coins to the coin stacks
|
||||||
|
(let [wallet (sum-coins (:tendered machine))]
|
||||||
|
(assoc
|
||||||
|
(dissoc (dissoc machine :tendered) :coins)
|
||||||
|
:coins (add-wallets wallet (:coins machine)))))
|
||||||
|
|
||||||
(defn get-item [machine item]
|
(defn get-item [machine item]
|
||||||
(let [item-price (item item-prices)
|
(let [item-price (item item-prices)
|
||||||
coins (:coins machine)
|
coins (:coins machine)
|
||||||
tendered (coins-value (:tendered machine))
|
tendered (coins-value (:tendered machine))
|
||||||
change (make-change (- tendered item-price) coins)]
|
change (make-change (- tendered item-price) coins)]
|
||||||
(print (list "hello" item-price coins tendered change ))
|
;; (print (list "hello" item-price coins tendered change ))
|
||||||
(cond (> 0 (item (:stock machine))) (message-machine (coin-return machine) (str "Sorry, " item " not in stock"))
|
(cond (> 0 (item (:stock machine))) (message-machine (coin-return machine) (str "Sorry, " item " not in stock"))
|
||||||
(<= tendered item-price) (message-machine machine "Please insert more money")
|
(<= tendered item-price) (message-machine machine "Please insert more money")
|
||||||
(= change '(0 0 0 0)) (message-machine (coin-return machine) "Sorry, I don't have enough change.")
|
(= change '(0 0 0 0)) (message-machine (coin-return machine) "Sorry, I don't have enough change.")
|
||||||
true (message-machine (deliver-item machine item change) (str "Enjoy your " item)))))
|
true (message-machine
|
||||||
|
(store-coins-machine
|
||||||
|
(make-change-machine
|
||||||
|
(deliver-item machine item) change))
|
||||||
|
(str "Enjoy your " item)))))
|
||||||
|
|
||||||
(defn get-caramel-wafer [machine]
|
(defn get-caramel-wafer [machine]
|
||||||
(get-item machine :caramel-wafer))
|
(get-item machine :caramel-wafer))
|
||||||
|
|
||||||
|
(defn get-teacake [machine]
|
||||||
|
(get-item machine :teacake))
|
||||||
|
|
||||||
|
(defn get-snowball [machine]
|
||||||
|
(get-item machine :snowball))
|
||||||
|
|
||||||
;; (get-caramel-wafer (add-coin (add-coin (make-default-machine) :merk) :merk))
|
;; (get-caramel-wafer (add-coin (add-coin (make-default-machine) :merk) :merk))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
(some #(= elm %) seq))
|
(some #(= elm %) seq))
|
||||||
|
|
||||||
|
|
||||||
(deftest test-add-coin
|
(deftest test-vending
|
||||||
(testing
|
(testing
|
||||||
"Test adding coins to machine"
|
"Test adding coins to machine"
|
||||||
(let [machine (make-default-machine)
|
(let [machine (make-default-machine)
|
||||||
|
@ -47,22 +47,34 @@
|
||||||
|
|
||||||
(testing
|
(testing
|
||||||
"making appropriate change"
|
"making appropriate change"
|
||||||
(let [no-change (make-change 0 5 5 5 5)
|
(let [wallet {:merk 5 :plack 5 :bawbee 5 :bodle 5}
|
||||||
ten-change (make-change 10 5 5 5 5)
|
no-change (make-change 0 wallet)
|
||||||
all-change (make-change 140 5 5 5 5)]
|
merk-change (make-change 100 wallet)
|
||||||
(is (= no-change '(0 0 0 0)) "one hundred units of change should be satisfied with one merk")
|
ten-change (make-change 10 wallet)
|
||||||
(is (= all-change '(1 1 1 1)) "140 units of change should be satisfied with one coin of each denomination")
|
all-change (make-change 140 wallet)]
|
||||||
(is (or (= ten-change '(0 0 1 0)) (= ten-change '(0 0 0 2))) "ten change could be satisfied with one bawbee or two bodles")))
|
(is (empty? no-change) "no change implies an empty coin list")
|
||||||
|
(is (= merk-change '(:merk)) "100 units of change should be satisfied with one mark")
|
||||||
|
(is (= (set all-change) (set (list :merk :plack :bawbee :bodle))) "140 units of change should be satisfied with one coin of each denomination")
|
||||||
|
(is (or (= (set ten-change) (set (list :bawbee))) (= (set ten-change) (set (list :bodle :bodle)))) "ten change could be satisfied with one bawbee or two bodles")))
|
||||||
|
|
||||||
(testing
|
(testing
|
||||||
"removing change from machine"
|
"removing change from machine"
|
||||||
(let [machine (make-default-machine)
|
(let [machine (make-default-machine)
|
||||||
changed (make-change-machine machine '(1 1 1 1))
|
changed (make-change-machine machine '(:merk :plack :bawbee :bodle))
|
||||||
emptied (make-change-machine machine '(1 4 4 4))]
|
emptied (make-change-machine machine '(:merk :plack :bawbee :bodle :plack :bawbee :bodle :plack :bawbee :bodle :plack :bawbee :bodle))]
|
||||||
(is (= (vals (:coins changed)) '(0 3 3 3)) "each coin slot should be decremented by one")
|
(is (= (vals (:coins changed)) '(0 3 3 3)) "each coin slot should be decremented by one")
|
||||||
(is (= (vals (:coins emptied)) '(0 0 0 0)) "each coin slot should be empty (contain zero)")
|
(is (= (vals (:coins emptied)) '(0 0 0 0)) "each coin slot should be empty (contain zero)")
|
||||||
))
|
))
|
||||||
|
|
||||||
|
(testing
|
||||||
|
"full machine cycle"
|
||||||
|
(let [machine (get-caramel-wafer (add-coin (make-default-machine) :merk))]
|
||||||
|
(is (= (:message machine) "Enjoy your :caramel-wafer"))
|
||||||
|
(is (= (set (:change machine)) #{:plack :bawbee}))
|
||||||
|
(is (= (:merk (:coins machine)) 2))
|
||||||
|
(is (= (:output machine) '(:caramel-wafer)))))
|
||||||
)
|
)
|
||||||
|
|
||||||
(make-change-machine (make-default-machine) '( 1 1 1 1))
|
(make-change-machine (make-default-machine) '( 1 1 1 1))
|
||||||
|
|
||||||
|
(set '(:a :b :c))
|
||||||
|
|
Loading…
Reference in a new issue