I’m working on a Clojure algorithm to solve the problem posed here: http://spin.atomicobject.com/2011/05/31/use-clojure-to-move-drugs-a-programming-challenge/ and I’ve run into a hiccup.
I’m using a recursive algorithm (perhaps not the right choice to begin with), to walk over a vector of “doll” structs that are ordered by highest to lowest value-to-weight ratio. The relevant code is:
(defn get-carryable-dolls
[dolls carryable-dolls]
(def doll (first dolls)) ;initializing for use in multiple places
(def rest-dolls (rest dolls)) ;initializing for use in multiple places
(
if (will-fit? doll (get-weight-sum carryable-dolls))
( ;will fit
(
if
(= carryable-dolls {})
(def new-doll-set [doll]) ;First trip, get rid of empty set by initializing new
(def new-doll-set (flatten [doll carryable-dolls])) ;otherwise, flatten set into vector of structs
)
;tests to see if we have any more dolls to test, and if so, recurses. Otherwise, should pass the resultant vector
;up the stack. it appears to be the "else" potion of this if statement that is giving me problems.
(if (not= () rest-dolls) (get-carryable-dolls rest-dolls new-doll-set) (vec new-dolls))
)
( ;will not fit
;gets the rest of the dolls, and sends them on without modifying the vector of structs
;it appears to be the "else" potion of this if statement that is giving me problems.
(if (not= () rest-dolls) (get-carryable-dolls rest-dolls carryable-dolls) (vec carryable-dolls))
)
)
)
That code is working correctly; returnable-dolls contains the desired vector of doll structs to return as a solution. Unfortunately, when I attempt to return the returnable-dolls vector to the calling position, I’m receiving the following error:
CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector,compiling:(drugmover\tests.clj:83)
Line 82-83 read:
(def empty-dolls {})
(def designated-dolls (get-carryable-dolls sorted-values empty-dolls))
I’m stumped as to what might be causing the issue in the compiler error, and since Clojure seems to prefer terse error messages over stack traces (or at least, the REPL functionality in Clooj does), I’m at a loss to how to fix it. If anyone has any suggestions, I’d greatly appreciate them!
Thanks in advance.
EDIT:
I’ve modified the code with the suggested fixes by those in the answers and the comments and provided a handful of comments to help illustrate the flow control that’s going on. Hopefully, by illustrating my thinking, someone will be able to give me an idea where I’m going wrong.
The following code incorporates most of the suggestions you already received in other answers and others, namely:
loop/letinstead ofdeffor local name bindingsseqfor checking empty listscarryable-dollsseq before adding an elementI can’t test it without having the definition of the ancillary functions you have (e.g.
will-fit?), but at least should fix a couple of issues (and bring the code in a more readable form):The following is a complete refactoring of the code that leverages the standard
reducefunction and defines a function that provides the core decision logic whether a doll has to be included or not in the result: