Re: rotate left an array

2022-10-04 Thread Christian Köstlin via Digitalmars-d-learn
If you are ok with using things from std.range you could use something 
like this:



```d
import std.range : cycle, drop, take;
import std.stdio : writeln;

int main(string[] args)
{
auto r = [1, 2, 3, 4, 5, 6, 7, 8];
writeln(r.cycle.drop(3).take(r.length));
return 0;
}
```

Kind regards,
Christian




Re: rotate left an array

2022-10-03 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Oct 03, 2022 at 05:38:25PM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
[...]
> Good catch but I think what we want is a copy of the front element, at
> least for InputRanges (.save does not work for File.byLine :/).

One of the things we need to settle in Phobos v2 is what to do with
transient ranges like File.byLine (i.e., ranges whose .front value is
invalidated by .popFront).  When you don't need to access each line
after calling .popFront, .byLine's current implementation reduces
allocations and decreases GC pressure.  However, when you do need to
save it, it produces counterintuitive results, like here.


> What is the generic way of copying an element? I wonder whether we
> have to use isSomeString to take care of all element types.
[...]

This was discussed many years ago.  There is no generic way to copy an
element, because there is no language-wide .clone method that enforces
the right semantics for every type.  You cannot simply deep-copy
something, as might be a tempting solution at first glance, because you
cannot tell, for an arbitary type, whether a reference member is meant
to be an owning reference (the referent needs to be cloned) or a
non-owning reference (the referent should not be cloned).  Both are
valid use cases, and there is no way to distinguish between them without
contextual knowledge of the type.

For example, if your range is generating, say, a tree of objects each
time .popFront is called, then you probably want to deep-copy the object
tree when you're saving the element.  However, if the range is iterating
over, say, some nodes in a preexisting graph, then you probably *don't*
want to be duplicating graph nodes when you save the value of .front,
because in this case .front merely references these nodes, it doesn't
own them.  Without application-specific knowledge, you can't tell which
of these cases you're dealing with.


T

-- 
Customer support: the art of getting your clients to pay for your own 
incompetence.


Re: rotate left an array

2022-10-03 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 4 October 2022 at 00:38:25 UTC, Ali Çehreli wrote:
Good catch but I think what we want is a copy of the front 
element, at least for InputRanges (.save does not work for 
File.byLine :/).


What is the generic way of copying an element? I wonder whether 
we have to use isSomeString to take care of all element types.


AFAIK there is no generic way to perform a deep copy of an 
arbitrary value in D. You could write a function to do it for all 
built-in types, but you might still run into trouble with 
user-defined types (e.g., how do you deep-copy a RefCounted!T 
without any knowledge of its specific semantics?).


I guess you could use a hybrid approach; e.g.,

static if (isDeepCopyable!(ElementType!R))
auto fr = range.front.deepCopy;
else
auto fr = range.front.save;

This would make it possible to accommodate some pure input ranges 
(including File.byLine), but would still require a forward range 
in the general case.


Re: rotate left an array

2022-10-03 Thread rassoc via Digitalmars-d-learn

On 10/3/22 23:06, Ali Çehreli via Digitalmars-d-learn wrote:

auto rotatedView(R)(R range)


Or even more generic by chaining two slices in case the range permits it:

auto rotatedView(R)(R range, long n = 1)
if (...)
{
if (n == 0) return range;
...
n %= range.length;
...
return chain(slice1, slice2);
}

Used something like that in previous advent of code challenges where they 
expect you to go for doubly linked lists due to large buffer size.


Re: rotate left an array

2022-10-03 Thread Ali Çehreli via Digitalmars-d-learn

On 10/3/22 17:00, Paul Backus wrote:
> On Monday, 3 October 2022 at 21:06:36 UTC, Ali Çehreli wrote:
>> On 10/3/22 13:48, Andrey Zherikov wrote:
>>> a "rotated view".
>>
>> Without indexes:
>>
>> import std.range : empty;
>>
>> auto rotatedView(R)(R range)
>> in (!range.empty)
>> {
>> import std.range : chain, front, only, popFront;
>> const fr = range.front;
>> range.popFront();
>> return chain(range, only(fr));
>> }
>
> Tiny nitpick: this should use
>
>  const fr = range.save.front;
>
> ...to ensure that `fr` is not invaliated or overwritten by the
> subsequent call to range.popFront (e.g., think of File.byLine here).

