A few range questions

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jan 5 11:42:42 PST 2016


On 01/05/2016 10:47 AM, Charles Smith wrote:

 >          auto result = 1_000.iota.map!(a => a.repeat(count(arr[],
 > a))).chain.array;

You are traversing the array per index value (1000 times), which can be 
done once up front:

enum elementCount = 1_000_000;
enum valueCount = 1000;

void main() {
     import std.conv : to;
     import std.datetime;
     import std.random;
     import std.stdio;

     int[elementCount] arr;

     for(int i; i < arr.length; ++i)
         arr[i] = uniform(0, valueCount);

     // Now they get their own arrays:
     auto benchmarks = benchmark!(() => algorithmSort(arr.dup),
                                  () => countingSort(arr.dup))(1);

     writeln("Algorithm's Sort: ", to!Duration(benchmarks[0]));
     writeln("Counting Sort   : ", to!Duration(benchmarks[1]));
}

auto algorithmSort(int[] arr) {
     import std.algorithm : sort, sum;

     auto result = sort(arr[]);
     return result.sum;
}

auto countingSort(int[] arr) {
     import std.algorithm : count, map, joiner, sum, each;
     import std.range : array, repeat, enumerate;

     uint[valueCount] hist;
     arr.each!(a => ++hist[a]);

     auto result = hist[].enumerate.map!(t => t[0].repeat(t[1])).joiner;
     // To make sure that we consume the lazy range:
     return result.sum;
}

 > 2. I noticed that result within `countingSort` is an array of arrays. I
 > thought `chain` would concat them... did I miss something obvious?

I think .joiner is what you're looking for.

 > 3. It's kind of hard to compare performance because of (1), but is there
 > a better way to do this?

I changed the code to pass each function a different array.

My results with -O -inline -noboundscheck:

Algorithm's Sort: 76 ms, 910 μs, and 8 hnsecs
Counting Sort   : 21 ms, 563 μs, and 9 hnsecs

Ali



More information about the Digitalmars-d-learn mailing list