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 void toString(Sink)(ref scope Sink 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 => _front; 27 28 void nextTriple() 29 { 30 if (++_front.y == _front.z) 31 { 32 if (++_front.x == _front.z) 33 { 34 ++_front.z; // if `_front.z` becomes 0 empty should be true 35 _front.x = 1; 36 } 37 _front.y = _front.x; 38 } 39 } 40 41 void popFront() 42 { 43 do 44 { 45 nextTriple(); 46 } while (_front.x*_front.x + _front.y*_front.y != _front.z*_front.z); 47 } 48 49 enum empty = false; 50 51 private Triple _front = Triple(1, 1, 2); 52 } 53 54 /// Get all Pythogorean triples in an infinite generator. 55 auto pythagoreanTriples(T = size_t)() 56 => PossiblePythagoreanTriples!T(); 57 58 /// 59 @safe pure nothrow @nogc unittest 60 { 61 auto t = pythagoreanTriples!size_t; 62 alias Triple = typeof(t.front); 63 assert(t.front == Triple(1,1,2)); t.popFront(); 64 assert(t.front == Triple(3,4,5)); t.popFront(); 65 assert(t.front == Triple(6,8,10)); t.popFront(); 66 assert(t.front == Triple(5,12,13)); t.popFront(); 67 assert(t.front == Triple(9,12,15)); t.popFront(); 68 assert(t.front == Triple(8,15,17)); t.popFront(); 69 assert(t.front == Triple(12,16,20)); t.popFront(); 70 }