Good catch but I think what we want is a copy of the front element, at 
least for InputRanges (.save does not work for File.byLine :/).


What is the generic way of copying an element? I wonder whether we have 
to use isSomeString to take care of all element types.


Ali




Re: rotate left an array

2022-10-03 Thread Paul Backus via Digitalmars-d-learn

On Monday, 3 October 2022 at 21:06:36 UTC, Ali Çehreli wrote:

On 10/3/22 13:48, Andrey Zherikov wrote:

a "rotated view".


Without indexes:

import std.range : empty;

auto rotatedView(R)(R range)
in (!range.empty)
{
import std.range : chain, front, only, popFront;
const fr = range.front;
range.popFront();
return chain(range, only(fr));
}


Tiny nitpick: this should use

const fr = range.save.front;

...to ensure that `fr` is not invaliated or overwritten by the 
subsequent call to range.popFront (e.g., think of File.byLine 
here).


Re: rotate left an array

2022-10-03 Thread Ali Çehreli via Digitalmars-d-learn

On 10/3/22 13:48, Andrey Zherikov wrote:

a "rotated view".


Without indexes:

import std.range : empty;

auto rotatedView(R)(R range)
in (!range.empty)
{
import std.range : chain, front, only, popFront;
const fr = range.front;
range.popFront();
return chain(range, only(fr));
}

void main()
{
import std.algorithm : equal;
int[] arr1 = [ 1, 2, 3, 4 ];
assert(arr1.rotatedView.equal([ 2, 3, 4, 1 ]));

// Now this is getting a little expensive! :)
assert(arr1
   .rotatedView
   .rotatedView
   .equal([ 3, 4, 1, 2 ]));
}

Ali




Re: rotate left an array

2022-10-03 Thread Andrey Zherikov via Digitalmars-d-learn

On Monday, 3 October 2022 at 18:09:05 UTC, Fausto wrote:

Hello all,

I am trying to rotate left an array.
I found a very basic way, and I am not sure if there is 
something clever than this :) maybe using slices...
the external for represents how many times you are rotating (in 
this case 2).


If you don't need to add or remove the data from your array then 
I'd go with constant array and translating external index to an 
internal one for this array. So it's gonna be something like a 
"rotated view".


Re: rotate left an array

2022-10-03 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 3 October 2022 at 18:09:05 UTC, Fausto wrote:

Hello all,

I am trying to rotate left an array.
I found a very basic way, and I am not sure if there is 
something clever than this :) maybe using slices...


Here we can't use slice assignment instead of the inner loop 
because that doesn't work for an overlapping slice. (Instead 
there's `copy` in std.algorithm).


The algorithm you wrote doesn't scale the best for speed - yours 
is the second one mentioned here:

https://www.geeksforgeeks.org/array-rotation/

Phobos has `bringToFront(arr[0..2], arr[2..$])` which does the 
same thing as a `rotate(arr, 2)` function. It seems to use the 
third algorithm from the link (or at least has the same time and 
space complexity).


The first algorithm may also work better in some cases, when 
swapping is expensive or when the result is duplicated anyway.




rotate left an array

2022-10-03 Thread Fausto via Digitalmars-d-learn

Hello all,

I am trying to rotate left an array.
I found a very basic way, and I am not sure if there is something 
clever than this :) maybe using slices...
the external for represents how many times you are rotating (in 
this case 2).


```d
void main()
{
import std.range;
import std.stdio: write, writeln, writef, writefln;

int[] arr1 = [ 1, 2, 3, 4 ];
int t = 0;

writeln(arr1);

for (int j = 0;j<2;j++) {
t = arr1[0];
for(int i = 0;i