Replacing elements in a list

Discussion of Common Lisp
Lispoman
Posts: 12
Joined: Mon Jun 01, 2009 6:09 pm

Replacing elements in a list

Post by Lispoman » Mon Jun 01, 2009 6:43 pm

Hi All.
I need some help cause I have no enough knowledge to complete my task. So what's the goal.
I need to define a a function which places a simbol * before every less-than-zero (-1..-5 etc.) element.
For ex. I've (setq a'(1 ,2 ,3 ,-1, -5 ,7 ,-8) a list. So then I should call a function forex MyFunc(x)
(Myfunc A) then I should get (1, 2, 3 ,*-1, *-5, 7 ,8) (i use commas here to separate elements of course no commas in the code).
I'm trying to write this function already 5 days but still can't .
Can someone help me?

So what I get

Code: Select all

(defun myfunc (a x)
 (cond ((null x) nil)
 ((< (car x) 0) (cons a (myfunc a (cdr x))))
 (T (cons (car x) (myfunc a (cdr x))))))
But it just replaces every less-than-zero in a list X to A. But I need a function with just one parameter X-which represents a list.

Harleqin
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: Replacing elements in a list

Post by Harleqin » Tue Jun 02, 2009 10:42 am

What kind of value do you expect "*-1" to be? The way you write it, it can only be a symbol, but the other elements seem to be numbers.

What kind of values should the input list contain?

By the way, you should properly indent your code to help with reading it. A nice explanation can be found in Practical Common Lisp.
"Just throw more hardware at it" is the root of all evil.
Svante

Jasper
Posts: 209
Joined: Fri Oct 10, 2008 8:22 am
Location: Eindhoven, The Netherlands
Contact:

Re: Replacing elements in a list

Post by Jasper » Tue Jun 02, 2009 12:13 pm

If the symbol * has to be before as element of the list your code is nearly correct:

Code: Select all

(defun myfunc (a x)
  (cond ((null x) nil)
    ((< (car x) 0)
      (append (list a (car x)) (myfunc a (cdr x))))
    (t
      (cons (car x) (myfunc a (cdr x))))))
