On Tuesday, 12 March 2024 at 06:38:28 UTC, Richard (Rikki) Andrew
Cattermole wrote:
By taking advantage of integer wrapping and a bitwise and, its
quite a simple problem to solve!
Challenge for the reader: add support for binary operations and
toString support.
https://dlang.org/spec/operatoroverloading.html
```d
struct Direction {
private int value;
Direction opUnary(string op:"++")() {
value++;
value &= 7;
return this;
}
Direction opUnary(string op:"--")() {
value--;
value &= 7;
return this;
}
void opOpAssign(string op:"+")(int amount) {
value += amount;
value &= 7;
}
void opOpAssign(string op:"-")(int amount) {
value -= amount;
value &= 7;
}
enum Direction N = Direction(0);
enum Direction NE = Direction(1);
enum Direction E = Direction(2);
enum Direction SE = Direction(3);
enum Direction S = Direction(4);
enum Direction SW = Direction(5);
enum Direction W = Direction(6);
enum Direction NW = Direction(7);
}
unittest {
Direction direction = Direction.N;
direction++;
assert(direction == Direction.NE);
direction+=3;
assert(direction == Direction.S);
direction--;
assert(direction == Direction.SE);
direction-=4;
assert(direction == Direction.NW);
}
```
Interesting. I didn't know that an enum can be defined inside a
struct like that. I had used functions to get around it.
Here is what I had already mostly written, using help from
ChatGPT (but only for the opUnary syntax, not the algorithm):
```
struct Direction //One of 8 directions stored in 3 bits
{
bool[3] d;
static Direction N() { return
Direction(d:[false,false,false]); }
static Direction NE() { return
Direction(d:[false,false,true]); }
static Direction E() { return
Direction(d:[false,true,false]); }
static Direction SE() { return
Direction(d:[false,true,true]); }
static Direction S() { return
Direction(d:[true,false,false]); }
static Direction SW() { return
Direction(d:[true,false,true]); }
static Direction W() { return Direction(d:[true,true,false]);
}
static Direction NW() { return Direction(d:[true,true,true]);
}
ref Direction opUnary(string op)() if (op == "++" || op ==
"--") {
if (op == "++") const bool up = true;
else const bool up = false;
if (d[0]) {
if (d[1]) d[2] = !d[2];
d[1] = !d[1];
}
d[0] = !d[0];
return this;
}
auto to(T)() const {
return cast(T)(d[0] + 2*d[1] + 4*d[2]);
}
}
```
I am not entirely sure how well it works. I will come back later
with an updated version with more functions.
I'm not familiar with the syntax of the line `value &= 7;`. Is it
equivalent to writing `value = value % 7;`?
Anyway, you used an int, but I used an array of 3 bools. I'm
guessing that mine uses less memory, but I'm not sure how memory
it adds when it's a struct with functions.