Created
June 4, 2011 11:56
-
-
Save simendsjo/1007840 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Written in the D Programming Language (D2) | |
* | |
* http://projecteuler.net/index.php?section=problems&id=1 | |
* | |
* If we list all the natural numbers below 10 that are multiples of 3 or 5, we | |
* get 3, 5, 6 and 9. The sum of these multiples is 23. | |
* | |
* Find the sum of all the multiples of 3 or 5 below 1000. | |
*/ | |
import std.stdio : writefln; | |
import std.conv : to; | |
import std.datetime : StopWatch; | |
import std.parallelism; | |
import std.range : iota; | |
enum uint BELOW = 100_000; | |
template SumMultiple3Or5(ulong Current, uint Below, ulong Sum) { | |
static if(Current >= Below) | |
enum SumMultiple3Or5 = Sum; | |
else static if(Current % 3 == 0 || Current % 5 == 0) | |
enum SumMultiple3Or5 = SumMultiple3Or5!(Current+1, Below, Sum+Current); | |
else | |
enum SumMultiple3Or5 = SumMultiple3Or5!(Current+1, Below, Sum); | |
} | |
template SumMultiple3Or5(uint Below) { | |
enum SumMultiple3Or5 = SumMultiple3Or5!(0, Below, 0); | |
} | |
unittest { | |
static assert(SumMultiple3Or5!0 == 0); | |
static assert(SumMultiple3Or5!3 == 0); | |
static assert(SumMultiple3Or5!4 == 3); | |
static assert(SumMultiple3Or5!5 == 3); | |
static assert(SumMultiple3Or5!6 == 3+5); | |
static assert(SumMultiple3Or5!7 == 3+5+6); | |
static assert(SumMultiple3Or5!9 == 3+5+6); | |
static assert(SumMultiple3Or5!10 == 3+5+6+9); | |
static assert(SumMultiple3Or5!11 == 3+5+6+9+10); | |
} | |
// Error: recursive expansion | |
//pragma(msg, SumMultiple3Or5!BELOW); | |
pure nothrow ulong SumMultiple3Or5_ctfe(uint below) { | |
ulong sum; | |
foreach(i; 0..below) { | |
if(i % 3 == 0 || i % 5 == 0) | |
sum += i; | |
} | |
return sum; | |
} | |
unittest { | |
static assert(SumMultiple3Or5_ctfe(0) == 0); | |
static assert(SumMultiple3Or5_ctfe(3) == 0); | |
static assert(SumMultiple3Or5_ctfe(4) == 3); | |
static assert(SumMultiple3Or5_ctfe(5) == 3); | |
static assert(SumMultiple3Or5_ctfe(6) == 3+5); | |
static assert(SumMultiple3Or5_ctfe(7) == 3+5+6); | |
static assert(SumMultiple3Or5_ctfe(9) == 3+5+6); | |
static assert(SumMultiple3Or5_ctfe(10) == 3+5+6+9); | |
static assert(SumMultiple3Or5_ctfe(11) == 3+5+6+9+10); | |
} | |
ulong SumMultiple3Or5_parallel(uint below) { | |
ulong sum; | |
foreach(i; parallel(iota(below))) { | |
if(i % 3 == 0 || i % 5 == 0) | |
sum += i; | |
} | |
return sum; | |
} | |
// have to be global when used in amap | |
pure nothrow ulong match(uint i) { | |
return (i % 3 == 0 || i % 5 == 0) ? i : 0; | |
} | |
ulong SumMultiple3Or5_parallel_functional(uint below) { | |
return taskPool.reduce!"a+b"(taskPool.amap!(match)(iota(below))); | |
} | |
enum ctfeAnswer = SumMultiple3Or5_ctfe(BELOW); | |
pragma(msg, "Calculating for: ", BELOW, ", Answer: ", ctfeAnswer); | |
void main() { | |
writefln("For %s", BELOW); | |
writefln("CTFE Answer : %s", ctfeAnswer); | |
uint rtBelow = BELOW; | |
StopWatch sw; | |
sw.start(); | |
immutable runtimeAnswer = SumMultiple3Or5_ctfe(rtBelow*10); | |
sw.stop(); | |
assert(runtimeAnswer == ctfeAnswer); | |
writefln("RUNTIME Answer : %s\n\tTime (hnsecs): %s", runtimeAnswer, sw.peek().hnsecs); | |
sw.reset(); | |
sw.start(); | |
immutable parallelAnswer = SumMultiple3Or5_parallel(rtBelow*10); | |
sw.stop(); | |
assert(parallelAnswer == ctfeAnswer); | |
writefln("PARALLEL Answer: %s\n\tTime (hnsecs): %s", parallelAnswer, sw.peek().hnsecs); | |
sw.reset(); | |
sw.start(); | |
immutable parallelAnswer2 = SumMultiple3Or5_parallel_functional(rtBelow*10); | |
sw.stop(); | |
assert(parallelAnswer2 == ctfeAnswer); | |
writefln("PARALLEL Answer: %s\n\tTime (hnsecs): %s", parallelAnswer2, sw.peek().hnsecs); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment