假设我有一个枚举Direction,指定基数(和心轴间)方向:
public enum Direction
{
None = 0,
Up = 1 << 1,
Down = 1 << 2,
Left = 1 << 3,
Right = 1 << 4,
UpLeft = Up | Left,
UpRight = Up | Right,
DownLeft = Down | Left,
DownRight = Down | Right
}
Run Code Online (Sandbox Code Playgroud)
在不引入冲突方向(向上和向下)的情况下,为了反转任意方向,我可以执行的最短逐位运算是什么?
我知道我可以使用三级语句来有效地处理这个问题
public Direction Inverse (Direction d) {
// Inverse of Direction.None should still be none
if (d == Direction.None) { return d; }
Direction dInvert = (d.HasFlag(Direction. Up)) ? Direction.Down : Direction.Up;
dInvert |= (d.HasFlag(Direction.Left)) ? Direction.Right : Direction.Left;
return dInvert;
}
Run Code Online (Sandbox Code Playgroud)
但我宁愿学习如何使用二元运算符处理这种"对称枚举反转".如果没有代码打高尔夫,我能想到的最好的是
dir ^ (Direction.Up | Direction.Down)
Run Code Online (Sandbox Code Playgroud)
但这显然只有在dir不包含任何水平'组件' 时才有效.
枚举应该看起来像这样(因此减少了一个1 << 0 == 1):
public enum Direction
{
None = 0,
Up = 1 << 0,
Down = 1 << 1,
Left = 1 << 2,
Right = 1 << 3,
UpLeft = Up | Left,
UpRight = Up | Right,
DownLeft = Down | Left,
DownRight = Down | Right
}
Run Code Online (Sandbox Code Playgroud)
让我们分析不同的可能性.这是一个带有标志和相应反转的表(只有最后8位)
+-----------+----------------+----------------+
| Direction | Flags | Inverted |
+---------------------------------------------+
| None | 0000 0000 = 0 | 0000 0000 = 0 |
| Up | 0000 0001 = 1 | 0000 0010 = 2 |
| Down | 0000 0010 = 2 | 0000 0001 = 1 |
| Left | 0000 0100 = 4 | 0000 1000 = 8 |
| Right | 0000 1000 = 8 | 0000 0100 = 4 |
| UpLeft | 0000 0101 = 5 | 0000 1010 = 10 |
| UpRight | 0000 1001 = 9 | 0000 0110 = 6 |
| DownLeft | 0000 0110 = 6 | 0000 1001 = 9 |
| DownRight | 0000 1010 = 10 | 0000 0101 = 5 |
+-----------+----------------+----------------+
Run Code Online (Sandbox Code Playgroud)
组合方向可以反转~dir & 0b1111,但我没有看到简单方向的简单按位操作.
让我们看一下十进制值.我们可以尝试推断一个函数.
inv.
^
10 | X
9 | X
8 | X
7 |
6 | X
5 | X
4 | X
3 |
2 | X
1 | X
0 X--+--+--+--+--+--+--+--+--+--+--> flag
0 1 2 3 4 5 6 7 8 9 10
Run Code Online (Sandbox Code Playgroud)
这看起来也不简单.
WolframAlpha可以从这些数字对中插入多项式
InterpolatingPolynomial [{{0,0},{1,2},{2,1},{4,8},{5,10},{6,9},{8,4},{9,6} ,{10,5}},x]
结果是:
- (X(X ^ 7 - 40×^ 6 + 686的x ^ 5 - 6580的x ^ 4 + 37709的x ^ 3 - 124180的x ^ 2 + 203524 X - 131280))/ 10080
uugh!
我会做一个反转字典
var inversion = new Dictionary<Direction, Direction> {
[Direction.None] = Direction.None,
[Direction.Up] = Direction.Down,
[Direction.Down] = Direction.Up,
[Direction.Left] = Direction.Right,
[Direction.Right] = Direction.Left,
[Direction.UpLeft] = Direction.DownRight,
[Direction.UpRight] = Direction.DownLeft,
[Direction.DownLeft] = Direction.UpRight,
[Direction.DownRight] = Direction.UpLeft
}
Run Code Online (Sandbox Code Playgroud)
并获得倒转的方向
Direction invDir = inversion[dir];
Run Code Online (Sandbox Code Playgroud)
最后,我发现了一个简单的解决方案:
如果你这样声明枚举:
public enum Direction
{
None = 0,
Up = 1,
Down = -1,
Left = 4,
Right = -4,
UpLeft = Up + Left,
UpRight = Up + Right,
DownLeft = Down + Left,
DownRight = Down + Right
}
Run Code Online (Sandbox Code Playgroud)
您可以通过使用二进制补码取负值来获得反转方向
~d + 1
foreach (Direction d in Enum.GetValues(typeof(Direction))) {
Console.WriteLine($"{d} ===> {~d + 1}");
}
Run Code Online (Sandbox Code Playgroud)
打印
无===>无
Up ===> Down
DownLeft ===> UpRight
Left ===> Right
UpLeft ===> DownRight
DownRight ===> UpLeft
Right ===> Left
UpRight ===> DownLeft
Down = ==> Up
简单地使用-d不起作用,因为-无法应用于枚举.你必须写(Direction)(-((int)dir)).
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |