setf and nth problem

Discussion of Common Lisp
Post Reply
mickmos
Posts: 2
Joined: Tue Sep 28, 2010 9:14 pm

setf and nth problem

Post by mickmos » Tue Sep 28, 2010 9:26 pm

Hi guys i am having a lot of trouble with this relatively simple piece of code. I cant for the life of me figure out whats wrong with it

Basically the program figures out how to get exactly half of an 8 liter paint time using the 8 liter tin, 5 liter, and a 3 liter tin,
To express this problem i made the list (eight-tin five-tin three-tin). so the initial state would be (8 0 0)

i believe that it is one of these two functions that are giving me the problem:
1) room-in-three gives back how much room there is in the 3 liter can
2) fix-three makes it so the 3 liter can is not negative or holding more than 3 liters

Code: Select all

(defun room-in-three (a)
   (- 3 (nth 2 a)))

Code: Select all

(defun fix-three (a)
   (cond ((< (nth 2 a) 0) (setf (nth 2 a) 0))
         ((> (nth 2 a) 3) (setf (nth 2 a) 3))))
When i run an a-star search i get this error

*** - NTH: 3 is not a list

Can anyone explain why this is happening, i have been staring at the screen for an hour looking for a syntax mistake but cant find any.
Any help would be greatly appreciated.
Cheers

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: setf and nth problem

Post by ramarren » Tue Sep 28, 2010 10:56 pm

You have not shown enough code to see your problem. You probably at some point pass arguments to NTH in a wrong order, since the system is telling you NTH gets a number where it expects a list. Possibly a number is passed as an argument to one of the functions you have shown.

In any case, you should very rarely use NTH. If you need positional access to a sequence, use an array (PCL chapter).

Also your FIX-THREE function doesn't really make sense anyway, if anything it should be an assertion to check contract conformance, otherwise you would lose or gain "paint" on error, which is unlikely to be a good thing to do. And does A* even make sense for this problem? I don't think there is any useful heuristic for this, which means a simple breadth search with duplication check would be enough.

mickmos
Posts: 2
Joined: Tue Sep 28, 2010 9:14 pm

Re: setf and nth problem

Post by mickmos » Tue Sep 28, 2010 11:23 pm

Hey mate, thanks for the reply, here is the full code.
i cant find anywhere where a number instead of a list is passed as an argument to one of the functions.
and the "fix" functions, while they look strange, seem to work fine.
Any ideas on where i may be using the 'nth' function incorrectly or where the error may be arising from.
Cheers

Code: Select all

(defparameter *start-state* (list 8 0 0))
(defparameter *goal-state* (list 4 4 0))
(defparameter temp 0)

(defparameter *operators*
   '(pour-eight-to-five
     pour-eight-to-three
     pour-five-to-eight
     pour-five-to-three
     pour-three-to-eight
     pour-three-to-five
))

(defun solution-state? (a)
   (if (equalp a *goal-state*) t))

(defun room-in-eight (a)
   (- 8 (nth 0 a)))

(defun room-in-five (a)
   (- 5 (nth 1 a)))

(defun room-in-three (a)
   (- 3 (nth 2 a)))

(defun fix-eight (a)
   (cond ((< (nth 0 a) 0) (setq (nth 0 a) 0))
         ((> (nth 0 a) 8) (setq (nth 0 a) 8))))

(defun fix-five (a)
   (cond ((< (nth 1 a) 0) (setq (nth 1 a) 0))
         ((> (nth 1 a) 5) (setq (nth 1 a) 5))))

(defun fix-three (a)
   (cond ((< (nth 2 a) 0) (setq (nth 2 a) 0))
         ((> (nth 2 a) 3) (setq (nth 2 a) 3))))

(defun pour-eight-to-five (a)
   (setf temp (nth 0 a))
   (setf (nth 0 a) (- (nth 0 a) (room-in-five a)))
   (setf (nth 1 a) (+ (nth 1 a) temp))
   (fix-eight a)
   (fix-five a))

(defun pour-eight-to-three (a)
   (setf temp (nth 0 a))
   (setf (nth 0 a) (- (nth 0 a) (room-in-three a)))
   (setf (nth 2 a) (+ (nth 2 a) temp))
   (fix-eight a)
   (fix-three a))

(defun pour-five-to-eight (a)
   (setf temp (nth 1 a))
   (setf (nth 1 a) (- (nth 1 a) (room-in-eight a)))
   (setf (nth 0 a) (+ (nth 0 a) temp))
   (fix-five a)
   (fix-eight a))

(defun pour-five-to-three (a)
   (setf temp (nth 1 a))
   (setf (nth 1 a) (- (nth 1 a) (room-in-three a)))
   (setf (nth 2 a) (+ (nth 2 a) temp))
   (fix-five a)
   (fix-three a))

(defun pour-three-to-eight (a)
   (setf temp (nth 2 a))
   (setf (nth 2 a) (- (nth 2 a) (room-in-eight a)))
   (setf (nth 0 a) (+ (nth 0 a) temp))
   (fix-three a)
   (fix-eight a))

(defun pour-three-to-five (a)
   (setf temp (nth 2 a))
   (setf (nth 2 a) (- (nth 2 a) (room-in-five a)))
   (setf (nth 1 a) (+ (nth 1 a) temp))
   (fix-three a)
   (fix-five a))
                                                                                                               

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: setf and nth problem

Post by ramarren » Wed Sep 29, 2010 12:50 am

Your not-included search algorithm probably calls one of your operators with a number instead of a list. My guess is you are misusing it, although how badly it is impossible to tell without seeing how it is implemented. Are you aware you are mutating the start state, which means that you have no history and so no backtracking? I would expect the search algorithm to require state transformation operators to generate new states. Instead, your operators mutate the passed state and return some number. Which is probably the source of your problem.

Additionally, why are you using global variable temp? You should use local variables create with LET for this purpose. And for pouring rather than using the 'fix' functions, which if at all work only through properties of modular arithmetic, which I don't understand how it could be easier to reason about, just compute the amount poured (MIN would be useful) and then add and subtract it properly, in which case it will never exceed the bounds.

Post Reply