0

I have this 25x25 matrix called 'a' which contains 1s and 0s and I need to the total number of specific patterns in it.

    V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25
1   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
2   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
3   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
4   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
5   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
6   0  0  0  0  0  0  0  1  1   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0
7   0  0  0  0  0  0  1  1  1   1   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0
8   0  0  0  0  0  1  1  0  0   0   0   0   1   1   1   0   0   0   0   0   0   0   0   0   0
9   0  0  0  0  1  1  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0
10  0  0  0  0  1  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0
11  0  0  0  0  1  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0
12  0  0  0  0  1  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0
13  0  0  0  0  1  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0
14  0  0  0  0  1  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0
15  0  0  0  0  1  0  0  0  0   0   0   0   0   1   1   0   0   0   0   0   0   0   0   0   0
16  0  0  0  0  1  0  0  0  0   0   0   0   0   1   1   0   0   0   0   0   0   0   0   0   0
17  0  0  0  0  1  1  0  0  0   0   0   0   1   1   1   1   0   0   0   0   0   0   0   0   0
18  0  0  0  0  0  1  1  0  0   0   0   1   1   0   0   1   0   0   0   0   0   0   0   0   0
19  0  0  0  0  0  0  1  1  1   1   1   1   0   0   0   1   1   0   0   0   0   0   0   0   0
20  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
21  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
22  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
23  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
24  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
25  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

An example of a pattern I need to find is a left2tile pattern:

      [,1] [,2]
[1,]    1    0
[2,]    1    0

Or a right2tile pattern:

      [,1] [,2]
[1,]    0    1
[2,]    0    1

Anyone have any advice on how to solve this?

Niall
  • 5
  • 4
  • This might be related: https://stackoverflow.com/q/31330196/3358272 (translating its use of `data.frame` to your `matrix`). (Actually ... what you first showed here is a `data.frame`, not a `matrix` ... I think; the row names look frame-y and not matrix-y.) – r2evans Mar 04 '21 at 16:59

1 Answers1

0

Here's a brute-force method.

Assuming a matrix:

str(a)
#  int [1:25, 1:25] 0 0 0 0 0 0 0 0 0 0 ...
#  - attr(*, "dimnames")=List of 2
#   ..$ : chr [1:25] "1" "2" "3" "4" ...
#   ..$ : chr [1:25] "V1" "V2" "V3" "V4" ...

head(matches <- which(a == left2tile[1,1], arr.ind = TRUE))
#    row col
# 9    9   5
# 10  10   5
# 11  11   5
# 12  12   5
# 13  13   5
# 14  14   5

nrow(matches)
# [1] 55

This says that there are 55 matches for the top-left element of left2tile within a, which is just a start. The first one is as [9,5], second (column-wise) is [10,5], etc.

From here:

matches2 <- Map(function(i,j) a[i+0:1,j+0:1], matches[,1], matches[,2])
head(matches2, 3)
# $`9`
#    V5 V6
# 9   1  1
# 10  1  0
# $`10`
#    V5 V6
# 10  1  0
# 11  1  0
# $`11`
#    V5 V6
# 11  1  0
# 12  1  0

Here, we have the first three submatrices of the matches. We can then test for equality:

(matches3 <- sapply(matches2, function(z) all(z == left2tile)))
#     9    10    11    12    13    14    15    16    17     8     9    17    18     7     8    18    19     6     7    19 
# FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
#     6     7    19     6     7    19     6     7    19     6     7    18    19     7     8    17    18     8    15    16 
# FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
#    17     8     9    10    11    12    13    14    15    16    17    17    18    19    19 
# FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE 

Where a TRUE indicates that that element within matches does contain the submatrix match. We can use

matches[matches3,]
#    row col
# 10  10   5
# 11  11   5
# 12  12   5
# 13  13   5
# 14  14   5
# 15  15   5
# 8    8  15
# 9    9  15
# 10  10  15
# 11  11  15
# 12  12  15
# 13  13  15
# 14  14  15
# 15  15  15
# 17  17  16

to give us the top-left of each submatrix within a that matches left2tile.

I would expect (and it is true here) that all of matches2[matches3] are the same as your left2tile.

r2evans
  • 141,215
  • 6
  • 77
  • 149