Thread overview
Idiomatic adjacent_difference
Oct 16, 2015
Guillaume Chatelet
Oct 16, 2015
John Colvin
Oct 16, 2015
Guillaume Chatelet
Oct 16, 2015
Edwin van Leeuwen
Oct 16, 2015
Per Nordlöw
Oct 16, 2015
Guillaume Chatelet
Oct 16, 2015
John Colvin
Oct 16, 2015
anonymous
Oct 16, 2015
Nordlöw
Oct 16, 2015
Meta
October 16, 2015
Is there an idiomatic way to do:

int[] numbers = [0, 1, 2, 3];
assert(adjacent_diff(numbers) == [1, 1, 1]);

I can't find something useful in the std library.
October 16, 2015
On Friday, 16 October 2015 at 11:11:28 UTC, Guillaume Chatelet wrote:
> Is there an idiomatic way to do:
>
> int[] numbers = [0, 1, 2, 3];
> assert(adjacent_diff(numbers) == [1, 1, 1]);
>
> I can't find something useful in the std library.

import std.range, std.algorithm;

auto slidingWindow(R)(R r, size_t n)
if(isForwardRange!R)
{
	//you could definitely do this with less overhead
	return roundRobin(r.chunks(n), r.save.drop(1).chunks(n))
		.filter!(p => p.length == n);
}

auto adjacentDiff(R)(R r)
{
	return r.slidingWindow(2).map!"a[1] - a[0]";
}

unittest
{
	import std.stdio;
	int[] numbers = [0, 1, 2, 3];
	writeln(numbers.slidingWindow(2));
	writeln(adjacentDiff(numbers));
	assert(adjacentDiff(numbers).equal([1, 1, 1]));
}
October 16, 2015
On Friday, 16 October 2015 at 11:38:35 UTC, John Colvin wrote:
> import std.range, std.algorithm;
>
> auto slidingWindow(R)(R r, size_t n)
> if(isForwardRange!R)
> {
> 	//you could definitely do this with less overhead
> 	return roundRobin(r.chunks(n), r.save.drop(1).chunks(n))
> 		.filter!(p => p.length == n);
> }
>
> auto adjacentDiff(R)(R r)
> {
> 	return r.slidingWindow(2).map!"a[1] - a[0]";
> }

Nice !
I wanted to use lockstep(r, r.dropOne) but it doesn't return a Range :-/
It has to be used in a foreach.
October 16, 2015
On Friday, 16 October 2015 at 11:43:16 UTC, Guillaume Chatelet wrote:
> On Friday, 16 October 2015 at 11:38:35 UTC, John Colvin wrote:
>
> Nice !
> I wanted to use lockstep(r, r.dropOne) but it doesn't return a Range :-/
> It has to be used in a foreach.

Instead of lockstep you can always use zip (which is the same but returns a range)


zip(r, r[1..$]).map!((t) => t[1]-t[0]);
October 16, 2015
On Friday, 16 October 2015 at 11:48:19 UTC, Edwin van Leeuwen wrote:
> zip(r, r[1..$]).map!((t) => t[1]-t[0]);

And for InputRanges (not requiring random-access):

zip(r, r.dropOne).map!((t) => t[1]-t[0]);
October 16, 2015
On Friday, 16 October 2015 at 12:03:56 UTC, Per Nordlöw wrote:
> On Friday, 16 October 2015 at 11:48:19 UTC, Edwin van Leeuwen wrote:
>> zip(r, r[1..$]).map!((t) => t[1]-t[0]);
>
> And for InputRanges (not requiring random-access):
>
> zip(r, r.dropOne).map!((t) => t[1]-t[0]);

That's neat. Thx guys :)
October 16, 2015
On Friday, 16 October 2015 at 12:03:56 UTC, Per Nordlöw wrote:
> On Friday, 16 October 2015 at 11:48:19 UTC, Edwin van Leeuwen wrote:
>> zip(r, r[1..$]).map!((t) => t[1]-t[0]);
>
> And for InputRanges (not requiring random-access):
>
> zip(r, r.dropOne).map!((t) => t[1]-t[0]);

We should have a good implementation of slidingWindow in std.range, it's a useful iteration pattern (although it does sometimes encourage inefficient algorithms).
October 16, 2015
On Friday, October 16, 2015 02:03 PM, Per Nordlöw wrote:

> zip(r, r.dropOne).map!((t) => t[1]-t[0]);

You should r.save one or both of those. The dropOne may affect both instances if you don't .save.

By the way, what's the point of `dropOne` over `drop(1)`? It's not shorter. Does it do anything subtly different?
October 16, 2015
On Friday, 16 October 2015 at 15:02:54 UTC, anonymous wrote:
> By the way, what's the point of `dropOne` over `drop(1)`? It's not shorter. Does it do anything subtly different?

I also find it strange.
October 16, 2015
On Friday, 16 October 2015 at 15:02:54 UTC, anonymous wrote:
> On Friday, October 16, 2015 02:03 PM, Per Nordlöw wrote:
>
>> zip(r, r.dropOne).map!((t) => t[1]-t[0]);
>
> You should r.save one or both of those. The dropOne may affect both instances if you don't .save.
>
> By the way, what's the point of `dropOne` over `drop(1)`? It's not shorter. Does it do anything subtly different?

The only difference is that dropOne calls popFront and drop calls popFrontN.