Так что решение для этого заняло у меня некоторое время. Мне нужно было определить другую вспомогательную функцию и несколько других, чтобы заставить ее работать. Чтобы свести его к минимуму, есть функция slicer
: она берет полную сетку и два кортежа, затем извлекает подсеть со строками в диапазоне первого кортежа и столбцами второго кортежа. Его определение таково:
slicer :: [[a]] -> (Int, Int) -> (Int, Int) -> [[a]]
slicer [] _ _ = []
slicer a (x1,x2) (y1,y2) =form (head ( [[index a (i,j)|i<-[x1..x2-1],j<-[y1..y2-1]]])) (x2-x1,y2-y1)
Мне также нужна была функция для возврата значения по указанному индексу в сетке, index
:
index :: [[a]] -> (Int, Int) -> a
index (b:bb) (0,0) = head b
index (c:cc) (0,y) = index [(tail c)] (0,y-1)
index (d:dd) (x,y) = index dd (x-1,y)
Следующим шагом было определить эту helper
функцию. Это заняло большую часть работы функции. Это помогло «вложить» операцию по всей сетке. Вся его функция состоит в том, чтобы сдвинуть окно с фиксированным размером по всей сетке и найти совпадение. Как только он это делает, он дает самые верхние левые координаты этого соответствующего окна. Его определение таково:
helper :: Eq a => [[a]] -> [[a]] -> (Int, Int, Int) -> [(Int, Int)]
helper x _ (l, m, n) | (l > length x) = []
helper x y (l, m, n) | (n > length (concat (take 1 x))) = helper x y (l+1, 0, (length (concat (take 1 y))))
helper x y (l, m, n) | (slicer x (l, (length y) + l) (m, n) == y) = [(l, m)] ++ helper x y (l, (m+1), (n+1))
helper x y (l, m, n) | (slicer x (l, (length y) + l) (m, n) /= y) = [] ++ helper x y (l, (m+1), (n+1))
Наконец, после того, как пришли все эти подфункции, пришло время создать функцию, которую я пытался создать с самого начала. По иронии судьбы, это был самый простой из них, поскольку он просто принимает данный шаблон по всей длине сетки.
matcher :: Eq a => [[a]] -> [[a]] -> [(Int, Int)]
matcher x y = helper x y (0, 0, (length (concat (take 1 y))))