Challenge: Make a data type for holding one of 8 directions allowing increment and overflow
Liam McGillivray
yoshi.pit.link.mario at gmail.com
Tue Mar 12 22:00:58 UTC 2024
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.
More information about the Digitalmars-d-learn
mailing list