If you want to attach to things into a string you can use format nil ... (nil indicating that output to string, and you can make strings into a symbol with intern. Left as an exercise.
Last edited by Jasper on Tue Jun 02, 2009 3:06 pm, edited 1 time in total.

Paul Donnelly
Posts: 148
Joined: Wed Jul 30, 2008 11:26 pm

Re: Replacing elements in a list

Post by Paul Donnelly » Tue Jun 02, 2009 1:11 pm

Break it up into two parts. Write a function that returns either the positive number or the... other thing, then use MAPCAR to apply it to the list.

Code: Select all

(defun do-strange-thing (list)
  (mapcar (lambda (number)
            (if (plusp number)
                number
                (cons '* number))) ; Replace this with what you actually wanted.
          list))
Or of course you could write the same thing recursively (or with DO or LOOP) if you wanted, but this strikes me as cleaner.

Lispoman
Posts: 12
Joined: Mon Jun 01, 2009 6:09 pm

Re: Replacing elements in a list

Post by Lispoman » Tue Jun 02, 2009 6:09 pm

Thanks for your attention.

Ok let me to explain.

So i have a list A(1 2 4 -1 3 -2 6 -8). As you see here is some members which has <0 values For ex. -1 -2 -8. and some members are >0 ok just simple list. ;)
Now the goal. I need a function which place a symbol * before every member which has <0 value. Thats all! :o

One more ex.

list A before
(1 2 4 -1 3 -2 6 -8)

list after A
(1 2 4 *-1 3 *-2 6 *-8)

So if I have a member which value is <0 then I should add a symbol * before. Or by other word it should be combined in one member * and a number. Here: *-1 is one single member and *-8 is another single member

Paul Donnelly
Posts: 148
Joined: Wed Jul 30, 2008 11:26 pm

Re: Replacing elements in a list

Post by Paul Donnelly » Tue Jun 02, 2009 7:52 pm

Lispoman wrote:Now the goal. I need a function which place a symbol * before every member which has <0 value. Thats all! :o
That seems like a bad idea. What can you do with a symbol like "*-1"?

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Replacing elements in a list

Post by gugamilare » Tue Jun 02, 2009 8:15 pm

Lispoman wrote:So if I have a member which value is <0 then I should add a symbol * before. Or by other word it should be combined in one member * and a number. Here: *-1 is one single member and *-8 is another single member
Changing Paul Donnelly's code you can do this in a quite simple way. To take a number (e.g. -3) and return the symbol add a * before it (e.g. *-3), you can use this function:

Code: Select all

(defun add-* (number)
  (intern (format nil "*~a" number)))
This should be more than enough information for you to do what you have in mind. This looks like homework and I don't want to do it for you.

But this is a very weird task. This takes a number and returns a symbol. If this is homework, are you sure you haven't gotten the exercise wrong? Because I believe that "add a symbol * before every number in the list", is to do something like this:

Code: Select all

(add-*-before-negatives '(1 2 4 -1 3 -2 6 -8)) => (1 2 4 * -1 3 * -2 6 * -8)
If this is not homework, then I have absolutely no idea of how this can be useful, and you must be doing things the wrong way.

Paul
Posts: 106
Joined: Tue Jun 02, 2009 6:00 am

Re: Replacing elements in a list

Post by Paul » Tue Jun 02, 2009 8:52 pm

Lispoman wrote:Hi All.
I need some help cause I have no enough knowledge to complete my task. So what's the goal.
I need to define a a function which places a simbol * before every less-than-zero (-1..-5 etc.) element.
For ex. I've (setq a'(1 ,2 ,3 ,-1, -5 ,7 ,-8) a list. So then I should call a function forex MyFunc(x)
(Myfunc A) then I should get (1, 2, 3 ,*-1, *-5, 7 ,8) (i use commas here to separate elements of course no commas in the code).
I rather suspect you want (1 2 3 * -1 * -5 7 8) — i.e., with * symbols appearing before the negative values, not symbols like *-1 as everyone seems to be assuming.

Code: Select all

(defun myfunc (a x)
 (cond ((null x) nil)
 ((< (car x) 0) (cons a (myfunc a (cdr x))))
 (T (cons (car x) (myfunc a (cdr x))))))
But it just replaces every less-than-zero in a list X to A. But I need a function with just one parameter X-which represents a list.
Is this homework?

I'd write

Code: Select all

(loop for x in list when (minusp x) collect '* collect x)

Lispoman
Posts: 12
Joined: Mon Jun 01, 2009 6:09 pm

Re: Replacing elements in a list

Post by Lispoman » Tue Jun 02, 2009 9:10 pm

Yes you right. This code has no any practical value but. I need a sample how to do such a transform because I need to use it in some functions. I did'n post my code here cause it will take a lot to explain the purpose but I need such a so called transfirmation of the list.
A function above is just what I need It adds a * symbol to anything. But how to connect it with my code I've tryed

Code: Select all


(defun add-*(number)
	   (intern (format nil "*~a" number)))
	   
(defun myfunc (x)
           (cond ((null x) nil)
                 ((< (car x) 0) (cons (add-* (car x)) (myfunc (add-* (car x)) (cdr x)))
                      (T (cons (car x) (myfunc (add-* (car x)) (cdr x)))))))
But it returns NIL insted of list.

Lispoman
Posts: 12
Joined: Mon Jun 01, 2009 6:09 pm

Re: Replacing elements in a list

Post by Lispoman » Tue Jun 02, 2009 10:10 pm

Yeea! Solved. Nice working.

Code: Select all

(defun add (number)
  	(intern (format nil "*~a" number)))

(defun myfunc (x)
	(cond ((null x) nil)
		((< (car x) 0) (cons (add (car x)) (myfunc (cdr x))))
		(T (cons (car x) (myfunc (cdr x))))))
Thanks

Now the question can lisp differ even and odd numbers? And how can the function above be modified to use with lambda?

Post Reply