www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Idiomatic adjacent_difference

reply Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
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.
Oct 16 2015
parent reply John Colvin <john.loughran.colvin gmail.com> writes:
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])); }
Oct 16 2015
parent reply Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
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.
Oct 16 2015
parent reply Edwin van Leeuwen <edder tkwsping.nl> writes:
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]);
Oct 16 2015
parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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]);
Oct 16 2015
next sibling parent Guillaume Chatelet <chatelet.guillaume gmail.com> writes:
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 :)
Oct 16 2015
prev sibling next sibling parent John Colvin <john.loughran.colvin gmail.com> writes:
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).
Oct 16 2015
prev sibling parent reply anonymous <anonymous example.com> writes:
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?
Oct 16 2015
next sibling parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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.
Oct 16 2015
prev sibling parent Meta <jared771 gmail.com> writes:
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.
Oct 16 2015