std.string and ranges
Denis Koroskin
2korden at gmail.com
Thu Feb 12 03:41:26 PST 2009
On Thu, 12 Feb 2009 07:46:31 +0300, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> Andrei Alexandrescu wrote:
>> Denis Koroskin wrote:
>> [about shuffling ranges]
>>> I'm with bearophile here. Not because his version is shorter, but
>>> because
>>> 1) some containers/ranges might not have a dup method
>>> 2) it is potentially faster because it may avoid unnecessary data
>>> copying (relevant for large arrays).
>>>
>>> That said, having both versions is preferred by me with names like
>>> shuffle and shuffledCopy.
>>> The same could be applied to sort - sortedCopy might be useful, too.
>> Oh, I understand now. Incidentally topNCopy exists already, and it
>> becomes a sortedCopy for n = input.length. But perhaps an explicit
>> function would drive the point home better.
>> About shuffleCopy, you and Leonardo are both right that it could be
>> significantly faster than copying and then shuffling the copy. The
>> solution that I see most in the spirit of the new range design is to
>> have a ShuffledRange that, given another range, iterates it in a random
>> manner. An ordinary copy() call closes the deal if a copy is needed.
>
> Wait, I take that back. I don't know of solid ways to sort into a copy
> or shuffle into a copy. For shuffling I'd need auxiliary memory (in
> addition to the copy itself), and for sorting I'd be better off copying
> and then sorting in place. Could anyone illuminate me about better ways?
>
> Andrei
That's why I said it /might/ be faster. It doesn't have to, the default
implementation may look as follows:
typeof(Range.first)[] shuffledCopy(Range)(Range range)
{
return shuffle(createCopy(range));
}
However, it may be implemented quite differently if not inplace. For this
to work we need two primitives that I didn't find in std.range (I know
names are not good, feel free to rename them as you please):
struct RandomNumbers(Rnd = Random)
{
// ...
}
A finite range of length 'max' that generates random numbers in interval
[0..max) without repeating. An example:
Random rnd;
auto gen = RandomNumbers(10, rnd);
foreach (n; gen) {
writefln(n);
}
Sample output:
2
6
8
1
4
7
5
9
0
3
Sample implementation is attached.
Next we need RandomItems - a finite range the acepts a random access range
and returns random elements one-by-one without repeating:
struct RandomItems(Range, Rnd = Random)
{
// ...
}
It makes use of RandomNumbers generator and is very simple (sample source
attached, too). Now we can create shuffledCopy easily:
auto shuffledCopy(Range)(Range range)
{
auto gen = RandomItems!(Range)(range);
typeof(range[0])[] copy = new typeof(range[0])[range.length];
foreach (ref elem; copy) {
elem = gen.head;
gen.next();
}
return copy;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.d
Type: application/octet-stream
Size: 2859 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20090212/2cd19484/attachment.obj>
More information about the Digitalmars-d
mailing list