Thread overview
Set operation like cartesian product
Feb 28, 2013
Andrea Fontana
Feb 28, 2013
Andrea Fontana
Feb 28, 2013
bearophile
Feb 28, 2013
H. S. Teoh
Feb 28, 2013
Andrea Fontana
Feb 28, 2013
H. S. Teoh
Feb 28, 2013
H. S. Teoh
February 28, 2013
I see cartesianProduct in std.algorithm. I read:

auto N = sequence!"n"(0); // the range of natural numbers
auto N2 = cartesianProduct(N, N); // the range of all pairs of natural numbers

So it gives (0,0) (0,1) (1,0) ... and so on.

Is there a way to generate only tuple:

a[0] > a[1] (0,1) (0,2) ... (1,2) (1,3) .. (2,3) (2,4)

or

a[0] >= a[1] (0,0) (0,1) (0,2) ... (1,1) (1,2) (1,3) .. (2,2) (2,3) (2,4)

Or the only way is use filter!(...) after cartesianProduct?
February 28, 2013
On Thursday, 28 February 2013 at 15:32:00 UTC, Andrea Fontana wrote:
> I see cartesianProduct in std.algorithm. I read:
>
> auto N = sequence!"n"(0); // the range of natural numbers
> auto N2 = cartesianProduct(N, N); // the range of all pairs of natural numbers
>
> So it gives (0,0) (0,1) (1,0) ... and so on.
>
> Is there a way to generate only tuple:
>
> a[0] > a[1] (0,1) (0,2) ... (1,2) (1,3) .. (2,3) (2,4)
>
> or
>
> a[0] >= a[1] (0,0) (0,1) (0,2) ... (1,1) (1,2) (1,3) .. (2,2) (2,3) (2,4)
>
> Or the only way is use filter!(...) after cartesianProduct?

PS: In my case I can't use filter!(...): I'm trying to compare an array of struct with itself to find similar ones, so I can't filter Tuple(struct, struct) in any way...

I have to write:

for (i; 0..arr.length) for(j; i+1..arr.length) // check arr[i] and arr[j] for similarities

Any ideas?


February 28, 2013
Andrea Fontana:

> Any ideas?

I suggested pairwise():
http://d.puremagic.com/issues/show_bug.cgi?id=6788

Bye,
bearophile
February 28, 2013
On Thu, Feb 28, 2013 at 04:31:59PM +0100, Andrea Fontana wrote:
> I see cartesianProduct in std.algorithm. I read:
> 
> auto N = sequence!"n"(0); // the range of natural numbers
> auto N2 = cartesianProduct(N, N); // the range of all pairs of
> natural numbers
> 
> So it gives (0,0) (0,1) (1,0) ... and so on.
> 
> Is there a way to generate only tuple:
> 
> a[0] > a[1] (0,1) (0,2) ... (1,2) (1,3) .. (2,3) (2,4)
[...]

auto triangularProduct(R1,R2)(R1 r1, R2 r2)
	if (isForwardRange!R1)
{
	return map!(function(a) => zip(take(a[1].save, a[0]), repeat(a[2])))(
			zip(sequence!"n"(0), repeat(r1.save), r2)
		)
		.joiner();
}

Both ranges can be infinite, only the first one needs to be a forward range.


> a[0] >= a[1] (0,0) (0,1) (0,2) ... (1,1) (1,2) (1,3) .. (2,2) (2,3)
> (2,4)
[...]

auto triangularProduct2(R1,R2)(R1 r1, R2 r2)
	if (isForwardRange!R1)
{
	return map!(function(a) => zip(take(a[1].save, a[0]), repeat(a[2])))(
			zip(sequence!"n"(1), repeat(r1.save), r2)
		)
		.joiner();
}

As above, both ranges can be infinite, only the first one needs to be a forward range.

Hope this helps. ;-)


T

