在枚举限制上使用按位运算获取反向

时间:2016-09-23 20:33:02

标签: javascript bit-manipulation lodash bitwise-operators pathing

快速而肮脏的问题。我感觉到我在一些看似简单的事情上缺少一些关于按位操作的基本知识。

我想解决的问题如下:

我有1到8之间的整数枚举,表示从网格中的位置移动的所有可能矢量。
(我想你们中的一些人可能会认识到这个问题)

{
    TOP: 1,
    TOP_RIGHT: 2,
    RIGHT: 3,
    BOTTOM_RIGHT: 4,
    BOTTOM: 5,
    BOTTOM_LEFT: 6,
    LEFT: 7,
    TOP_LEFT: 8,
}

给定网格上的位置路径,在两点之间,这些可用于表示沿该路径的移动。

[
  {x: 22, y: 30}, 
  {x: 22, y: 29}, 
  {x: 22, y: 28}, 
  {x: 23, y: 27}, 
  {x: 24, y: 26}, 
  {x: 25, y: 25}, 
  {x: 26, y: 25}, 
  {x: 27, y: 24},
  {x: 26, y: 23},
  {x: 27, y: 22},
  {x: 26, y: 22}
]

最终表示为字符串

"1122232827"

如何最好地反转方向?

我一直在尝试使用不同的按位操作来尽可能快地完成此操作,但我无法弄明白(这是一个很大的瓶颈)。到目前为止,我一直在使用速记,只是检查方向是否超过限制的一半,然后删除或添加一半。但是,我再次感觉到这可以通过一些按位的jiggery更有效地完成。请随意使用以下代码执行任何操作。

注意:查找地图,方向向量和获取方向的方法是常量, 无法 更改。它们实际上是对特定API引擎下发生的事情的解释,并且可能更好地实现。

// Enum of vectors
let vectors = {
	TOP: 1,
	TOP_RIGHT: 2,
	RIGHT: 3,
	BOTTOM_RIGHT: 4,
	BOTTOM: 5,
	BOTTOM_LEFT: 6,
	LEFT: 7,
	TOP_LEFT: 8,
};
_.extend(window, vectors); // Add them to global

// Lookup table for vectors
let dirMap = {
	1:    { 1: TOP_RIGHT, 0: RIGHT, "-1": BOTTOM_RIGHT },
	0:    { 1: TOP, "-1": BOTTOM, },
	"-1": { 1: TOP_LEFT, 0: LEFT, "-1": BOTTOM_LEFT }
};

// Get the direction key
function getDirection(a, b){
	return dirMap[b.x - a.x][a.y - b.y];
}

// Example path
let path = [   
	{x: 22, y: 30}, 
	{x: 22, y: 29}, 
	{x: 22, y: 28}, 
	{x: 23, y: 27}, 
	{x: 24, y: 26}, 
	{x: 25, y: 25}, 
	{x: 26, y: 25}, 
	{x: 27, y: 24},
	{x: 26, y: 23},
	{x: 27, y: 22},
	{x: 26, y: 22}
];

let strPath = "", strInverted = "";

for(let i = 1, len = path.length; i < len; i++){
	let prev = path[i - 1];
	let direction = getDirection(prev, path[i]);
	let inverse = direction + (direction > 4 ? -4 : 4); // Can I turn this into a bitwise operation?
	strPath += direction;
	strInverted = inverse + strInverted;
}

console.log("Forward: ", strPath);
console.log("Reverse: ", strInverted);

document.getElementById("forward").innerHTML = strPath;
document.getElementById("reverse").innerHTML = strInverted;

// Just for debugging purposes
function getDirString(dirString){
	let arrDir = [];
  _.each(dirString, function(c){
  	let val = parseInt(c), dir = "";
    _.find(vectors, function(o, i){ if(o === val){ dir = i; return true; }});
    arrDir.push(dir);
	});
  return arrDir.join(", ");
}

document.getElementById("full_forward").innerHTML = getDirString(strPath);
document.getElementById("full_reverse").innerHTML = getDirString(strInverted);
body{ font-family: Arial, Helvetica, sans-serif; }

#forward:before, #reverse:before, #full_forward:before, #full_reverse:before{
  display: inline-block;
  margin-right: 1em;
  width: 4em;
}

#full_forward, #full_reverse{font-size: 0.7em; white-space: nowrap;}

#forward:before{ content: "Forward:"; }
#reverse:before{ content: "Reverse:"; }
#full_forward:before{ content: "Forward:"; }
#full_reverse:before{ content: "Reverse:"; }
<script src="https://cdn.jsdelivr.net/lodash/2.1.0/lodash.compat.js"></script>

<div id="forward"></div>
<div id="reverse"></div>
<br>
<div id="full_forward"></div>
<div id="full_reverse"></div>

Here's a jsfiddle to play with.

白板我在过去一小时左右一直盯着看 whiteboard of ultimate scratchheading

1 个答案:

答案 0 :(得分:1)

我不认为你想在这里进行按位操作,我实际上认为一个具有硬编码值的数组,你只需将你的值作为索引填充就可以了。当然它不是内存效率,但你的列表只有8的长度,所以它可以忽略不计。

试试这个:

var inverseDirList = [5,6,7,8,1,2,3,4];
var invertedDirection = inverseDirList[direction - 1];

如果你真的关心不对方向值进行任何算术运算,你可以简单地在列表的开头添加一个stub元素,比如-1,所以它基本上是从1开始的

正如其他人提到的,您可以使用devTools来检查性能并进行比较,但根据此stackoverflow question/answer JS散列/数组查找具有恒定的时间复杂度