a function called A-SUM that calculates Σpi=ni, where n≥0,p≥0. Below are examples of what A-SUM returns considering different arguments - lisp

CL-USER> (a-sum 0 3)
->> 6
I wrote this program :
(defun a-sum (x y)
(if (and (> x -1) (> y -1))
(do ((i 0 (1+ i))
(sum 0)
(num x))
((equal i (+ (- y x) 1)))
(setq sum (+ sum num))
(setq num (+ num 1))
sum)
(print " NOPE")))
put if I run it in the terminal it returns nil and not the answer stated above;
can someone help with the problem so it returns the value then Boolean.

DO,DO* Syntax
The entry for DO,DO* says that the syntax is as follows:
do ({var | (var [init-form [step-form]])}*)
(end-test-form result-form*)
declaration*
{tag | statement}*
The body is used as a list of statements and no intermediate value in this body is used as the result form of the do form. Instead, the do form evaluates as the last expression in result-form*, which defaults to nil.
(do ((i 0 (1+ i))
(sum 0)
(num x))
((equal i (+ (- y x) 1))
;;; RESULT FORMS HERE
)
(setq sum (+ sum num)) ;; (*)
(setq num (+ num 1)) ;; (*)
sum ;; (*)
)
All the expressions marked commented (*) above are used for side-effects only: the result of their evaluation is unused and discarded.
Problem statement
It is not clear to me what Σpi=ni means, and your code does not seem to compute something that could be expressed as that mathematical expression.
One red flag for example is that if (+ (- y x) 1) is negative (i.e. if y < x-1, for example y=1,x=3), then your loop never terminates because i, which is positive or null, will never be equal to the other term which is negative.
I would try to rewrite the problem statement more clearly, and maybe try first a recursive version of your algorithm (whichever is easier to express).
Remarks
Please indent/format your code.
Instead of adding setq statements in the body, try to see if you can define them in the iteration clauses of the loop (since I'm not sure what you are trying to achieve, the following example is only a rewrite of your code):
(do ((i 0 (1+ i))
(sum 0 (+ sum num)
(num x (1+ num))
(... sum))

Consider what value(s) a function returns. It's the value of the last form evaluated. In your case, that appears to be a do or maybe a setq or print (It's difficult to read as it's formatted now, and I don't have question edit privileges).
In short, the form that's returning the value for the function looks to be one evaluated for side-effects instead of returning a value.

Related

how to return the value of a prime number while trying to print the sum of prime numbers in a range of numbers from check-prime to prime-sum

I was working on this question to print the sum of prime numbers in a range of numbers. The range values will be be taken as an input from the user. I got the syntax errors all cleared out but could not figure out how to return the value of the prime no. to the sum if it is true.
(defun check-prime(num)
(if (= num 1) nil)
;(setq i 2)
(loop for i from 2 to ( isqrt num) do
(if (= (mod num i) 0) nil t)
(= i (+ i 1))
)
)
(defun prime-sum(*begin* *end*)
(defvar *s* 0)
(defvar *i* *end*)
(loop for *i* from *end* to *begin* do
;i= 13
(if (check-prime *i*)
(= *s* (+ *s* *i* ) )
)
(= *i* (- *i* 1))
)
(write *s*)
)
(defun vals()
(print "enter the range1: ")
(defvar *begin* (read))
(print "enter the range2: ")
(defvar *end* (read))
(prime-sum *begin* *end*)
)
(print(vals))
;b =4
;e 13
Here is your function, cleaned up a bit and formatted in a conventional way:
(defun check-prime(num)
(if (= num 1) nil)
(loop
for i from 2 to (isqrt num)
do
(if (= (mod num i) 0) nil t)
(= i (+ i 1))))
There are multiple things that are incorrect, and they boil down to how are Lisp forms evaluated.
There is a special form progn in Common Lisp that is used to evaluate a list of expressions, with the following pattern:
(progn E1 E2 ... EN)
A lot of other functions in Lisp are described has having "an implicit progn", that's the case for defun which allows for more than one expression in its body, but since the progn doesn't appear literally it is implicit. The behavior is however always the same: each expression E1 to EN is evaluated in sequence, and evaluation of the whole progn are the values returned by the last expression, EN (that's where the N comes from in the name). In other words, the intermediate values from E1 etc. are discarded, the expressions are only useful for their side-effects.
In your code, that's the case for (if (= num 1) nil), which is an expression in the body of defun which is not the last one, and which doesn't even have side-effects. It is thus completely useless.
Likewise, in the loop macro, all that follows the do keyword are expressions that are evaluated for their side effects and do not contribute to the resulting value of the whole loop form.
In fact, loop is a bit complicated but here your don't have any accumulating clause in your loop (something like collect, append, sum etc. that would compute a result). Instead, your loop will always return nil.
Note also that for i from 2 to (isqrt num) takes care of incrementing i, you don't have to do it yourself like you tried in the do. Moreover, = is a comparison operator, in order to mutate i you would need to use setf instead: (setf i (+ i 1)), or (incf i) (which I repeat is unnecessary here).
To combine the first two expressions, I would write:
(if (= num 1) nil ...)
Where ... is the loop: because if is a functional if, it evaluates to whichever branch is selected by the condition.
And inside the loop, I would use never:
(loop for i from 2 to (isqrt num) never (= 0 (mod num i)))
The never clause makes the loop compute a boolean and halt as soon as the result is false.

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)))))))

