How to get dotted pairs in Lisp? - list

I've searched google and other places for a while but I can't find out how to generate or create dotted pairs. I ask this because, I need to turn a list that looks like this:
(X Y Z)
To a list that is in this format:
((X . 1) (Y . 2) (Z . 3))
Where the numbers represent the index. I have a function that turns the list into the format of
(X 1 Y 2 Z 3)
Here is that function:
(defun listFormat (l)
(defun place-index (idx l)
(if (null l)
nil
(append (list (first l)) (list idx)
(place-index (+ idx 1) (rest l)))))
(place-index 1 l))
But I'm not sure how to get dotted pairs.
Thanks in advance

Your code has a very basic mistake:
(defun listFormat (l)
(defun place-index (idx l) ; <<<---- This DEFUN is wrong
(if (null l)
nil
(append (list (first l)) (list idx)
(place-index (+ idx 1) (rest l)))))
(place-index 1 l))
Don't nest DEFUN. That's just wrong. DEFUN defines a global function. Whenever you run listFormat, it redefines the GLOBAL function PLACE-INDEX. You may have seen similarly nested functions in SCHEME using DEFINE. In Common Lisp you should not use DEFUN for a nested local function.
In Lisp local functions are defined with FLET or LABELS (for recursive functions).
(defun listFormat (l)
(labels ((place-index (idx l)
(if (null l)
nil
(append (list (first l)) (list idx)
(place-index (+ idx 1) (rest l))))))
(place-index 1 l)))
Also Stackoverflow is the wrong place to solve your homework. Google searches is also the wrong way to learn Lisp programming.
I propose to use the good old way of reading an introductory book and using a reference.
Here is a basic introductory Lisp book for download: Common Lisp: A Gentle Introduction to Symbolic Computation.
Reference sheets: a small Common Lisp Quick Reference (PDF) and a more detailed Common Lisp Quick Reference.
Dotted pairs are called conses in Lisp.
See the real online reference for Common Lisp, the Common Lisp HyperSpec.

You want the else-branch to read:
(cons (cons (first l) idx) (place-index (+ idx 1) (rest l)))

And by the way, for the question itself, this code will do:
(defun listFormat (lst)
(loop for idx from 1
for item in lst
collect (cons item idx)))

Related

How to transform a list into a set in LISP?

