Task

Show the first   30   positive integers which are squares but not cubes of such integers.

Optionally, show also the first   3   positive integers which are both squares and cubes,   and mark them as such.




import std.algorithm;
import std.range;
import std.stdio;
 
auto squareGen() {
    struct Gen {
        private int add = 3;
        private int curr = 1;
 
        bool empty() {
            return curr < 0;
        }
 
        auto front() {
            return curr;
        }
 
        void popFront() {
            curr += add;
            add += 2;
        }
    }
 
    return Gen();
}
 
auto cubeGen() {
    struct Gen {
        private int add1 = 7;
        private int add2 = 12;
        private int curr = 1;
 
        bool empty() {
            return curr < 0;
        }
 
        auto front() {
            return curr;
        }
 
        void popFront() {
            curr += add1;
            add1 += add2;
            add2 += 6;
        }
    }
 
    return Gen();
}
 
auto merge() {
    struct Gen {
        private auto sg = squareGen();
        private auto cg = cubeGen();
 
        bool empty() {
            return sg.empty || cg.empty;
        }
 
        auto front() {
            import std.typecons;
            if (sg.front == cg.front) {
                return tuple!("num", "isCube")(sg.front, true);
            } else {
                return tuple!("num", "isCube")(sg.front, false);
            }
        }
 
        void popFront() {
            while (true) {
                if (sg.front < cg.front) {
                    sg.popFront();
                    return;
                } else if (sg.front == cg.front) {
                    sg.popFront();
                    cg.popFront();
                    return;
                } else {
                    cg.popFront();
                }
            }
        }
    }
 
    return Gen();
}
 
void main() {
    foreach (p; merge.take(33)) {
        if (p.isCube) {
            writeln(p.num, " (also cube)");
        } else {
            writeln(p.num);
        }
    }
}