I can't solve Tower of Hanoi on Lisp - lisp

I know the algorithm :
(defun Hanoi (n) (if (= n 1) 1 (+ (* 2 Hanoi(- n 1)) 1)))
However, CLISP said
*** - IF: variable HANOI has no value
How could I tweak this? I can't find out the problem.

Here is your code:
(defun Hanoi (n)
(if (= n 1)
1
(+ (* 2 Hanoi (- n 1))
1)))
The error says:
*** - IF: variable HANOI has no value
So, inside the IF you are making a reference to HANOI as a variable, and there is no such variable currently bound at this point. If we look closely, we can see the following expression:
(* 2 Hanoi (- n 1))
This expressions is the application of function * to 3 arguments, namely 2, Hanoi and (- n 1). The second argument, Hanoi, stands for a variable. But there is no such variable defined here (for example, with a let). You are supposed to call the funtion #'Hanoi using the same syntax as you did for multiplication or addition, which is: wrap the function's name in parentheses along with its arguments:
(hanoi (- n 1))
See https://common-lisp.net/documentation for resources about Common Lisp.

You don't call functions as f(x) in Lisp, you call them as (f x) So your recursive call to hanoi needs to be (hanoi (- n 1)).

Related

Unused Lexical Variable

Just started learning lisp. I have no idea why I am getting these errors or even what they mean. I am simply trying to code an approximation of pi using the Gregory-Leibniz series, here is the code.
(defun gl (n)
(defparameter x 0) ;init variable to hold our runnning sum
(loop for y from 0 to n ;number of iterations, starting from 0 to desired n
(if (= y 0) ;if n is 0 then we just want 4
(defparameter w 4))
(if (> y 0) ;else, 4*(-1^y)/((2 * y)+1)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w)) ;add to our running sum
(write x)) ;once loop is over, print x.
I have tried using setq, defvar, let etc. instead of defparameter but I still get "Undeclared free variable X".
I also get the error "Unused lexical variable N" even though I am using it for my loop, which is weird also.
How can I fix this and why is it happening? Thanks!
Here is the code after Emacs auto-indented it:
(defun gl (n)
(defparameter x 0)
(loop for y from 0 to n
(if (= y 0)
(defparameter w 4))
(if (> y 0)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w))
(write x))
Compiling the following code with SBCL gives one error and two warnings.
One warning says that x is undefined.
You should not call defparameter from inside your function, since defvar and defparameter are used to declare dynamic variables and to set their value in the global scope. Prefer to have let bindings, or, since you already are using a loop, a with clause. When you want to modify a binding, use setf.
The errors comes from the macroexpansion of LOOP, which is malformed. For SBCL, that means that the code is treated as dead-code for the rest of the function compilation; that explains why n appears not to be used, which is what the second warning is about.
There are various fixes remaining to be done:
Use function EXPT, not EXP.
Calling (+ x w) only computes a value but does not modify x, the result is useless.
Prefer using if as expression, like a ternary operator in other languages, in your case the code can be simplified
Adding one can be done with function 1+ (that's the name of the function, not a special syntax for adding constants)
The write operation is rarely needed, especially if you are computing a mathematical formula; just return the value, and the REPL will print it automatically.
Small corrections that make your code works:
(defun gl (n)
(let ((x 0))
(loop
for y from 0 to n
for w = (if (= y 0)
4
(* 4 (/ (expt -1 y) (+ (* 2 y) 1))))
do (setf x (+ x w)))
(write x)))
I would personally get rid of x and w, and use a SUM loop clause.
(defun gl (n)
(loop
for y from 0 to n
sum (if (zerop y)
4
(* 4 (/ (expt -1 y)
(1+ (* 2 y)))))))

Sum numbers that are positive which is less than n

(defun sum (n)
(if (n<0) 0 n-1) ;; if n<0, add 0. Else add the next smallest.
(sum (n-1)))
So far I come out with something like this but I am not sure how do I declare a variable to store the sum that I would like to return.
Note that you are implementing 1+2+...+m for m = n-1, which admits a simple formula:
(lambda (n)
;; You could inject n-1 on the formula to get n.(n-1)/2
;; (like in Vatine's answer), but here I just decrement
;; the input to show how to modify the local variable
;; and reuse the formula linked above to sum up-to m.
(decf n)
(if (minusp n)
0
(/ (* n (1+ n)) 2)))
An iterative version would work too, there is no need go recursive when doing simple loops:
(lambda (n) (loop :for x :below n :sum x))
Regarding your code:
Space matters1: n<0 is read as a symbol of name "N<0" (upcased by default). The same goes for n-1 which is a symbol named "N-1".
(n<0) will attempt to run the function named n<0. The same goes for (n-1).
Comparison: you can use (minusp n) or (< n 0).
Decrement: you can use (1- n) or (- n 1).
If what you wrote was correctly written, like this:
(defun sum (n)
(if (< n 0) 0 (- n 1))
(sum (- n 1)))
... there would still be issues:
You expect your (n-1) to actually decrement n but here the if only compute a value without doing side-effects.
You unconditionally call (sum (n-1)), which means: infinite recursion. The value returned by the preceding if is always ignored.
1: For details, look at constituent and terminating characters: 2.1.4 Character Syntax Types
Edit: zerop > minusp to check for negative numbers, fixed to fit OPs question
Was some time ago I used Lisp but if I recall right the last evaluation gets returned. A recursive solution to your problem would look like this:
(defun sum (n)
(if (<= n 0) 0 ;;if n is less or equal than 0 return 0
(+ (- n 1) (sum (- n 1))))) ;; else add (n-1) to sum of (n-1)
In Lisp, all comparator functions are just that, functions, so it needs to be (< n 0) and (- n 1) (or, more succinct, (1- n)).
You don't need to keep an intermediate value, you can simply add things up as you go. However, this is complicated by the fact that you are summing to "less than n", not "to n", so you need to use a helper function, if you want to do this recursively.
Even better, if you peruse the standard (easily available on-line, as the Common Lisp HyperSpec, you will sooner or later come across the chapter on iteration, where the loop facility does everything you want.
So if I needed to do this, I would do one of:
(defun my-sum (n)
(/ (* n (1- n)) 2))
or
(defun my-sum (n)
(loop for i below n
sum i))
If I absolutely needed to make it recursive, I would use something like:
(defun my-sum (n)
(labels ((sum-inner (i)
(if (< i 1)
0
(+ i (sum-inner (1- i))))))
(sum-inner (1- n))))
This is (almost) identical to defining a global function called sum-inner, which may be preferable for debugging purposes. However, since it is very unlikely that sum-inner would have any other use, I made it local.

Lisp Sum of power

Define a function "power" that takes two input arguments m and n, and returns m^n. Then, by using the function "power", define a function sum_power that takes two input arguments m and n and returns the sum: (1^n + 2^n + 3^n +.... + m^n).
int first function i calculate power from given arguments in second function a sum powers. But program gives error: Program stack overflow. RESET...
I cant find my error. Function power is correct I checked.
(defun power(m n)
(let ((result 1))
(dotimes (count n result)
(setf result (* m result)))))
(defun sum_power (m n)
(if (= 0 m)
0
(+ (powern m)
(sum_power (1- m) n))))
Ok the problem is your function sum_power when you pass the variable m
the expression (- 1 m) is an infinite loop first time because is for example
for m = 5 first time (- 1 m) => -4 (new m = -4) second time (- 1 m)
=> 5 (new m = 5)
begin again so is a recusive infinite loop, you never arrive to 1 so this is teh case of the overflow
Use instead the build function (1- m) which decreases the value of m, or (- m 1) if you want
So the new funtion will be like this, also this is no tail recursion so for big m and n it will take a lot of time, but for your needs it should work, and this function is better formated, please take of fromatting when writing lisp functions for easy reading
(defun sum_power (m n)
(if (= 1 m)
1
(+ (power n m) (sum_power (1- m) n))
You have a argument order mistake in your sum_power function. The stand lisp function - when given two arguments subtracts the second argument from the first argument that is (- 1 m) will subtract m from one and NOT 1 from m as you probably expected thus your result will be a negative integer and your base case (= 1 m) will never be reached. For you code to work correctly you have to swap the arguments to - thus (- m 1) or you can user the lisp function 1- (1- m) which subtracts one from its only argument thus a corrected version of your code is as follows:
(defun sum_power (m n)
(if (= 1 m)
1
(+ (power m n) (sum_power (1- m) n))))
On a non-related side-note lisp allows a lot more characters in function, variable and macro names than most other languages thus you can use sum-power instead of sum_power, in-fact it is arguably better lisp style to use hyphens to join multiple-word identifier names rather than underscores (as used in C) or camel-back casing (sumPower as used in Java). Secondly closing parenthesis usually are not written on a separate line but are on the same line as the last expression before the closing parentheses, as I have done above in the corrected version. These are merely conventions you may follow them if you wish but you're not obliged to.
Why you don't use higher-order functions and loop macro? I think is more readable that way:
(defun power (n m)
(reduce #'* (loop for x below n collect m))
(defun sum-power (n m)
(reduce #'+ (loop for x from 1 to m collect (power x n)))

if: Bad syntax error (Scheme programming)

(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1))))))
This program is designed to take a number and a function as inputs and do the following..
f(1) + f(2) + f(3)+ … + f(N).
An example input would be:
(generalized-triangular square 3)
The Error message:
if: bad syntax;
has 4 parts after keyword in: (if (= n 1) 1 (+ (input n) (generalized-triangular (- n 1))) input)
The error is quite explicit - an if form can only have two parts after the condition - the consequent (if the condition is true) and the alternative (if the condition is false). Perhaps you meant this?
(if (= n 1)
1
(+ (input n) (generalized-triangular input (- n 1))))
I moved the input from the original code, it was in the wrong place, as the call to generalized-triangular expects two arguments, in the right order.
For the record: if you need to execute more than one expression in either the consequent or the alternative (which is not the case for your question, but it's useful to know about it), then you must pack them in a begin, for example:
(if <condition> ; condition
(begin ; consequent
<expression1>
<expression2>)
(begin ; alternative
<expression3>
<expression4>))
Alternatively, you could use a cond, which has an implicit begin:
(cond (<condition> ; condition
<expression1> ; consequent
<expression2>)
(else ; alternative
<expression3>
<expression4>))
Literal answer
The code you posted in your question is fine:
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1))))))
The error message in your question would be for something like this code:
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1)))
input)))
The problem is input. if is of the form (if <cond> <then> <else>). Not counting if itself, it has 3 parts. The code above supplies 4.
Real answer
Two tips:
Use DrRacket to write your code, and let it help you with the indenting. I couldn't make any sense of your original code. (Even after someone edited it for you, the indentation was a bit wonky making it still difficult to parse mentally.)
I don't know about your class, but for "real" Racket code I'd recommend using cond instead of if. Racket has an informal style guide that recommends this, too.
here's the tail-recursive
(define (generalized-triangular f n-max)
(let loop ((n 1) (sum 0))
(if (> n n-max)
0
(loop (+ n 1) (+ sum (f n))))))
Since you're using the racket tag, I assume the implementation of generalized-triangular is not required to use only standard Scheme. In that case, a very concise and efficient version (that doesn't use if at all) can be written with the racket language:
(define (generalized-triangular f n)
(for/sum ([i n]) (f (+ i 1))))
There are two things necessary to understand beyond standard Scheme to understand this definition that you can easily look up in the Racket Reference: how for/sum works and how a non-negative integer behaves when used as a sequence.

