简体   繁体   中英

Javascript Pattern Matching a Matrix

In javascript, I have an array of matrices, each of which are 5x5. Eg:

25, 32, 26, 27, 29
01, 22, 15, 17, 99
12, 14, 17, 19, 88
16, 14, 12, 17, 19
02, 08, 09, 18, 19

I have a method findMatches (a, b, c, d, e) that takes five number values. The goal is to return a new array of matrices which match any of the following conditions:

At least 4 numbers from the findMatches (a, b, c, d, e) method match at least 4 consecutive numbers in any matrix row. Eg. If a matrix row has 22, 23, **29**, 24, 25 it would not match because no set of four numbers from the method are next to each-other (it doesn't matter, however, if the order matches that of the order of the ints provides to the method. It can be a, c, d, e and that's fine.). However, if it were 22, 26, 23, 24 it would match because there are at least four consecutive numbers are from the method. Eg:

**22**, 32, 26, 27, 29
**26**, 22, 15, 17, 99
**23**, 14, 17, 19, 88
**24**, 14, 12, 17, 19
  02,   08, 09, 18, 19

The same as above but in any matrix column instead of row

20, 01, 02,  03,  08
01,*22,*23*,*25*,*24*
12, 14, 17, 19, 88
16, 14, 12, 17, 19
02, 08, 09, 18, 19

The same as the last two but diagonally, instead of in a row or column

**22**, 32, 26, 27, 29            01, 02, 03,   04,   05
01, **23**, 15, 17, 99            06, 07, 08, **24**, 10
12, 14, **26**, 19, 88            11, 12, **23**, 14, 15
16, 14, 12, **25**, 19            16, **25**, 18, 19, 20
02, 08, 09,   18,   19          **22**, 22,   23, 24, 25

No two numbers in any matrix are the same. Eg, there will not be the number 1 more than once in the entire matrix.

I'm not quite sure how to approach this. My first instinct is to sit there and generate all possible matrices to check for matches, but this obviously isn't feasible considering that there are well over a million possible combinations.

So here's a solution using regex:

First, I'm assuming each matrix is stored in a textual format exactly as you stated (that's important, as the regex may need tweaking otherwise).

We'll use this pattern, (you'll need to substitute in variables for the 01, 02, 03, 20). I'll explain it a bit

(01|02|03|20), (?!\1)(01|02|03|20), (?!\1)(?!\2)(01|02|03|20), (?!\1)(?!\2)(?!\3)(01|02|03|20)

First we match any of the numbers. Then a comma, and then any number that wasn't the first number.

That (?!\\1) is doing a couple things. First it does a "negative lookahead assertion" which looks forward without consuming the characters, and it makes sure they do not contain \\1 which is a back reference to our first captured number.

Using this for vertical and diagonal lists is a simple matter, just grab the appropriate row and convert it to a horizontal format, then run the regex on it.

Hope this helps you get started. Feel free to post back with your attempts if you run into a wall.

Non-regex approach.

var matrix;

function findMatches(a, b, c, d, e) {
    // Rows
    for (var i = 0; i < matrix.length; i++) {
        if (checkMatch(matrix[i], [a, b, c, d, e]))
            return true;
    }

    // Columns
    for (var i = 0; i < matrix[0].length; i++) {
        if (checkMatch(getColumn(matrix, i), [a, b, c, d, e]))
            return true;
    }

    // Diagonals
    var diagonalArray = [];
    for (var i = 0; i < matrix.length; i++) {
        for (var x = 0; x < matrix[i].length; x++) {
            if (i === x) {
                diagonalArray.push(matrix[i][x]);
                continue;
            }
        }
    }
    if (checkMatch(diagonalArray, [a, b, c, d, e]));
        return true;

    var revDiagonalArray = [];
    for (var i = 0; i < matrix.length; i++) {
        for (var x = 0; x < matrix[i].length; x++) {
            if (i === 4 - x) {
                revDiagonalArray.push(matrix[i][x]);
                continue;
            }
        }
    }
    if (checkMatch(revDiagonalArray, [a, b, c, d, e]));
        return true;

    return false;
}

function getColumn(matrix, columnIndex) {
    var array = [];
    for (var i = 0; i < matrx.length; i++)
        array.push(matrix[i][columnIndex]);
    return array;
}

function checkMatch(array, toMatch) {
    var matchCount = 0;
    for (var i = 0; i < array.length; i++) {
        if (toMatch.indexOf(array[i]) > -1) {
            matchCount++;
            if (matchCount === 4)
                return true;
        }
        else if (i > 0)
            break;
    }
    return false;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM