Thread overview | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 26, 2014 Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Hello ! I got a problem which I'm sure can be solved by a smart one liner. I would like to obtain the term by term product of a given range by the infinite cyclic range cycle([1,-1]). How can I do that ? |
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | On Sunday, 26 January 2014 at 12:50:05 UTC, matovitch wrote: > Hello ! > > I got a problem which I'm sure can be solved by a smart one liner. I would like to obtain the term by term product of a given range by the infinite cyclic range cycle([1,-1]). How can I do that ? dpaste seems to be somewhat slow. import std.range; import std.algorithm; import std.stdio; void main() { auto myRange = iota(0,10); foreach(e; myRange.zip(cycle([1,-1])).map!(a => a[0]*a[1])) writeln(e); } Like this? |
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | matovitch:
> I got a problem which I'm sure can be solved by a smart one liner. I would like to obtain the term by term product of a given range by the infinite cyclic range cycle([1,-1]). How can I do that ?
void main() {
import std.stdio, std.range, std.algorithm;
auto r = [10, 20, 30, 40, 50];
auto p = cycle([1, -1]);
auto result = r.zip(p).map!(rp => rp[0] * rp[1]);
result.writeln;
}
But it's easy to avoid the multiplication and replace it with a conditional neg.
Bye,
bearophile
|
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Sunday, 26 January 2014 at 13:05:55 UTC, Stanislav Blinov wrote:
> On Sunday, 26 January 2014 at 12:50:05 UTC, matovitch wrote:
>> Hello !
>>
>> I got a problem which I'm sure can be solved by a smart one liner. I would like to obtain the term by term product of a given range by the infinite cyclic range cycle([1,-1]). How can I do that ?
>
> dpaste seems to be somewhat slow.
>
> import std.range;
> import std.algorithm;
> import std.stdio;
>
> void main() {
>
> auto myRange = iota(0,10);
>
> foreach(e; myRange.zip(cycle([1,-1])).map!(a => a[0]*a[1]))
> writeln(e);
>
> }
>
> Like this?
Exactly ! I just found this solution too. Thanks.
|
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sunday, 26 January 2014 at 13:06:38 UTC, bearophile wrote:
> matovitch:
>
>> I got a problem which I'm sure can be solved by a smart one liner. I would like to obtain the term by term product of a given range by the infinite cyclic range cycle([1,-1]). How can I do that ?
>
> void main() {
> import std.stdio, std.range, std.algorithm;
> auto r = [10, 20, 30, 40, 50];
> auto p = cycle([1, -1]);
> auto result = r.zip(p).map!(rp => rp[0] * rp[1]);
> result.writeln;
> }
>
>
> But it's easy to avoid the multiplication and replace it with a conditional neg.
>
> Bye,
> bearophile
How would you do this ?
map!(a => (a.index & 1) ? a : -a)([1, 2]) ? (index field isn't available of course)
|
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | >> But it's easy to avoid the multiplication and replace it with a conditional neg.
>>
>> Bye,
>> bearophile
>
> How would you do this ?
>
> map!(a => (a.index & 1) ? a : -a)([1, 2]) ? (index field isn't available of course)
import std.range;
import std.algorithm;
import std.stdio;
void main() {
auto myRange = iota(0,10);
auto index = sequence!((a,n) => a[0]+n)(1);
auto result = myRange.zip(index).map!(a => a[1] & 1 ? a[0] : -a[0]);
result.writeln;
}
|
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Sunday, 26 January 2014 at 13:21:24 UTC, Stanislav Blinov wrote:
>>> But it's easy to avoid the multiplication and replace it with a conditional neg.
>>>
>>> Bye,
>>> bearophile
>>
>> How would you do this ?
>>
>> map!(a => (a.index & 1) ? a : -a)([1, 2]) ? (index field isn't available of course)
>
> import std.range;
> import std.algorithm;
> import std.stdio;
>
> void main() {
>
> auto myRange = iota(0,10);
>
> auto index = sequence!((a,n) => a[0]+n)(1);
> auto result = myRange.zip(index).map!(a => a[1] & 1 ? a[0] : -a[0]);
> result.writeln;
> }
Zipping an index array is uglier in my opinion... ;-)
|
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | Now DMD compiler segfaulted. Here is my code if you are interested... The berstein.d file : import std.array; import std.range; import std.traits; import std.algorithm; bool isBernstein(alias K)() { static if (isArray!(typeof(K)) && (K.empty || isNumeric!(typeof(K[0])))) return true; return false; } struct Bernstein(alias K, int S) if (isBernstein!(K)) { immutable typeof(K) kernel = K; immutable int shift = S; } template reverse(alias B) { alias reverse = Bernstein!(array(retro(B.kernel)), - (B.shift + cast(int)B.kernel.length - 1)); } template alternate(alias B) { alias alternate = Bernstein!( array(map!(a => a[0] * a[1])(zip(B.kernel, cycle([-1, 1])))), B.shift); } and the berstein_test.d file : import berstein; import std.stdio; import std.range; import std.algorithm; void main() { alternate!(Bernstein!([1.,1.], 0)) haar_scale; writeln(haar_scale.kernel); writeln(haar_scale.shift); } I get the following error message : /usr/include/dmd/phobos/std/range.d(4220): Error: Internal Compiler Error: CTFE literal Tuple(void, void)._expand_field_0 dmd: ctfeexpr.c:359: Expression* copyLiteral(Expression*): Assertion `0' failed. Aborted (core dumped) |
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | On Sunday, 26 January 2014 at 13:24:06 UTC, matovitch wrote:
> Zipping an index array is uglier in my opinion... ;-)
Extract it into a function and stick it into your library, it's extremely useful :)
import std.range;
import std.algorithm;
import std.stdio;
auto enumerate(R)(R r) {
return zip(sequence!((a,n) => a[0]+n)(0), r);
}
void main() {
auto myRange = iota(0,10);
auto result = myRange.enumerate.map!(a => a[0] & 1 ? -a[1] : a[1]);
result.writeln;
}
We need generic enumerate() in Phobos :(
|
January 26, 2014 Re: Alternate signs in a range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov |
> Extract it into a function and stick it into your library, it's extremely useful :)
Anyway, the proposed solutions use twice much memory than a simple for loop...is the compiler smart enougth to optimize this kind of code ?
|
Copyright © 1999-2021 by the D Language Foundation