Rocksolid Light

News from da outaworlds

mail  files  register  groups  login

Message-ID:  

BOFH excuse #38: secretary plugged hairdryer into UPS


comp / comp.lang.lisp / Cprod (Cartesian Product) in Lisp (or Scheme)

SubjectAuthor
* Cprod (Cartesian Product) in Lisp (or Scheme)HenHanna
+* Re: Cprod (Cartesian Product) in Lisp (or Scheme)Spiros Bousbouras
|`- Re: Cprod (Cartesian Product) in Lisp (or Scheme)HenHanna
`- Re: Cprod (Cartesian Product) in Lisp (or Scheme)Kaz Kylheku

1
Subject: Cprod (Cartesian Product) in Lisp (or Scheme)
From: HenHanna
Newsgroups: comp.lang.lisp, comp.lang.scheme
Organization: A noiseless patient Spider
Date: Tue, 21 May 2024 19:18 UTC
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: HenHanna@devnull.tb (HenHanna)
Newsgroups: comp.lang.lisp,comp.lang.scheme
Subject: Cprod (Cartesian Product) in Lisp (or Scheme)
Date: Tue, 21 May 2024 12:18:52 -0700
Organization: A noiseless patient Spider
Lines: 28
Message-ID: <v2is2s$ndjr$4@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 21 May 2024 21:18:52 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="4ee11fe942d496548c5fef5d03dc9b69";
logging-data="767611"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18NwZaKQTd4okZgL8/tl9nEeCu2oQBRTeI="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:g3j1XHytE4oXyAlAUDfph0FQ44w=
Content-Language: en-US
View all headers

How would you write this in Lisp (or Scheme) ?