Simple LISP function not working

I decided to learn LISP today, and have been playing around with it for a bit. I wrote a simple baby function just to test my understanding, and now understand that my understanding doesn't understand as much as I had understood it to understand. :D
Anyway, here is the function. The idea is that when it is called, e.g. (esexp base x) it should return the value base^x. So (esexp 3 4) = 3^4 = 81.
(I am using the CMU implementation of Common Lisp, if that matters.)
(defun esexp (base x)
(if (= x 0)
1
(if (< x 0)
(/ esexp (base (+ x 1)) base)
(* esexp (base (+ x 1)) base))))
This doesn't work. I get errors that look like (Warning: This variable is undefined: SLBEXP) and (Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable SLBEXP is unbound.) So. What am I doing wrong? AND would there be a better (or more LISP-ish way) to write this function?
ETA
Corrected code:
(defun esexp (base x)
(if (= x 0)
1
(if (< x 0)
(/ (esexp base (+ x 1)) base)
(* (esexp base (- x 1)) base))))
esexp(base (+ x 1))
should be
(esexp base (+ x 1))
esexp is a function just like +. The syntax for invoking a function is
(function-name arg1 arg2 ...)
The technical explanation of the error: the compiler was parsing the code:
(/ esexp(base (+ x 1)) base)
as this:
(/ esexp (base (+ x 1)) base)
which says:
first, add 1 to the parameter x
then, invoke a function called base with the result above.
divide the value of a variable called esexp by the result above.
then, divide that result by the parameter base. (The divide operator in Common Lisp can take more than two arguments.)
You see the trick? When a word appears as the first item in a s-expression (and that s-expression isn't quoted), it's usually treated as the name of a function you want to invoke. Otherwise, it's treated as the name of a variable whose value you want to retrieve. Further, in Common Lisp a symbol like esexp can be bound to both a function value and a variable value at the same time; context or special expressions like #'esexp (which means the function) are used to figure out which one you mean.
The compiler was telling you that, though esexp was bound to a function with your defun statement, it had not yet been bound to a variable value, and therefore could not be used as such. Hence, the error.
Just a note about the code. I believe it should be
(defun esexp (base x)
(if (= x 0)
1
(if (< x 0)
(/ (esexp(base (+ x 1)) base))
(* (esexp(base (- x 1)) base))))
Otherwise the function will never terminate. (you had (* (esexp(base (+ x 1)) base)))))