From: Shane Seira
Subject: A simple lisp function
Date: 
Message-ID: <B739A3C7.C8C%shaneseira@cableone.net>
I am very new at lisp programming and need some help. I am trying to write a
function that will accept a list and produce a new list containing the
numeric atoms at the top level. Once I have this I want to multiply each
number in the list by two.
Example:
    (mult-numbers '(2 a 0 -4  -9 b (3 4) c (d 5)))
Will produce:
    (4 0 -8 -18)


Here is what I have so far (which is probably completely wrong!)

(defun mult-number(alist)
   (cond
        ((null alist) nil)
        ((listp alist)  alist)
        (numberp (car alist))(car alist))
        (* (alist) 2)
    )
)


Please help me!
Thanks! 


-- 
Shane Seira
··········@cableone.net

From: Hartmann Schaffer
Subject: Re: A simple lisp function
Date: 
Message-ID: <slrn9h8jfl.2df.hs@paradise.nirvananet>
In article <·······················@cableone.net>, Shane Seira wrote:
>I am very new at lisp programming and need some help. I am trying to write a
>function that will accept a list and produce a new list containing the
>numeric atoms at the top level. Once I have this I want to multiply each
>number in the list by two.
>Example:
>    (mult-numbers '(2 a 0 -4  -9 b (3 4) c (d 5)))
>Will produce:
>    (4 0 -8 -18)
>
>
>Here is what I have so far (which is probably completely wrong!)
>
>(defun mult-number(alist)
>   (cond
>        ((null alist) nil)

this is correct

>        ((listp alist)  alist)

this check is unnecessary:  you want to do something if it's a number, other-
wise you want to skip it.  no need to check for any other types

>        (numberp (car alist))(car alist))

with this, your function value is just the first  number you encounter,
nothing done with it (btw, it's probably a typo, but there should be an
extra opening parenthesis on the line).  instead, you want to multiply
it by 2 and build a list with the rest  of alist, something like

         ((numberp (car alist)) ( ... (* (car alist) 2)  ... (cdr alist) ...)

(i won't get into more detail just in case this is homework)

>        (* (alist) 2)

this is completely wrong:  you are still in the conditional, and you haven't
specified yet what you want to do when neither alist is empty nor its 1st
element a number (hint:  you want to do more of the same, with the rest of
the list, you also want some condition that catches all still possible
cases)


>    )
>)

these lines are correct

>Please help me!
>Thanks! 

good enough?  you should also look into doing that with some of the higher
level list functions, map... or some of the filtering functions

-- 

hs

----------------------------------------------------------------

"The cheapest pride is national pride.  I demonstrates the lack of
characteristics and achievements you can be proud of.  The worst loser
can have national pride"  - Schopenhauer
From: Richard Krush
Subject: Re: A simple lisp function
Date: 
Message-ID: <9f1ghg$1os68$1@ID-60069.news.dfncis.de>
Shane Seira <··········@cableone.net> wrote:
> I am very new at lisp programming and need some help. I am trying to write a
> function that will accept a list and produce a new list containing the
> numeric atoms at the top level. Once I have this I want to multiply each
> number in the list by two.
> Example:
>    (mult-numbers '(2 a 0 -4  -9 b (3 4) c (d 5)))
> Will produce:
>    (4 0 -8 -18)


> Here is what I have so far (which is probably completely wrong!)

> (defun mult-number(alist)
>   (cond
>        ((null alist) nil)
>        ((listp alist)  alist)
>        (numberp (car alist))(car alist))
>        (* (alist) 2)
>    )
> )

Using applicative operators would be much easier to do this, but they are
quite expensive (so is recusion though). Here's an example of how it can be
done using (mapcar) and (remove-if-not) :

(defun mult-numbers (mylist)
  (mapcar #'(lambda (a) (* a 2)) (remove-if-not #'numberp mylist)))

If you want a solution which uses recursion, it is quite easy to do as
well:

(defun rec-mult (mylist)
  (cond ((null mylist) nil)
        ((numberp (first mylist)) (cons (* 2 (first mylist))
                                        (rec-mult (rest mylist))))
        (t (rec-mult (rest mylist)))))

Or you could make it a little more efficient (just a tiny bit though), you
could use (let) to assign (first mylist) and (rest mylist) to variables,
like this:

(defun rec-mult (mylist)
  (let ((carlist (first mylist))
	(cdrlist (rest mylist)))
    (cond ((null mylist) nil)
	  ((numberp carlist) (cons (* 2 carlist)
				   (rec-mult cdrlist)))
	  (t (rec-mult cdrlist)))))

Hope this helps,
 rk

-- 
  Richard Krushelnitskiy   "A mathematician is a blind man in a dark
  ·········@gmx.net         room looking for a black cat which isn't
  http://rkrush.cjb.net	    there." -- Charles Darwin
From: Alex LaFontaine
Subject: Re: A simple lisp function
Date: 
Message-ID: <5bd73ec0.0105300452.e2b45d8@posting.google.com>
Shane Seira <··········@cableone.net> wrote in message news:<·······················@cableone.net>...
> I am very new at lisp programming and need some help. I am trying to write a
> function that will accept a list and produce a new list containing the
> numeric atoms at the top level. Once I have this I want to multiply each
> number in the list by two.
> Example:
>     (mult-numbers '(2 a 0 -4  -9 b (3 4) c (d 5)))
> Will produce:
>     (4 0 -8 -18)

Hi all,

I am also a Lisp newbie, but I've been following the newsgroup for a
little while and I've been trying to learn by working on questions
posted by other folks.  I found a pretty simple solution for this
question by breaking it into two parts -- one part to flatten the list
and another to do the multiplication.

The multiplication was the most straightforward:

(defun mult2 (l)
  (loop for x in (flatten l) when (numberp x) collect (* x 2)))

My flatten function also seems to work okay:

(defun flatten (l)
  (cond
   ((null l) nil)
   ((listp (car l)) (append (flatten (car l)) (flatten (cdr l))))
   (t (cons (car l) (flatten (cdr l))))))

My question is this, the FAQ says 'avoid using APPLY to flatten
lists', it then gives two examples of other ways to flatten lists of
lists:

(reduce #'append list-of-lists :from-end t)
(mapcan #'copy-list list-of-lists)

My question is, is there an elegant way of using REDUCE or MAPCAN (or
a similar function) to flatten a list that has sublists but is not a
list-of-lists?  For example, to flatten a list like: (1 (2 3) 4)

I suppose one way would be make sure that any list that I have is a
list of lists by filtering it through something like this:

(defun make-list-of-lists (l)
  (loop for x in l collect (if (listp x) x (list x))))

Then put everything together:

(reduce #'append (make-list-of-lists '(1 (2 3) 4)) :from-end t)

Sorry to be long winded and thanks for your time.

Cheers.
From: Tim Moore
Subject: Re: A simple lisp function
Date: 
Message-ID: <9f38us$a5k$0@216.39.145.192>
On 30 May 2001, Alex LaFontaine wrote:
> My question is, is there an elegant way of using REDUCE or MAPCAN (or
> a similar function) to flatten a list that has sublists but is not a
> list-of-lists?  For example, to flatten a list like: (1 (2 3) 4)
> 
> I suppose one way would be make sure that any list that I have is a
> list of lists by filtering it through something like this:
> 
> (defun make-list-of-lists (l)
>   (loop for x in l collect (if (listp x) x (list x))))
> 
> Then put everything together:
> 
> (reduce #'append (make-list-of-lists '(1 (2 3) 4)) :from-end t)
> 
> Sorry to be long winded and thanks for your time.

It's questionable if this is more elegant, but it is different:

(defun flatten (l)
  (mapcan #'(lambda (x)
	      (if (listp x)
		  (copy-list x)
		  (list x)))
	  l))

It conses a bit less garbage than your approach.

By the way, your approach (and mine) only flatten one level of sublists.
To go "all the way" you'd want to do something like:

(defun really-flatten (l)
  (typecase l
    (atom
     (list l))
    (t
     (loop for x in l nconc (really-flatten x)))))

Tim
From: Barry Margolin
Subject: Re: A simple lisp function
Date: 
Message-ID: <0UcR6.27$F93.1270@burlma1-snr2>
In article <·······················@cableone.net>,
Shane Seira  <··········@cableone.net> wrote:
>I am very new at lisp programming and need some help. I am trying to write a
>function that will accept a list and produce a new list containing the
>numeric atoms at the top level. Once I have this I want to multiply each
>number in the list by two.

This is very strange.  Yesterday someone posted a question, asking for a
"simple function" that would take a list and return a list of all the
negative numbers with 1 added to them.  These are practically the same
problem, posted by different people.

And both of you used "alist" as the name of the parameter to the function.

Are both of you taking the same class?

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.