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