在Javascript(Node.js)中分析此数组的最有效方法?

时间:2014-03-07 12:21:10

标签: javascript node.js algorithm

首先,我想指出这是服务器端的Node.js代码,而不是普通的客户端Javascript。我不想使用jQuery,但使用任何本机Node.js方法(如果你知道有任何潜在有用的方法)都可以。

这是纸牌游戏中的机器人玩家的代码。机器人有一手牌,结构如下:

[ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]

所以8张牌中的每张牌都是value+suit字符串。这是无法更改的,因为整个应用程序都适用于此结构。

现在,机器人必须分析此手以搜索某些卡片组合。例如,它应该找到任何“第三位国王”(国王至少有2张相同花色的小牌),“第二位数”(女王至少有1张相同花色的小牌)或“第三位皇后”。

在上面的例子中,它应该提出:第三王钻石和第三王牌俱乐部。

我正在寻找实现搜索算法来找到这些组合,但我担心这会非常低效。我的第一个想法是遍历数组以找到所有的国王,王后和10并将这些数据保存在某处,然后再次迭代它以计算我们拥有的同一套牌的其他牌数。例如,对于国王:

var kingsuits = [];
for(var i=0;i<8;i++){
    if(hand[i].substr(0,1) == "K")
        kingsuits.push(hand[i].substr(-1));
}
//now kingsuits has the suits of all kings, and we can go through our hand again and check how many cards we have in each of these suits...

我的问题是,有没有更有效的方法来实现这一目标?问题是,还有很多其他组合也应该被寻找,而不仅仅是我上面举例说明的那些组合。

另外 - 也许更重要的是 - 如果我们找到“第三位国王”,我们根本不需要寻找“第三位女王”或“第二位女王”。这些组合有一个明确的层次结构,所以如果我们找到第一个组合,我们根本不需要关心其他组合。

5 个答案:

答案 0 :(得分:3)

使用二维hashmap或数组或其他类型的直接访问数据结构,在该数据结构中存储特定类型的(布尔)或多少(int)卡。例如:

[ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]
=>
  | A  K  Q  J  10 9  8  7  6  5  4  3  2
--+--------------------------------------
C | 0  0  1  1  0  0  0  1  0  0  0  0  0
D | 0  1  0  0  0  1  0  0  0  0  0  0  0
H | 0  0  0  0  0  1  0  0  0  0  0  0  0
S | 0  0  0  0  1  0  0  0  0  0  0  0  0

这应该允许在该结构中进行非常快速和简单的搜索 - 通过循环,您可以快速识别出有多个9,并且俱乐部女王旁边有2张俱乐部卡。

是否为黑桃选择一个对象或一个数组并且哪些(套装或值)是第一维或第二维并不重要。对于值,您将需要使用数组来获取定义的顺序,即使映射(例如A-> 0,K-> 1,... 2-> 12)是非常规的。

答案 1 :(得分:2)

快速解决方案是先将手快速分类为套装/数字顺序,即:

[ '9H', '10S', '7D', '9D', 'KD', '7C', 'JC', 'QC' ]

然后在列表中进行单次传递,跟踪到目前为止发现的单一套装中最长的卡片序列,例如:

var lastCard
var currentSequence
var bestSequence

for card in cards:
  if suitOf(card) = suitOf(lastCard) and numberOf(card) = numberOf(lastCard) + 1:
    append to currentSequence
  else:
    if currentSequence better than bestSequence:
      bestSequence = currentSequence
    clear currentSequence

当您找到“最佳”序列时,可以轻松中止搜索。

答案 2 :(得分:2)

由于关于您正在搜索的内容存在很多未知数,因此可能只需对卡进行排序即可,但您可以考虑将卡排列在对象(哈希表)中以快速查找条件。

function value(s) {
    return s.substr(0, s.length - 1)
}

function suit(s) {
    return s.substr(-1)
}


function search(arr) {
    var suits = {
        S: {},
        C: {},
        D: {},
        H: {}
    }

    var count = {
        S: 0,
        C: 0,
        D: 0,
        H: 0
    }

    for (var i = 0; i < arr.length; i++) {
        var card = arr[i]
        var s = suit(card)
        var v = value(card)

        suits[s][v] = true
        count[s]++
    }

    // hunt in the structure here
}

这将允许您获取第三个皇后,例如:

var thirdQueens = ["S", "C", "D", "H"].map(function (s) {
    var hash = suits[s]

    if (hash.Q && count[s] - (hash.K ? 1 : 0) >= 3) {
        return "Q" + s
    }
}).filter(function identity(x) { return x })

答案 3 :(得分:1)

...以下是你的hashmap的构造方式......我猜其他任何东西都已在我面前解释过了。

var input = [ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]

var M = [ [], [], [], [] ]

var values = {
  2:  0,
  3:  1,
  4:  2,
  5:  3,
  6:  4,
  7:  5,
  8:  6,
  9:  7,
 10:  8,
  J:  9,
  Q: 10,
  K: 11,
  A: 12,
}

var suits = {
  C: 0,
  D: 1,
  H: 2,
  S: 3,
}

input.forEach(function(x) {
  M[suits[x.slice(-1)]][values[x.slice(0, -1)]] = 1
})

答案 4 :(得分:1)

要回答问题的“更重要”部分,您可以按优先顺序创建一系列规则,为每个规则创建一个函数,然后迭代它。这是一个非常简单的例子:

var hand = [ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ];

var rules = [
    function(hand) {
        if (hand.indexOf('9H') !== -1) {
            return {
                rule: "Has a 9H",
                cards: [ "9H" ]
            };
        }
    },

    function(hand) {

        if (hand.indexOf('7D') !== -1) {
            return {
                rule: "Has a 7D",
                cards: [ "7D" ]
            };
        }
    }
];

var match = false;

for (var i = 0, len = rules.length; i < len && !match; ++i) {
    match = rules[i](hand);
}

console.log(match);

编写完成后,您可以查看规则并检查逻辑的重复,并开始重写规则:

var rules = [
    matchCardFn("9H"),
    matchCardFn("7D")
];

function matchCardFn(matchCard) {
    return function(hand) {
        if (hand.indexOf(matchCard) !== -1) {
            return {
                rule: "Has a " + matchCard,
                cards: [ matchCard ]
            };
        }
    };
}