-- 
Gone Chopin. Bach in a minuet.
February 28, 2013
On Thursday, 28 February 2013 at 18:23:04 UTC, H. S. Teoh wrote:
> On Thu, Feb 28, 2013 at 04:31:59PM +0100, Andrea Fontana wrote:
>> I see cartesianProduct in std.algorithm. I read:
>> 
>> auto N = sequence!"n"(0); // the range of natural numbers
>> auto N2 = cartesianProduct(N, N); // the range of all pairs of
>> natural numbers
>> 
>> So it gives (0,0) (0,1) (1,0) ... and so on.
>> 
>> Is there a way to generate only tuple:
>> 
>> a[0] > a[1] (0,1) (0,2) ... (1,2) (1,3) .. (2,3) (2,4)
> [...]
>
> auto triangularProduct(R1,R2)(R1 r1, R2 r2)
> 	if (isForwardRange!R1)
> {
> 	return map!(function(a) => zip(take(a[1].save, a[0]), repeat(a[2])))(
> 			zip(sequence!"n"(0), repeat(r1.save), r2)
> 		)
> 		.joiner();
> }
>
> Both ranges can be infinite, only the first one needs to be a forward
> range.
>
>
>> a[0] >= a[1] (0,0) (0,1) (0,2) ... (1,1) (1,2) (1,3) .. (2,2) (2,3)
>> (2,4)
> [...]
>
> auto triangularProduct2(R1,R2)(R1 r1, R2 r2)
> 	if (isForwardRange!R1)
> {
> 	return map!(function(a) => zip(take(a[1].save, a[0]), repeat(a[2])))(
> 			zip(sequence!"n"(1), repeat(r1.save), r2)
> 		)
> 		.joiner();
> }
>
> As above, both ranges can be infinite, only the first one needs to be a
> forward range.
>
> Hope this helps. ;-)
>
>
> T

triangulaProduct2 for [0,1,2,3] and [0,1,2,3] doesn't give (0,0) (1,1) (2,2) (3,3)

:)
February 28, 2013
On Thu, Feb 28, 2013 at 09:20:52PM +0100, Andrea Fontana wrote:
> On Thursday, 28 February 2013 at 18:23:04 UTC, H. S. Teoh wrote:
[...]
> >auto triangularProduct2(R1,R2)(R1 r1, R2 r2)
> >	if (isForwardRange!R1)
> >{
> >	return map!(function(a) => zip(take(a[1].save, a[0]),
> >repeat(a[2])))(
> >			zip(sequence!"n"(1), repeat(r1.save), r2)
> >		)
> >		.joiner();
> >}
> >
> >As above, both ranges can be infinite, only the first one needs to
> >be a
> >forward range.
> >
> >Hope this helps. ;-)
> >
> >
> >T
> 
> triangulaProduct2 for [0,1,2,3] and [0,1,2,3] doesn't give (0,0)
> (1,1) (2,2) (3,3)
> 
> :)

Ahhh, slight mistake there, it should be:

auto triangularProduct2(R1,R2)(R1 r1, R2 r2)
	if (isForwardRange!R1)
{
	return map!(function(a) => zip(take(a[1].save, a[0]+1), repeat(a[2])))(
			zip(sequence!"n"(1), repeat(r1.save), r2)
		)
		.joiner();
}

There, better now? ;-)

Also, if you only need products of finite ranges, it's possible to rewrite it so that it produces items in a nicer order. The strange order output by my examples are to cater for the infinite case.


T

-- 
Life would be easier if I had the source code. -- YHL
February 28, 2013
On Thu, Feb 28, 2013 at 03:01:48PM -0800, H. S. Teoh wrote:
> On Thu, Feb 28, 2013 at 09:20:52PM +0100, Andrea Fontana wrote:
> > On Thursday, 28 February 2013 at 18:23:04 UTC, H. S. Teoh wrote:
> [...]
> > >auto triangularProduct2(R1,R2)(R1 r1, R2 r2)
> > >	if (isForwardRange!R1)
> > >{
> > >	return map!(function(a) => zip(take(a[1].save, a[0]),
> > >repeat(a[2])))(
> > >			zip(sequence!"n"(1), repeat(r1.save), r2)
> > >		)
> > >		.joiner();
> > >}
> > >
> > >As above, both ranges can be infinite, only the first one needs to
> > >be a
> > >forward range.
> > >
> > >Hope this helps. ;-)
> > >
> > >
> > >T
> > 
> > triangulaProduct2 for [0,1,2,3] and [0,1,2,3] doesn't give (0,0)
> > (1,1) (2,2) (3,3)
> > 
> > :)
> 
> Ahhh, slight mistake there, it should be:
> 
> auto triangularProduct2(R1,R2)(R1 r1, R2 r2)
> 	if (isForwardRange!R1)
> {
> 	return map!(function(a) => zip(take(a[1].save, a[0]+1), repeat(a[2])))(
> 			zip(sequence!"n"(1), repeat(r1.save), r2)
[...]

Argh. Another mistake. The above line should read:

 			zip(sequence!"n"(0), repeat(r1.save), r2)

:-/


T

-- 
Once bitten, twice cry...