I have been trying to transform a linear list into a set but with no avail. Everytime I run this, I get some weird compilation errors like "badly formed lambda" which points to the way I use append. Here is my code:
(defun mem(e l)
(cond
((null l) nil)
((equal e (car l)) t)
((listp (car l)) (mem e (car l)))
(t(mem e (cdr l)))
)
)
(defun st(l k)
(cond
((null l) nil)
(( mem '(car l) 'k) (st (cdr l) k))
((listp (car l)) (st (car l) k))
( t (st (cdr l) (append((car l) k)) ))
(t(mem e (cdr l)))
)
)
EDIT: frankly I just want to remove the duplicates from list l
Prefer Standard Library Functions
EDIT: frankly I just want to remove the duplicates from list l
Common Lisp has a remove-duplicates function. The documentation inclues examples:
Examples:
(remove-duplicates "aBcDAbCd" :test #'char-equal :from-end t) => "aBcD"
(remove-duplicates '(a b c b d d e)) => (A C B D E)
(remove-duplicates '(a b c b d d e) :from-end t) => (A B C D E)
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr) => ((BAR #\%) (BAZ #\A))
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr :from-end t) => ((FOO #\a) (BAR #\%))
Are you trying to flatten the list too?
From your code for mem, where you do:
((listp (car l)) (mem e (car l)))
it looks like you want your member function to also recurse into sublists. That's a bit questionable, even when working with sets, since sets can traditionally include other sets. E.g., {{3},{4},5} is a set containing 5, the set {3}, and the set {4}. It's not the same as the set {3,4,5}. Your st function also looks like it's trying to recurse into lists, which makes it seem like you want to flatten you lists, too. Again, that's a bit questionable, but if you want to do that, then your conversion to a set would be easier as a "flatten, then remove duplicates" process:
(defun flatten (list)
"Returns a fresh list containing the leaf elements of LIST."
(if (listp list)
(mapcan 'flatten list)
(list list)))
;; CL-USER> (flatten '(1 2 (3 4) 5 ((6))))
;; (1 2 3 4 5 6)
(defun to-set (list)
"Returns a set based on the elements of LIST. The result
is a flat list containing the leaf elements of LIST, but
with any duplicate elements removed."
(delete-duplicates (flatten list)))
;; CL-USER> (to-set '(1 3 (3 4) ((4) 5)))
;; (1 3 4 5)
Notes
I get some weird compilation errors like "badly formed lambda" which points to the way I use append.
Yes, you're trying to call append like: (append((car l) k)). That's actually not a problem for append. Remember, the syntax for a function call in Lisp is (function argument…). That means that you've got:
(append ((car l) k))
<function> <argument1>
But your argument1 is also a function call:
((car l) k )
<function> <argument1>
In Common Lisp, you can't use (car l) as a function. The only thing that can appear for a function is a symbol (e.g., car, append) or a lambda expression (e.g., (lambda (x) (+ x 1)).
You want to call (append (car l) k) instead.
First, CL does not have a set data type.
Lists, however, can be used as sets, you do not need to write any special code for that.
Second, I don't understand what your st function is supposed to do, but I bet that in the second cond clause you should not quote (car l) and k. You should use meaningful names for your functions and avoid abbreviations. As per your explanation in the comment, you should use pushnew instead.
Third, your mem function is quite weird, I am pretty sure you do not mean what you wrote: e is searched along a path in the tree l, not in the list l. As per your explanation in the comment, you should check both car and cdr:
(defun tree-member (tree element &key (test #'eql))
(if (consp tree)
(or (tree-member (car tree) element :test test)
(tree-member (cdr tree) element :test test))
(funcall test element tree)))

Abstract List Functions in Racket/Scheme - Num of element occurrences in list

So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.

constuct mixed list

Hi everyone I am trying to construct a mixed list with letters and numbers. For example when you call the funciton (inc-list1 '(cat 4 dog 3 x 5)) => (cat 5 dog 4 x 6). I am pretty sure the logic is right, so i think i am missing something from the syntax. Here is my code
(defun inc-list1 (list)
(cond ((null list)
nil
)
(numberp (first list)
(cons ( + 1 (first list)) (inc-list1 (rest list)))
)
(T
cons (first list) (inc-list1 (rest list))
)
)
)
An example of how you could have approached the problem:
(defun mapcar-if (list test if-true &optional (otherwise #'identity))
(mapcar
#'(lambda (x)
(funcall
(if (funcall test x)
if-true
otherwise) x)) list))
(mapcar-if '(cat 4 dog 3 x 5) #'numberp #'1+)
Which would make the function a little bit more useful in other situations too.
Your code:
(T cons ...) doesn't do what you think it does. You probably wanted to call cons rather then simply mention it. Mentioning it in the way you did has no effect and no side effect (it would have side effect, if the symbol cons was unbound - i.e. you'd receive an error). Whatever happens next is the result of the previous error. Calling (first list) has no side effect too (in your case).
"Consing" the list in the way you did isn't a particularly good technique. Because this technique is already implemented in other functions (like mapcar, reduce etc.) They were written with the purpose in mind to reduce the amount of text you have to type to write a program, and to make it easier to read, once you have written it. ;)
There are various typos in your code. Here is a fixed version
(defun inc-list1 (list)
(cond ((null list)
nil
)
((numberp (first list))
(cons ( + 1 (first list)) (inc-list1 (rest list)))
)
(t
(cons (first list) (inc-list1 (rest list)))
)
)
)
Note the added parens around the numberp and cons function calls and the t in lower case.

transform M dimensional list in one dimension

I'm new in scheme programming and I'm learning basic algorithms, like how to define map, append and so on.
But there is an algorithm for which I can't find an implementation. I speak about transforming an M-dimensional list into one dimension. I tried to define it by myself, but without success.
What exactly I want:
'(a b c (d (e)) (g f h)) => '(a b c d e g f h)
I think the term you want to search for is "Flatten". The simplest way to write it is this: if it's not a list, then return a list of length one containing it. If it is a list, then apply append to the result of mapping a recursive call over its elements.
There are a couple of ways to flatten a list. First, a straightforward solution using only primitive list procedures:
(define (flatten lst)
(cond ((null? lst)
'())
((not (list? lst))
(list lst))
(else
(append (flatten (car lst))
(flatten (cdr lst))))))
This other solution uses the map higher-order procedure and apply (as suggested by John Clements):
(define (flatten lst)
(if (not (list? lst))
(list lst)
(apply append (map flatten lst))))
And finally, as has been mentioned in the comments, the built-in flatten procedure found in some Scheme implementations like Racket (I don't know if it's available in bigloo):
(require racket/list)
(flatten '(a b c (d (e)) (g f h)))

How to create and add elements in a list in Scheme?

I want to define a method that take an integer as input and creates dynamically a list of all descending integer numbers to zero. I find trouble into calling method for the n-1 element
It's not all that pretty but this should work, tested in DrScheme.
(define (gen-list x )
(if (= x 0) (list 0) (cons x (gen-list (- x 1)))))
Now that it's a homework question, I think a tail-recursive version could be an alternative.
(define (gen-list x)
(let lp ((n 0) (ret '()))
(if (> n x)
ret
(lp (1+ n) (cons n ret)))))
If you're using PLT scheme, the comprehensions library will let you do this rather neatly:
; natural -> (listof natural)
(define (list-to-zero start-num)
(for/list ([i (in-range start-num 0 -1)])
i))
Just an alternative to the recursive form...