From: acp
Subject: combination function help
Date: 
Message-ID: <db96gk$3qd$1@newsdbm05.news.prodigy.com>
i am novice to lisp.

i am looking for a function that does the following combination 'across 
lists'.

((1 2) (3 4) (5 6))

to

((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))

thanks,
-AC

From: Tron3k
Subject: Re: combination function help
Date: 
Message-ID: <1121476084.102259.91230@z14g2000cwz.googlegroups.com>
acp wrote:
> i am novice to lisp.
>
> i am looking for a function that does the following combination 'across
> lists'.
>
> ((1 2) (3 4) (5 6))
>
> to
>
> ((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))
>
> thanks,
> -AC

Here's my try at this function:

(defun combine (lst)
    (if (endp lst)
	(list '())
	(loop with crest = (combine (rest lst))
	      for item in (first lst)
	      nconc (loop for items in crest
			  collect (cons item items)))))
From: Christopher C. Stacy
Subject: Re: combination function help
Date: 
Message-ID: <ufyufeolu.fsf@news.dtpq.com>
acp <·······@yahoo.com> writes:

> i am novice to lisp.
> 
> i am looking for a function that does the following
>  combination 'across lists'.
> 
> ((1 2) (3 4) (5 6))
> 
> to
> 
> ((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))

There is no Lisp function that does this.
You'll have to write it.
From: Pascal Bourguignon
Subject: Re: combination function help
Date: 
Message-ID: <877jfreqm2.fsf@thalassa.informatimago.com>
acp <·······@yahoo.com> writes:

> i am novice to lisp.
>
> i am looking for a function that does the following combination
> across lists'.
>
> ((1 2) (3 4) (5 6))
>
> to
>
> ((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))

You don't know the fun you miss not writting it yourself!


(DEFUN COMBINE (ARGS)
  "
RETURN:  (elt args 0) x (elt args 1) x ... x (elt args (1- (length args)))
         = the set of tuples built taking one item in order from each list
           in args.
EXAMPLE: (COMBINE '((WWW FTP) (EXA) (COM ORG))) 
           --> ((WWW EXA COM) (WWW EXA ORG) (FTP EXA COM) (FTP EXA ORG))
"
  (COND
   ((NULL ARGS) '(NIL))
   ((NULL (CAR ARGS)) (APPLY (FUNCTION COMBINE) (CDR ARGS)))
   ((CONSP (CAR ARGS))
    (MAPCAN (LAMBDA (ITEM) (COMBINE (cons ITEM (CDR ARGS))))
            (CAR ARGS)))
   (T
    (MAPCAN (LAMBDA (REST) (LIST (CONS (CAR ARGS) REST)))
            (COMBINE (CDR ARGS))))))


[15]> (combine '((1 2) (3 4) (5 6)))
((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?
From: Pascal Bourguignon
Subject: Re: combination function help
Date: 
Message-ID: <873bqfeqgs.fsf@thalassa.informatimago.com>
Pascal Bourguignon <···@informatimago.com> writes:

> acp <·······@yahoo.com> writes:
>
>> i am novice to lisp.
>>
>> i am looking for a function that does the following combination
>> across lists'.
>>
>> ((1 2) (3 4) (5 6))
>>
>> to
>>
>> ((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))
>
> You don't know the fun you miss not writting it yourself!

Actually, use this (I left one APPLY when I converted to your
signature specification):


(DEFUN COMBINE (ARGS)
  "
RETURN:  (elt args 0) x (elt args 1) x ... x (elt args (1- (length args)))
         = the set of tuples built taking one item in order from each list
           in args.
EXAMPLE: (COMBINE '((WWW FTP) (EXA) (COM ORG))) 
           --> ((WWW EXA COM) (WWW EXA ORG) (FTP EXA COM) (FTP EXA ORG))
"
  (COND
   ((NULL ARGS) '(NIL))
   ((NULL (CAR ARGS)) (COMBINE (CDR ARGS)))
   ((CONSP (CAR ARGS))
    (MAPCAN (LAMBDA (ITEM) (COMBINE (cons ITEM (CDR ARGS))))
            (CAR ARGS)))
   (T
    (MAPCAN (LAMBDA (REST) (LIST (CONS (CAR ARGS) REST)))
            (COMBINE (CDR ARGS))))))


[15]> (combine '((1 2) (3 4) (5 6)))
((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?
From: acp
Subject: Re: combination function help
Date: 
Message-ID: <db9a62$68l$1@newsdbm05.news.prodigy.com>
i was actually looking for a function in the standard library that does 
this job.

working great..

actually..'FUN' just started.

thanks for your help,
-AC



Pascal Bourguignon wrote:
> Pascal Bourguignon <···@informatimago.com> writes:
> 
> 
>>acp <·······@yahoo.com> writes:
>>
>>
>>>i am novice to lisp.
>>>
>>>i am looking for a function that does the following combination
>>>across lists'.
>>>
>>>((1 2) (3 4) (5 6))
>>>
>>>to
>>>
>>>((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))
>>
>>You don't know the fun you miss not writting it yourself!
> 
> 
> Actually, use this (I left one APPLY when I converted to your
> signature specification):
> 
> 
> (DEFUN COMBINE (ARGS)
>   "
> RETURN:  (elt args 0) x (elt args 1) x ... x (elt args (1- (length args)))
>          = the set of tuples built taking one item in order from each list
>            in args.
> EXAMPLE: (COMBINE '((WWW FTP) (EXA) (COM ORG))) 
>            --> ((WWW EXA COM) (WWW EXA ORG) (FTP EXA COM) (FTP EXA ORG))
> "
>   (COND
>    ((NULL ARGS) '(NIL))
>    ((NULL (CAR ARGS)) (COMBINE (CDR ARGS)))
>    ((CONSP (CAR ARGS))
>     (MAPCAN (LAMBDA (ITEM) (COMBINE (cons ITEM (CDR ARGS))))
>             (CAR ARGS)))
>    (T
>     (MAPCAN (LAMBDA (REST) (LIST (CONS (CAR ARGS) REST)))
>             (COMBINE (CDR ARGS))))))
> 
> 
> [15]> (combine '((1 2) (3 4) (5 6)))
> ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
> 
From: Tron3k
Subject: Re: combination function help
Date: 
Message-ID: <1121475092.608853.304570@g47g2000cwa.googlegroups.com>
Pascal Bourguignon wrote:
> Pascal Bourguignon <···@informatimago.com> writes:
>
> > acp <·······@yahoo.com> writes:
> >
> >> i am novice to lisp.
> >>
> >> i am looking for a function that does the following combination
> >> across lists'.
> >>
> >> ((1 2) (3 4) (5 6))
> >>
> >> to
> >>
> >> ((1 3 5) (2 3 5) ( 1 4 5) ( 2 4 5) ( 1 3 6) ( 2 3 6) ( 1 4 6) ( 2 4 6))
> >
> > You don't know the fun you miss not writting it yourself!
>
> Actually, use this (I left one APPLY when I converted to your
> signature specification):
>
>
> (DEFUN COMBINE (ARGS)
>   "
> RETURN:  (elt args 0) x (elt args 1) x ... x (elt args (1- (length args)))
>          = the set of tuples built taking one item in order from each list
>            in args.
> EXAMPLE: (COMBINE '((WWW FTP) (EXA) (COM ORG)))
>            --> ((WWW EXA COM) (WWW EXA ORG) (FTP EXA COM) (FTP EXA ORG))
> "
>   (COND
>    ((NULL ARGS) '(NIL))
>    ((NULL (CAR ARGS)) (COMBINE (CDR ARGS)))
>    ((CONSP (CAR ARGS))
>     (MAPCAN (LAMBDA (ITEM) (COMBINE (cons ITEM (CDR ARGS))))
>             (CAR ARGS)))
>    (T
>     (MAPCAN (LAMBDA (REST) (LIST (CONS (CAR ARGS) REST)))
>             (COMBINE (CDR ARGS))))))
>
>
> [15]> (combine '((1 2) (3 4) (5 6)))
> ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
>
> --
> __Pascal Bourguignon__                     http://www.informatimago.com/
>
> In a World without Walls and Fences,
> who needs Windows and Gates?

I think you made a mistake here - correct me if I'm wrong.

You said that if the CAR of ARGS is the empty list, just skip it and
move on. I don't think this is right. Consider the following identity:

(= (length (combine x))
   (apply #'* (mapcar #'length x)))

This should always hold, shouldn't it? The number of elements in the
COMBINE list should be the number formed by multiplying all the lengths
of the elements in the original list. For the empty list, this would
mean multiplying no numbers together: (*), which evaluates to 1. So
your first COND clause is correct. But if there were an empty list
somewhere in the original list, the number of elements in the COMBINE
list should be precisely ZERO! You have no choice of what to put in
that slot, so you can't do anything. What do you think?
From: Pascal Bourguignon
Subject: Re: combination function help
Date: 
Message-ID: <87u0ivd061.fsf@thalassa.informatimago.com>
"Tron3k" <······@gmail.com> writes:
>> (DEFUN COMBINE (ARGS)
>>   "
>> RETURN:  (elt args 0) x (elt args 1) x ... x (elt args (1- (length args)))
>>          = the set of tuples built taking one item in order from each list
>>            in args.
>> EXAMPLE: (COMBINE '((WWW FTP) (EXA) (COM ORG)))
>>            --> ((WWW EXA COM) (WWW EXA ORG) (FTP EXA COM) (FTP EXA ORG))
>> "
>>   (COND
>>    ((NULL ARGS) '(NIL))
>>    ((NULL (CAR ARGS)) (COMBINE (CDR ARGS)))
>>    ((CONSP (CAR ARGS))
>>     (MAPCAN (LAMBDA (ITEM) (COMBINE (cons ITEM (CDR ARGS))))
>>             (CAR ARGS)))
>>    (T
>>     (MAPCAN (LAMBDA (REST) (LIST (CONS (CAR ARGS) REST)))
>>             (COMBINE (CDR ARGS))))))
>>
>>
>> [15]> (combine '((1 2) (3 4) (5 6)))
>> ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
>
> I think you made a mistake here - correct me if I'm wrong.
>
> You said that if the CAR of ARGS is the empty list, just skip it and
> move on. I don't think this is right. Consider the following identity:
>
> (= (length (combine x))
>    (apply #'* (mapcar #'length x)))
>
> This should always hold, shouldn't it? The number of elements in the
> COMBINE list should be the number formed by multiplying all the lengths
> of the elements in the original list. For the empty list, this would
> mean multiplying no numbers together: (*), which evaluates to 1. So
> your first COND clause is correct. But if there were an empty list
> somewhere in the original list, the number of elements in the COMBINE
> list should be precisely ZERO! You have no choice of what to put in
> that slot, so you can't do anything. What do you think?

You are perfectly right. I wrote this combine function in the context
of composing domain names to generate DNS zone files where a NIL in
the list of the name components doesn't mean we don't want no
combination [my COMBINE takes () to be equivalent to (""), expecting
the resulting combinations to be concatenated].

But indeed, a generic, mathematical, combine should be specified more
consistently as you do.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?