LISP : SYSTEM::READ-EVAL-PRINT: variable I has no value

I made a simple test function trying to assign j a value of i by calling (test j 10).
I am getting SYSTEM::READ-EVAL-PRINT: variable J has no value.
(DEFUN test (j i)
(LET ((j i))
(print j)
)
)
I'm unsure if you are aware that the variable j in the let and j defined in the parameters of test are two completely different variables. As a true refactoring would be to rename them so that it is clear, here is your code with that ambiguity removed:
(defun test (pj pi)
(let ((lj pi))
(print lj)))
This is exactly the same code since the new binding in the let effectively makes the old variable with that same name inaccessible for the duration of the let. The warning will be about pj since it is still unused in the function and thus you should consider removing it:
(defun test (pi)
(let ((lj pi))
(print lj)))
Usually having a parameter that is not used is a bug so CL nags about such things. However sometimes you make higher order functions that use functions you pass values. eg.
(defun map-assoc (fn lst)
(loop :for n :from 0
:for (k . v) :in lst
:collect (funcall fn k v n lst)))
Now imagine you want to make a list of just the keys.
(defun assoq-keys (lst)
(map-assoc (lambda (k v n lst)
(declare (ignore v n lst))
k)
lst))
(assoq-keys '((I . 1) (II . 2) (III . 3) (IV . 4) (V . 5)))
; ==> (I II III IV V)
The declare statement will supress the error that the other variables passed will not be used, but you must include them as that is the contract made by the map-assoc function. For a function that takes their values or perhaps swaps other there are other variables you will be using so passing the values is a good generalization.
I think you're misunderstanding how the arguments work. Your test function, in its current form, takes two arguments: j and i. You seem to only use i, so there's no reason to pass a second one. Consider
(defun test (i)
(let ((j i))
(print j)))
Then call it simply as (test 10).

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.

Another Lisp function refinement

I've completed the Graham's exercise Chapter 5.8,and my code is:
(defun max-min (vec &key (start 0) (end (length vec)))
(cond
((eql start (1- end)) (values (elt vec start) (elt vec (1- end))))
((zerop end) (values nil nil))
(t
(multiple-value-bind (x y) (max-min vec :start (1+ start) :end end)
(let* ((maxx x)(minn y))
(values (max maxx (elt vec start)) (min minn (elt vec start))))))))
You don't need to worry about the details, basically it just returns the max and min of a given vector in a "value" form.
I use the above recursion to solve the problem, but my teachers marked my function as "almost done" with such critique:
"If a function takes start and end, then length is neither needed nor correct. Length could be > 0 but it's whether start < end or not that matters. Testing end all by itself is not relevant at all."
I am not very clear at this point, I tried getting rid of the (length vec) default value for "end", but then the default value for end becomes nil.
We have clear instrution that "length" should at most be called once.
Could you please give me some hint on this? Thanks.
Your lambda list is OK. The problem is the base case: (zerop end) should be modified so that you also get a sensible result if called like (min-max myvec :start 5 :end 3).
The next critique is about these two lines:
(multiple-value-bind (x y) (max-min vec :start (1+ start) :end end)
(let* ((maxx x) (minn y))
;; ...
If you want the results of the recursive call to be named maxx and minn, why don't you name them like that directly?
(multiple-value-bind (maxx minn) (max-min vec :start (1+ start) :end end)
;; ...
By the way, you can call them max and min (there are separate namespaces for variables and functions), or max-of-rest and min-of-rest (to be more descriptive).
I don't know some of the lisp features you're using, but it looks to me very much like your teacher is incorrect.
"If a function takes start and end, then length is neither needed nor correct. Length could be 0 but it's whether start < end or not that matters. Testing end all by itself is not relevant at all."
It looks to me like length is the default value for end, and that you are only testing end, not testing length at all... His complaint already appears to be addressed.
That said, there are a other things to complain about in that code. For example, what happens if you call max-min with end < start? It looks to me like you'll recurse by incrementing start, until you run out of vector, then you'll get some kind of exception.