in Python... (writing this out: itertools.product([0, 1], repeat=N )

The value can be a list or a Tuple.

cprod([0, 1], 1) => ((0) (1))

cprod([0, 1], 2) => ((0,0) (0,1) (1,0) (1,1))

This works:

def cprod(x, c):
if c==1: return [[i] for i in x]
Sub= cprod(x, c-1)
return [i for F in x for i in [[F]+R for R in Sub]]

---------- Is there another (better) way to write [F]+R ???

it seems odd, compared to CONS in Lisp

Other ways to improve it?

Subject: Re: Cprod (Cartesian Product) in Lisp (or Scheme)
From: Spiros Bousbouras
Newsgroups: comp.lang.lisp
Organization: A noiseless patient Spider
Date: Thu, 23 May 2024 15:46 UTC
References: 1
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: spibou@gmail.com (Spiros Bousbouras)
Newsgroups: comp.lang.lisp
Subject: Re: Cprod (Cartesian Product) in Lisp (or Scheme)
Date: Thu, 23 May 2024 15:46:34 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 35
Message-ID: <1NyKRUFob21AKlp59@bongo-ra.co>
References: <v2is2s$ndjr$4@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Injection-Date: Thu, 23 May 2024 17:46:34 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="82fe97c482ea8aed36794c227a5c1597";
logging-data="1924635"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18ScFxwqjRd+YuaKJVUO4mN"
Cancel-Lock: sha1:S3LYXYg7M3uNX6ePXDmqx0Hj5YY=
X-Server-Commands: nowebcancel
In-Reply-To: <v2is2s$ndjr$4@dont-email.me>
X-Organisation: Weyland-Yutani
View all headers

On Tue, 21 May 2024 12:18:52 -0700
HenHanna <HenHanna@devnull.tb> wrote:
>
>
> How would you write this in Lisp (or Scheme) ?
>
>
>
> in Python... (writing this out: itertools.product([0, 1], repeat=N )
>
> The value can be a list or a Tuple.
>
> cprod([0, 1], 1) => ((0) (1))
>
> cprod([0, 1], 2) => ((0,0) (0,1) (1,0) (1,1))

This is cartesian power rather than arbitrary cartesian product. Here
is a Common Lisp version. It only works for vectors.

(defun cartesian-power
(vector power
&aux (len (length vector)) (wheels (make-array power :initial-element 0))
result (posres 0)
)
(when (or (eql power 0) (eql len 0))
(return-from cartesian-power (make-array 0)))
(setq result (make-array (expt len power)))
(do () (nil)
(setf (aref result posres)
(map 'vector (lambda (a) (aref vector a)) wheels))
(incf posres)
(let ((pos (position-if (lambda (a) (< a (1- len))) wheels)))
(unless pos (return-from cartesian-power result))
(incf (aref wheels pos))
(dotimes (i pos) (setf (aref wheels i) 0)))))

Subject: Re: Cprod (Cartesian Product) in Lisp (or Scheme)
From: HenHanna
Newsgroups: comp.lang.lisp
Organization: A noiseless patient Spider
Date: Thu, 23 May 2024 17:27 UTC
References: 1 2
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: HenHanna@devnull.tb (HenHanna)
Newsgroups: comp.lang.lisp
Subject: Re: Cprod (Cartesian Product) in Lisp (or Scheme)
Date: Thu, 23 May 2024 10:27:04 -0700
Organization: A noiseless patient Spider
Lines: 38
Message-ID: <v2nu99$1qmlm$4@dont-email.me>
References: <v2is2s$ndjr$4@dont-email.me> <1NyKRUFob21AKlp59@bongo-ra.co>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Thu, 23 May 2024 19:27:06 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="a9965e799039eb2965b7c1874d29addb";
logging-data="1923766"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19k3joYB9bNjtVtH0EZVyjmP/HeEIgWTBw="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:9I41w0EkCLWtH9hZ6PuDOPj7AxU=
Content-Language: en-US
In-Reply-To: <1NyKRUFob21AKlp59@bongo-ra.co>
View all headers

On 5/23/2024 8:46 AM, Spiros Bousbouras wrote:
> On Tue, 21 May 2024 12:18:52 -0700
> HenHanna <HenHanna@devnull.tb> wrote:
>>
>>
>> How would you write this in Lisp (or Scheme) ?
>>
>>
>>
>> in Python... (writing this out: itertools.product([0, 1], repeat=N )
>>
>> The value can be a list or a Tuple.
>>
>> cprod([0, 1], 1) => ((0) (1))
>>
>> cprod([0, 1], 2) => ((0,0) (0,1) (1,0) (1,1))
>
> This is cartesian power rather than arbitrary cartesian product. Here
> is a Common Lisp version. It only works for vectors.
>
> (defun cartesian-power
> (vector power
> &aux (len (length vector)) (wheels (make-array power :initial-element 0))
> result (posres 0)
> )
> (when (or (eql power 0) (eql len 0))
> (return-from cartesian-power (make-array 0)))
> (setq result (make-array (expt len power)))
> (do () (nil)
> (setf (aref result posres)
> (map 'vector (lambda (a) (aref vector a)) wheels))
> (incf posres)
> (let ((pos (position-if (lambda (a) (< a (1- len))) wheels)))
> (unless pos (return-from cartesian-power result))
> (incf (aref wheels pos))
> (dotimes (i pos) (setf (aref wheels i) 0)))))

Thanks!

Subject: Re: Cprod (Cartesian Product) in Lisp (or Scheme)
From: Kaz Kylheku
Newsgroups: comp.lang.lisp, comp.lang.scheme
Organization: A noiseless patient Spider
Date: Fri, 24 May 2024 02:00 UTC
References: 1
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: 643-408-1753@kylheku.com (Kaz Kylheku)
Newsgroups: comp.lang.lisp,comp.lang.scheme
Subject: Re: Cprod (Cartesian Product) in Lisp (or Scheme)
Date: Fri, 24 May 2024 02:00:11 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 92
Message-ID: <20240523183817.334@kylheku.com>
References: <v2is2s$ndjr$4@dont-email.me>
Injection-Date: Fri, 24 May 2024 04:00:11 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="e11ec59bf0ae08b37203ccb330e57e74";
logging-data="2252792"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19Ip0/PohK1xumwOkjHJVT4exsc1Jd/xeY="
User-Agent: slrn/pre1.0.4-9 (Linux)
Cancel-Lock: sha1:LcFAy3HNgI8SJi2TyLRL5uoZx+o=
View all headers

On 2024-05-21, HenHanna <HenHanna@devnull.tb> wrote:
>
>
> How would you write this in Lisp (or Scheme) ?
>
>
>
> in Python... (writing this out: itertools.product([0, 1], repeat=N )
>
> The value can be a list or a Tuple.
>
> cprod([0, 1], 1) => ((0) (1))
>
> cprod([0, 1], 2) => ((0,0) (0,1) (1,0) (1,1))

Another name for this is "repeating permutations": permutations
of the (0 1) elements, such that repetitions are allowed.

How I would write this is by having it built into the language.

This is the TXR Lisp interactive listener of TXR 294.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
Everything you type here can and will be used against you in
comp.lang.lisp.
1> (rperm '(0 1) 2)
((0 0) (0 1) (1 0) (1 1))

I would have it as a lazy list, so we can ask for the first 5
items of an incredibly long instance of such a sequence.

2> (take 5 (rperm #\A..#\Z 15))
((#\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A)
(#\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\B)
(#\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\C)
(#\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\D)
(#\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\A #\E))
3> (take 5 (rperm (join #\A..#\Z) 15))
("AAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAB" "AAAAAAAAAAAAAAC" "AAAAAAAAAAAAAAD"
"AAAAAAAAAAAAAAE")

That reminds me; I should probably implement iterators which
step over these sequences, to complement the lazy list implementation.

The implementation of rperm starts here:

https://www.kylheku.com/cgit/txr/tree/combi.c?h=txr-294#n264

The heart of it is the rperm_gen_fun function, which updates
a permutation vector to the next permutation.

The state consists of a vector of lists, and a reset list.

For instance, if we are generating triplets of (A B C D), the
vector gets initialized to a copy of the list in every position:

#((A B C D)
(A B C D)
(A B C D))

We take the first repeating permutation by taking the car
of every list: (A A A A). Then to generate the next permutation,
we pop the last list:

#((A B C D)
(A B C D)
(B C D)) ;; pop!

When we pop the last list empty, we restore it back to (A B C D),
and pop the next one:

#((A B C D)
(A B C D)
(B))

#((A B C D)
(A B C D)
()) ;; pop! oops!

#((A B C D)
(B C D) ;; pop!
(A B C D)) ;; whump! (restored)

When we pop the first list down to nil, then we are done.
The rperm_while_fun tests for this condition.

It's a very simple algorithm compared to the nonrepeating
permutations, and repeating or nonrepeating combinations.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

1

rocksolid light 0.9.8
clearnet tor