| 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
Permalink
Reply