I think this is going to be a vague question because I don't know exactly what I am doing in the first place but here it goes.
I have to do a towers of hanoi problem in common lisp using lists. Basically a function takes a list of strings (names) and then moves them from peg A to peg C using peg B for storage, keeping them in the same order as they were in the list.
I have never used lisp before and I find the syntax very hard to understand.
This is my code so far
goo function is the hanoi work
(defparameter A '())
(defparameter B '())
(defparameter C '())
(defun findPeg (p1 p2) (cond ((= 0 (- 3 p1 p2))A)
((= 1 (- 3 p1 p2))B) ((= 2 (- 3 p1 p2))C)))
(defun getnum (x) (cond ((equalp x A) 0)((equalp x B)1)((equalp x C) 2)))
(defun hanoi (x) (defparameter A x) (setlength A)(goo len A C B))
(defun setlength(x) (defparameter len (list-length x)))
(defun goo (leng from to via)
(cond ((= leng 1)(push (pop A) C)) ;base case
((goo (1- leng) from via to)(push (pop A) B) ;say/do something i think
((goo (1- leng) via to from)(push (pop B) C) ;say/do something i think
))))
My problem is with the recursive calls. I am very confused as to what exactly I should be doing. I know I obviously have to move the first string in the first list to another peg, but I don't know which peg or even how to manipulate the lists. I feel like I should be using the variables that were passed into the goo function, but I cant figure out how to edit them because when I change them in the function the variables outside do not change.
Right now I am running into the error
* - SYSTEM::%EXPAND-FORM: (GOO (1- LENG) FROM VIA TO) should be a lambda expression
This is a recursive call so I don't know why it is saying that.
Basically I just want some tips or tricks on where do continue or ever where to restart because I don't even know if my approach is a good one.
Anything is greatly appreciated. Thanks
First off, using defparameter inside a DEFUN is almost never the right thing to do.
If you want to have a lexically-scoped variable, use LET (or simply name your formal parameters as you'd like them named).
Second, you have something on the form ((fun arg ..) (fun arg ...)) inside your GOO function. You want to lose the outermost parentheses.
Related
I am new to Racket and functional languages in general. For now I am just trying to prepend items to a list. The concepts are a bit confusing and not sure why my code isn't working.
I am trying to do dot product calculations.
I have a function called "dProduct" that takes 2 lists (A and B) and multiplies each corresponding element in them.
;function takes dot product
(define (dProduct A B)
(define C '()) ; define list to store the multiplied elements
;multiply ea lists elements
(for ([i A] [j B])
(display (* i j)) ;THIS WORKS
(cons (* i j) C) ;APPARENTLY DOESN'T WORK
)
;THIS FOR LOOP DISPLAYS NOTHING
;display the new list "C"
(for ([k C])
(display k)
)
)
I don't understand why I can't use cons to prepend the new multiplied elements to my new list "C". What am I missing? Everything compiles fine. Would like to figure this out so I can finish this function :) Any help would be great. Thanks!
Lists are immutable, and cons does not prepend an element to an existing list. Instead, it produces a new list with the element prepended:
> (define x '(2 3))
> (cons 1 x)
'(1 2 3)
> x
'(2 3)
Since your question is tagged functional-programming, I will assume that you probably want to know how to do this functionally, and functional programming generally discourages mutating values or bindings.
Instead of mutating a binding, you should build up a new structure functionally. The easiest way to do this is to change your use of for to for/list, which produces a list of return values:
(define C
(for/list ([i A] [j B])
(* i j)))
For this program, you could make it even simpler by using the higher-order function map, which acts like a “zip” when provided more than one list argument:
(define C (map * A B))
Since for always returns #<void>, it’s only useful for producing side-effects, and in functional programming, you generally try and keep side-effects to a minimum. For that reason, you will likely find that for/list and for/fold are actually much more commonly useful in idiomatic Racket than plain for is.
Current C list has to be given new value of (cons (* i j) C) and this can be done using set! :
(define (dProduct A B)
(define C '())
(for ([i A] [j B])
(displayln (* i j))
(set! C (cons (* i j) C))) ; NOTE set! HERE.
(for ([k C])
(displayln k)))
Note that the use of set! is strongly discouraged and for/list is much better way to achieve desired result here.
I'm having trouble incorporating a recursive function that squares a number.
Basically I am trying to write a function that keeps calling the Add function x number of times to square it. So if it is 7 it should call it seven times to get 49.
(define (Add a b)
(if (and (number? a) (number? b))
(+ a b)
(lambda (x)
(+ (a x) (b x)))))
(define i 0)
(define ans 0)
(define (Square a)
(when (> i a)
((Add a ans) (+ i 1 ))))
The main issue I'm running into is that the square function only goes through the loop once, I'm not sure why the condition won't update/keep going through the loop till it reaches that condition.
Writing square directly is a big pain. It's much easier to write a recursive multiply function and then just have your square function call multiply. Follow the design recipe for recursion on the natural numbers, as it appears in section 9.3 of HtDP.
By the way, if you haven't already written a bunch of recursive functions on more standard self-referential data definitions (e.g. lists), then, well, I claim that your instructor is doing in wrong.
You should make everything that changes parameters. Imagine you want to make the factorial then two values change. It's the result and the iteration of the number down to zero.
(define (factorial value)
(define (helper cur ans)
(if (zero? cur)
ans ; finished. return the answer
(helper (- cur 1) ; recur by updating n
(* cur ans)))) ; and update the answer
(helper value 1))
Again. It's exactly the same as my example in the comment except it does something else at each step. The basic building blocks are the same and something that would square the argument is very similar.
(define (unknown (lambda (x y)
(cond
((null? y) y)
((x (car y)) (unknown x (cdr y))))
(else (cons (car y) (unknown x (cdr y)))))))
I'm a newbie when it comes to scheme and wanted to know the purpose of this function which I came across in a textbook. My main doubt lies as to what ((x (car y)) does. How does this expression get executed without any operators and yet I don't come across any errors while compiling. Although I'm unable to run the program because the values I input for x are apparently not applicable for the function. Please help.
Scheme functions can take functions as arguments, and can return functions. Your code makes sense if you pass in a function as an argument.
If you call the code like this:
(unknown even? '(1 2 3 4 5))
then it should return the list (1 3 5). This is a filtering function that returns members of y where the result of applying the function x to the member is false.
So I am very new to lisp, and not that advanced of a programmer yet. Just getting started really.
I'm messing around trying to get a very simple genetic algorithm going from scratch, and while most of my code seems to execute as desired, I'm stuck with such a simple bug/misunderstanding that I am blocked from the bottom... There is clearly something I am not getting despite my hours online trying to find a solution..
Basically, I know it has something to do with the fact I am trying to call a variable as if it were an operator (which the variable holds) and thus it tells me my function (which is really just a variable holding an operator) is not defined.
The start of my code works fine.
(defvar *nb* 8)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Returns an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
So (get-operator) does get me one of the four random operators, as desired.
I used this even simpler code to test the structure of my code, and it works as desired.
(defun ga-simple ()
"Returns the value of genome once it matches *nb* and prints
the number of generations required."
(do ((genome (random 10) (random 10))
(generation-counter 1 (incf generation-counter)))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
The problem comes when I try and create a genome composed of three variables, one holding the operator, and the other two, the integers.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
my compiler warnings tell me where the problem is...
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Unused lexical variable OPR1
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Undefined function OPR1/
And so clearly a call to the function (ga-with-operator) says opr1 is an undefined-function-call. So from what I gather when the "do" macro checks the increment condition for the variable genome, it reads the list, expecting opr1 to be an operator and not a variable holding an operator... Now, an operator simply entered works perfect here, but I don't know how to make lisp use the evaluated value of opr1, which is an operator, as the operator for the integers...
To simplify, I made a function trying to construct a single genome using my get-operator function, and failed hard even there lol
(defun get-genome ()
(let ((operator1 (get-operator)))
(operator1 (random 10) (random 10))))
So I made a test-let function to make sure my "let" variable assignment is right...
(defun test-let ()
(let ((rand (get-operator)))
(print rand)))
Which it does... So now I am getting desperate and missing something obviously very simple and yet crucial to make it all stick together.
If someone could explain to me, or just show me, how to get the simple (get-genome) function to work I would really appreciate it. I know lisp expects an operator as the first element in the list, and my error stems from me feeding it a variable holding an operator instead... How do I convince it my variable is the operator it is holding?
in case anyone wants to know the working code...
(defvar *nb* 42)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Return an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (+ 1 (random 9)) (+ 1 (random 9)))))
(defun ga-with-operator ()
(do ((genome (get-genome) (get-genome))
(generation-counter 0 (1+ generation-counter)))
((eql genome *nb*)
(format t "The solution is ~S, and it took ~D generations"
genome generation-counter))))
In Common Lisp you need to use FUNCALL if the function is returned by a function or if the function is stored in a variable.
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (random 10) (random 10))))
Common Lisp has different namespaces for functions and for values. Thus a name can both be a variable and a function:
(defun foo (list)
(list list list))
The first list in the last line calls the global function called list and the second and third are actually the local variable list.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
Above function has more problems.
Can you see the first? Hint: try indenting it correctly. Are the parentheses correct?
also: + is not a function. It is a variable in your code. To make it a function you would need to quote or function quote it. '+ or #'+.
you also don't need to INCF the generation-counter. Just adding 1 is fine. The DO loop updates the variable. Use (1+ generation-counter).
Of course, FUNCALL / APPLY is what you want, but just to complete the picture, note that this also works:
(setf (symbol-function 'operator1) (get-operator))
(operator1 (+ 1 (random 9)) (+ 1 (random 9)))
The reason you generally don't want to do this is that binding of the symbol-function slot is global.
My professor has given us a refresher assignment in clisp. One exercise is to achieve the same thing in three ways: Return a flattened list of all positive integers in a given list.
Now, there's only one way I really like doing this, using cons and recursion, but he wants me to do this using mapcan and a loop (I suspect lisp is not his first choice of language because this style of coding feels extremely resistant to the nature of lisp). I'm having a hard time working out how one would do this using a loop...I need to first start a list, I suppose?
I apologize for vague language as I'm not really sure how to TALK about using a functional language to write procedurally. Following is my first attempt.
(defun posint-loop (l)
(loop for i in l
do (if (listp i)
(posint-loop i)
(if (integerp i)
(if (> i 0)
(append i) ; this doesn't work because there's nothing to
; start appending to!
nil)
nil))))
In order to establish a new lexical binding, use let or the with keyword of loop. In order to extend an existing list, you might want to use push; if you need the original order, you can nreverse the new list finally.
Another way would be to use the when and collect keywords of loop.
Another hint: mapcan implicitly creates a new list.
Mapcan applies a function to each element of a list, expecting the function to return a list, and then concatenates those resulting lists together. To apply it to this problem, you just need to process each element of the toplevel list. If the element is a list, then you need to process it recursively. If it's not, then you either need to return an empty list (which will add no elements to the final result) or a list of just that element (which will add just that element to the final result):
(defun flatten2 (list)
(mapcan (lambda (x)
(cond
((listp x) (flatten2 x))
((and (integerp x) (plusp x)) (list x))
(t '())))
list))
(flatten2 '((a 1 -4) (3 5 c) 42 0))
;=> (1 3 5 42)
With loop, you can do just about the same thing with the recognition that (mapcan f list) is functionally equivalent to (loop for x in list nconc (funcall f x)). With that in mind, we have:
(defun flatten3 (list)
(loop for x in list
nconc (cond
((listp x) (flatten3 x))
((and (integerp x) (plusp x)) (list x))
(t '()))))