1 /** Pythogorean triple generators. 2 * 3 * See_Also: https://forum.dlang.org/post/q08qsm$22j3$1@digitalmars.com 4 */ 5 module nxt.pythogorean_triples; 6 7 /// Pythogorean triple generator rangeg. 8 struct PossiblePythagoreanTriples(T) 9 { 10 /// Pythogorean triple. 11 struct Triple 12 { 13 T x, y, z; 14 version(none) 15 @property void toString(scope void delegate(scope const(char)[]) @safe sink) const @safe 16 { 17 import std.conv : to; 18 sink(x.to!string); 19 sink(","); 20 sink(y.to!string); 21 sink(","); 22 sink(z.to!string); 23 } 24 } 25 26 @property Triple front() const 27 { 28 return _front; 29 } 30 31 void nextTriple() 32 { 33 if (++_front.y == _front.z) 34 { 35 if (++_front.x == _front.z) 36 { 37 ++_front.z; // if `_front.z` becomes 0 empty should be true 38 _front.x = 1; 39 } 40 _front.y = _front.x; 41 } 42 } 43 44 void popFront() 45 { 46 do 47 { 48 nextTriple(); 49 } while (_front.x*_front.x + _front.y*_front.y != _front.z*_front.z); 50 } 51 52 enum empty = false; 53 54 private Triple _front = Triple(1, 1, 2); 55 } 56 57 /// Get all Pythogorean triples in an infinite generator. 58 auto pythagoreanTriples(T = size_t)() 59 { 60 return PossiblePythagoreanTriples!T(); 61 } 62 63 /// 64 @safe pure nothrow @nogc unittest 65 { 66 auto t = pythagoreanTriples!size_t; 67 alias Triple = typeof(t.front); 68 assert(t.front == Triple(1,1,2)); t.popFront(); 69 assert(t.front == Triple(3,4,5)); t.popFront(); 70 assert(t.front == Triple(6,8,10)); t.popFront(); 71 assert(t.front == Triple(5,12,13)); t.popFront(); 72 assert(t.front == Triple(9,12,15)); t.popFront(); 73 assert(t.front == Triple(8,15,17)); t.popFront(); 74 assert(t.front == Triple(12,16,20)); t.popFront(); 75 }