Skip to content

Instantly share code, notes, and snippets.

@simendsjo
Created June 4, 2011 11:56
Show Gist options
  • Save simendsjo/1007840 to your computer and use it in GitHub Desktop.
Save simendsjo/1007840 to your computer and use it in GitHub Desktop.
/* 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