A varaible independent its local scope - lisp

I tried to solve the twoSum Problem with primitive tools of car and cdr
Given an array of integers, return indices of the two numbers such
that they add up to a specific target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
The idea is to take a x from nums, then check if x's complement (target -x) is member of set nums-x
The key logic is
if ((memberp complement (remove-first x nums))
then (list x complement))
Begin with a helper function try nums
(defun two-sum (nums target)
(try nums))
The main function:
(defun try (nums)
(let ((x (car nums))
(complement (- target x)))
(cond
((null x) '())
((memberp complement (remove-first x nums))
(list x complement))
(t (try (cdr nums)))
)))
Then I realize that nums in ((memberp complement (remove-first x nums)) should be stay unchanged and independent from the local scope of let.
How could get such a nums?
memberp and `remove-first'
(defun remove-first (item sequence)
(filter (lambda (x) (not (= x item)))
sequence))
(defun filter (predicate sequence)
(cond ((null sequence) nil)
((funcall predicate (car sequence))
(cons (car sequence)
(filter predicate
(cdr sequence))))
(t (filter predicate
(cdr sequence)))))
(defun memberp(item x)
(cond ((null x) 'false)
((equal item (car x)) x)
(t (memq item (cdr x)))))

Here is a simple recursive function to compute the indexes:
(defun two-sum (list target &optional (pos 0))
(if (null (cdr list))
nil
(let ((p (my-position (- target (car list)) list)))
(if p
(list pos (+ pos p))
(two-sum (cdr list) target (1+ pos))))))
(defun my-position (element list &optional (pos 0))
(cond ((null list) nil)
((eql element (car list)) pos)
(t (my-position element (cdr list) (1+ pos)))))
The function is initially called with the list and the target. The parameter pos, which initially is not passed to the function, is assigned automatically to 0, and in the subsequent calls it will be incremented by one, so that it tracks the index of the current element of the list.
The first condition checks if the list has less than two elements: if it is empty (or its cdr is empty) the result is nil since no solution is possibile (note that in Common Lisp (cdr nil) is nil).
Otherwise we compute the position of the “complement” of the number in the rest of the list (note that position is a primitive function, so I called my-position its rewriting). If the element is present, we return both pos and (+ pos p) (since the position found is relative to the current position), otherwise (my-position returns nil when no element is found) we recur on the rest of the list.
Note that with this method there is no need to consider every time all the elements of the list.

Related

What's the element in position n of a list

I have this function which gives me the element at given position in a list and need to rewrite it with cond instead of if. Also I want to change it a bit so If I give a negative value it returns nil for example
(getn 2 '(a b c)) => (c)
(getn -1 '(a b c)) => nil
The function :
(defun getn (n lst)
(if
(zerop n)
(car lst)
(getn (1- n) (cdr lst)) ) )
I did that but doesn't work :
(defun getn (nb liste)
(cond
((= 0 nb) liste)
(getn (1- n) (cdr liste)) )
Your first version is almost right. Note that when you call getn recursively you are shortening the list, so there will be a point where you are passing nil as the lst argument. You have to check for this condition before anything else and return nil if lst is nil.
cond is like a list of sequential if's. In your case you can write:
(cond ((null lst) nil)
((< n 0) nil)
((= n 0) (car lst))
...
)
(defun getn (n lst)
(cond ((or (null lst) (< n 0)) nil)
((= n 0) (car lst))
(t (getn (- n 1) (cdr lst)))))
For the case, that the nth element of the list is itself nil,
in lisp often one sends additional information. A second value, which is t,
if an element was found, and nil if no element was found.
So nil; t means the nth element was nil, while nil; nil means no element
was found.
(defun getn (n lst)
(cond ((or (null lst) (< n 0)) (values nil nil))
((= n 0) (values (car lst) t))
(t (getn (- n 1) (cdr lst)))))
[8]> (getn 1 '(1 nil 3))
NIL ;
T
;; an element was found -> T as second value, and the element was `nil`
[9]> (getn 1 '(1))
NIL ;
NIL
;; no element was found -> nil as second value, and therefore first value is also `nil`.
A very good book to learn recursive thinking and programming in lisp is The little schemer or the older version the little lisper. I learned through it thinking recursively.

Lisp function count recurring a's in list

I am trying to write a function that takes only a list as a parameter and counts the number of times the symbol a appears in the list, without counting any a's in a sublist within the list.
I am very new to Lisp so please use as basic code as possible so I could understand what it is doing, even if it is inefficient.
(defun times (l)
(setf x 'a)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x(cdr l)))))
So (times '(a b (a) c)) should return 1. However I am getting the error that with this line times is getting two arguments when it should be getting one.
There are multiple ways to implement this in Common Lisp. The example should be small enough for you to follow (test them).
Recursive implementation
Your approach is fine, except you have small errors (in addition to the other ones reported in comments):
Do not use SETF for undeclarded variables.
Do not return NIL in the base case: your function should return a number.
Also, your code coud be better formatted, and you should use longer names (lowercase l in particular is hard to read)
Here is a modified version:
(defun times (list element)
(cond
((null list) 0)
((equal (car list) element) (1+ (times (cdr list) element)))
(t (times (cdr list) element))))
Example
Let's TRACE the function:
CL-USER> (trace times)
Here is the execution trace:
CL-USER> (times '(a b c d a f a) 'a)
0: (TIMES (A B C D A F A) A)
1: (TIMES (B C D A F A) A)
2: (TIMES (C D A F A) A)
3: (TIMES (D A F A) A)
4: (TIMES (A F A) A)
5: (TIMES (F A) A)
6: (TIMES (A) A)
7: (TIMES NIL A)
7: TIMES returned 0
6: TIMES returned 1
5: TIMES returned 1
4: TIMES returned 2
3: TIMES returned 2
2: TIMES returned 2
1: TIMES returned 2
0: TIMES returned 3
3
You can see that the call stack grows for each and every element visited in the list. It is usually a bad practice, especially when the recursive function is basically implementing a loop.
Loops
Use a simple LOOP:
(defun times (list element)
(loop for value in list count (equal value element)))
Alternatively, use DOLIST:
(defun times (list element)
(let ((counter 0))
(dolist (value list counter)
(when (equal element value)
(incf counter)))))
Here above, counter is a local variable introduced by LET. It is incremented with INCF inside the loop, only WHEN the comparison holds. Finally, counter is returned from the dolist (the third parameter indicates which form to evaluate to have the result value). The return value of dolist is also the return value of the let and the whole function.
This can be rewritten also with DO:
(defun times (list element)
(do ((counter 0)) ((null list) counter)
(when (equal element (pop list))
(incf counter))))
The first list in do introduces bindings, the second list is a termination test (here we stop when the list is empty) followed by a result form (here, the counter). Inside the body of the loop, we POP elements from the input list and do the comparison, as before.
Tail-recursive implementation
If you want to keep a recursive implementation, add an accumulator and compute all the intermediate results before entering a recursive evaluation. If all results are passed as function arguments, there is no need to keep track of intermediate results at each step of the recursion, which eliminates the need to even allocate stack frames. The ability to perform tail-call elimination is not expressly required by the specification of the language, but it is typically available in most implementations.
(defun times (list element)
(labels ((recurse (list counter)
(cond
((null list) counter)
((equal (first list) element)
(recurse (rest list) (1+ counter)))
(t (recurse (rest list) counter)))))
(recurse list 0)))
Here above, recurse is a local recursive function introduced by LABELS, which accepts a counter parameter. The difference with the original recursive function is that when the list is empty, it returns the current value of counter instead of zero. Here, the result of recurse is always the same as the value returned by recursive invocations: the compiler can just rebind inputs and perform a jump instead of allocating intermediate frames.
Higher-order functions
Here are yet two other ways, based on higher-order functions.
First, the usual way to define functions with accumulators is with REDUCE (known as fold in other languages). There is no explicit mutation:
(defun times (list element)
(reduce (lambda (counter value)
(if (equal value element)
(1+ counter)
counter))
list
:initial-value 0))
The anonymous function accepts the current state of the accumulator, the current value being visited in the list, and shall compute the next state of the accumulator (the counter).
Alternatively, call MAP with a nil first argument, so that the iteration is only done for effects. The anonymous function established by the LAMBDA form closes over the local counter variable, and can increment it when comparison holds. It is similar to the previous dolist example w.r.t. incrementing the counter through side-effects, but the iteration is done implicitly with map.
(defun times (list element)
(let ((counter 0))
(map ()
(lambda (value)
(when (equal value element)
(incf counter)))
list)
counter))
Built-in
For your information, there is a built-in COUNT function:
(defun times (list element)
(count element list :test #'equal))
Here is some code which might help. It uses tail recursion and defines a helper function which is called recursively and keeps track of the number of times the symbol 'a appears with the argument count. The helper function takes two arguments, but the functino count-a takes one. Count-a calls the helper with the list l and the total number of times it has counted the symbol 'a at the beginning, which is zero to kick off the recursive calls.
(defun count-a (l)
(labels ((helper (x count)
(if (equalp 'a (car x)) (incf count))
(cond ((null x) count)
(t (helper (cdr x) count)))))
(helper l 0)))
You can also use the loop macro:
(defun count-a-with-a-loop (l)
(loop for i in l count (equalp 'a i))\
Or as Coredump points out:
(defun count-a-with-count (l)
(count 'a l :test #'equal))
Note the '# character before equal lets the Lisp interpreter know that equal is a function, known as a reader macro.
If you use a Lisp compiler (like SBCL) you might see this:
* (defun times (l)
(setf x 'a)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x(cdr l)))))
; in: DEFUN TIMES
; (TIMES X (CDR L))
;
; caught WARNING:
; The function was called with two arguments, but wants exactly one.
;
; caught WARNING:
; The function was called with two arguments, but wants exactly one.
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 3 WARNING conditions
The Lisp compiler tells you that there are three errors in your code.
Let's fix the undefined variable problem first, by introducing a local variable x:
(defun times (l)
(let ((x 'a))
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l))))))
Now, we look at the other two: you call TIMES with two arguments.
We can just remove the x argument, since it is not needed:
(defun times (l)
(let ((x 'a))
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times (cdr L))))
(t (times (cdr l))))))
It may be more useful to be able to search for more things, so we add x to the argument list and add it to the call arguments.
(defun times (x l)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l)))))
Now the function should always return a number, not NIL for an empty list:
(defun times (x l)
(cond
((null l) 0)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l)))))
Since Lisp has functions like first and rest, we can replace car and cdr:
(defun times (x l)
(cond
((null l) 0)
((equal x (first l)) (+ 1 (times x (rest l))))
(t (times x (rest l)))))

Write a function COUNT-NUMBERS that counts the number of numbers in a list

I'm begginer at LISP, and I have a question need your help.
Write a function COUNT-NUMBERS that counts the number of numbers in a list,and return " NO NUMBER" if there is no number in the list
For example, for a list: (A 2.3 B C 4 5), it returns 3.
I've tried with the following code, but it doesn't work . Could you help me to figure out? Moreover, I don't know how to return "NO NUMBER" if there is no number in the list.
(defun count-numbers (x)
(cond ((null x) 0)
((numberp x) 1)
(t (+(count-numbers (car x))(count-numbers (cdr x))))))
Thanks in advance,
You could to define a inner helper function to do the counting, and check the result to decide what to return in the main function:
(defun number-counter (lst)
(labels ((do-count (l)
(cond ((null l) 0)
((numberp (car l)) (+ 1 (do-count (cdr l))))
(t (do-count (cdr l))))))
(let ((r (do-count lst)))
(if (= r 0) 'NO-NUMBER r))))
This would be a tail-recursive version. Somehow you have to check what to return.
(defun count-numbers (list &optional (n 'no-number))
(cond ((null list) n)
((numberp (first list))
(count-numbers (rest list)
(if (eq n 'no-number)
1
(1+ n))))
(t (count-numbers (rest list) n))))
With a LOOP you can write that this way:
(defun count-numbers (list)
(loop for element in list
count (numberp element) into n
finally (return (if (zerop n) 'no-number n))))

Cannot do sum in lisp with do loop

(defun suma (L)
(setq var 0)
(do
((i 0 (+ i 1)))
((= i (length L)))
(+ var (nth i L)))
var)
Why does it always returns 0?
Shouldn't it return sum of list L?
+ does not modify its arguments, so, since you never modify var, its initial value of 0 is returned.
You need to replace (+ var (nth i L)) with (incf var (nth i L)), of, equivalently, (setq var (+ var (nth i L))).
See incf.
Note that you should bind var with let instead of making it global with setq.
Most importantly, note that your algorithm is quadratic in the length of the list argument (because nth scans your list every time from the start).
Here are some better implementations:
(defun sum-1 (l)
(reduce #'+ l))
(defun sum-2 (l)
(loop for x in l sum x))
(defun sum-3 (l)
(let ((sum 0))
(dolist (x l sum)
(incf sum x))))
Here is a bad implementation:
(defun sum-4 (l)
(apply #'+ l))
The problem with sum-4 is that it will fail if the length of the supplied list is larger than call-arguments-limit.
I thought this would be a comment for the full learning experience, but I was not able to put code in the comment.
There is a way to do sums without modifying any argument, and that is by doing it recursively:
(defun recsum (list)
(if list
(+ (first list) (recsum (rest list)))
0))
This version can be tail call optimized by the compiler, and as fast as a loop:
(defun recsum2 (list &optional (accumulator 0))
(if list
(recsum2 (rest list) (+ accumulator (first list)))
accumulator))
What you are trying to do could be done with do like this:
(defun suma (l)
(do
((var 0)
(i 0 (+ i 1)))
((= i (length l)) var)
(incf var (nth i l))))
But we don't usually do anything in dos body, so it's like this then:
(defun suma (l)
(do
((i 0 (+ i 1))
(var 0 (+ var (nth i l))))
((= i (length l)) var)))
But nth and length are slow, so better do it this way:
(defun suma (l)
(do*
((var (first l) (+ var (first list)))
(list (rest l) (rest list)))
((null list) var)))
This one is without the * in do, and returns 0 on empty list:
(defun suma (l)
(do
((acc 0 (+ acc (first list)))
(list l (rest list)))
((null list) acc)))
But my favorite is the reduce version from #sds which also can return 0 on empty list with :initial-value 0
EDIT: recsum2 did not return anything, so it needed a fix.

Return element of list as integer in Lisp

I'm supposed to write a function that will take in a list, extract the ID number from the list, and then return it as an integer (not a list).
My first function was pretty simple:
(defun idReturn2 (l) (if (eq (car l) '(ID)) (cadr l) (idReturn list)))
Which I called with the function:
(idReturn2 '((name (light bulb)) (mfgr ge) (watts 60) (id 357) (quantity 6)))
The method is supposed to return 357, but instead returns (357). It's the right number to return, but it's part of a list, which my professor outright told us not to do.
I noticed that my quadratic equation function only returned an integer without the parentheses, so I thought I could parse the integer using parse-integer:
(defun idReturn2 (l) (if (eq (car l) '(ID)) (parse-integer (cadr l)) (idReturn list)))
Still returns (357). I've gone over my lisp notes a dozen times, as well as the slides, and I can see absolutely no way to pull the data out of the list. Could anyone offer me some guidance?
So you have a list ((property-name1 value1) (property-name2 value2) ...) if that list is given as argument l then (car l) isn't (property-name1) but (property-name1 value1). Luckily you see that the symbol you should check is in the results first element and that means you should use (car (car l)) or (caar l) for short. (eq (caar l) 'property-name1) ; ==> t
Notice that when you don't find it in the first iteration you call a totally different function IdReturn, not with the rest of l but a different variable list (whatever that is). You haven't supplied it so I cannot tell how you get (357) but it's not from functions supplied in your question.
PS: Any list (a) (a b) or (a b c) you pull the first value with car. (car '(357)) ;==> 357
Maybe it's less confusing if you use the first, second and rest functions:
(defun idReturn (l)
(when l
(let ((c (first l)))
(if (eq (first c) 'id)
(second c)
(idReturn (rest l))))))
which is the same as
(defun idReturn (l)
(when l
(let ((c (car l)))
(if (eq (car c) 'id)
(cadr c)
(idReturn (cdr l))))))
then
? (idReturn '((name (light bulb)) (mfgr ge) (watts 60) (id 357) (quantity 6)))
357
? (idReturn '((name (light bulb)) (mfgr ge) (watts 60) (idx 357) (quantity 6)))
NIL
Note that, using assoc, you can simplify the function to
(defun idReturn (l)
(second (assoc 'id l)))