【问题标题】:Searching for a word in a grid在网格中搜索单词
【发布时间】:2013-12-30 02:57:12
【问题描述】:

我正在尝试编写一个函数,该函数接受一个方形的字母网格,并给出一个从单词列表中查找的单词,它水平、垂直或对角搜索它(在每种情况下也向后看)。我试过以各种方式编写这个函数,但没有成功,所以想知道我的通用算法是否听起来不错并且可以实现。

  • 返回单词第一个字母出现的所有位置的坐标,例如 [row,col] = find(grid==words(2)) 单词是单词列表,网格是方阵。所以这将在grid 中搜索words 中的第二个单词。

  • 对于这个字母的每次出现,在单词长度的所有方向上垂直、水平和对角移动,如果最后一个字母是我们要查找的单词的最后一个字母,则存储每个字符从第一个到最后一个作为数组中的单词。

  • 将每个单词与我们要查找的单词进行比较,如果匹配,则画一条线。

想法?

【问题讨论】:

  • words(2) 错字?什么是words(1)?这是另一个处理类似问题的问题,但目前只解决行和第一对角线:stackoverflow.com/questions/20502065/matlab-loop-not-working
  • @user3058703 感谢您对此有所了解。我拼凑了一些解决任务的代码,但与您描述的算法不完全一样。

标签: matlab pattern-matching octave text-processing


【解决方案1】:

考虑沿水平、垂直和两个对角线方向查找的字符数组和子字符串:

A = char(randi(16,7,10)+'a'-1)
A =
  ilhpcdchkl
  ooaecloocd
  kogajcdkpg
  imlnnbiihf
  bigoahciin
  afjfjdhgmp
  pejcdfnmke
% horizontal string in row 4, starting at col 5
cH = [4 5]; l = 4; % strings of length 4
sh = A(cH(1),cH(2)+(0:l-1))
sh =
  nbii

% vertical string in col 6, starting at row 3
cV = [2 6];
sv = A(cV(1)+(0:l-1),cV(2)).' %'
sv =
  lcbh

% diagonal (downward) string starting at row 3, col 7
cD = [3 7];
sd = A((cD(1)+(0:l-1))+size(A,1)*((cD(2)+(0:l-1))-1))
sd =
  diip

% diagonal (upward) string starting at row 5, col 2
cU = [5 2]
su = A((cU(1)-(0:l-1))+size(A,1)*((cU(2)+(0:l-1))-1))
su =
  ilac

从一个可以在矩阵的行中搜索字符串的函数开始:

function ij = strsearch(A,s)

C = mat2cell(A,ones(size(A,1),1),size(A,2));
matches = strfind(C,s);
rows = find(~cellfun(@isempty,matches));
if ~isempty(rows),
    cols = vertcat(matches{rows});
else
    cols = [];
end
ij = [rows cols];

例如,这给出了矩阵A中水平字符串sh的(行,列)位置:

>> ij = strsearch(A,sh)
ij =
     4     5

这对于水平字符串来说非常棒,但我们想要的是能够在所有方向和方向上进行搜索。我们创建了一个新函数,称为wordsearch,它将输出以下内容:

>> matches = wordsearch(A,sh)
matches = 
          start: [4 5]
    orientation: 'horizontal'
      direction: 0  % forward
>> matches = wordsearch(A,sv)
matches = 
          start: [2 6]
    orientation: 'vertical'
      direction: 0
>> matches = wordsearch(A,sd)
matches = 
          start: [3 7]
    orientation: 'downward diagonal'
      direction: 0
>> matches = wordsearch(A,su)
matches = 
          start: [5 2]
    orientation: 'upward diagonal'
      direction: 0
>> matches = wordsearch(A,fliplr(sh))
matches = 
          start: [4 8] % sh goes from column 5 to 8, in row 4
    orientation: 'h'
      direction: 1  % backward

要做到这一点,我们可以在strsearch 的基础上通过转置矩阵来搜索水平和垂直事件。通过翻转输入字符串可以找到向后出现的事件。要搜索对角线,我们可以使用arrayfundiag提取对角线并以类似的方式搜索。

通用搜索功能:

function ij = wordsearcher(A,s,orientation,order)
s = s(:).'; %' ensure row vector
if order, s = fliplr(s); end
switch lower(orientation(1))
    case 'h'
        ij = strsearch(A,s);
        if order && ~isempty(ij), ij(:,2) = ij(:,2) + numel(s) - 1; end
    case 'v'
        ij = fliplr(strsearch(A.',s)); %'
        if order && ~isempty(ij), ij(:,1) = ij(:,1) + numel(s) - 1; end
    case 'd' % down-right diagonals
        Cdiags = arrayfun(@(k)diag(A,k).',-size(A,1)+1:size(A,2)-1,'uni',0); %'
        matches = strfind(Cdiags,s);
        k = find(~cellfun(@isempty,matches));
        if isempty(k), ij=[]; return; end
        row =  (k<=size(A,1)) .* (size(A,1) - k) + [matches{k}];
        col = ~(k<=size(A,1)) .* (k - size(A,1)) + [matches{k}];
        ij = [row; col].'; %'
        if order, ij = ij+numel(s)-1; end
    case 'u' % up-right diagonals
        Cdiags = arrayfun(@(k)diag(flipud(A),k).', ... %' flip A up-down
                                          -size(A,1)+1:size(A,2)-1,'uni',0);
        matches = strfind(Cdiags,s);
        k = find(~cellfun(@isempty,matches));
        if isempty(k), ij=[]; return; end
        row = ~(k<=size(A,1)) .* (size(A,1) - k) + k - [matches{k}] + 1;
        col = ~(k<=size(A,1)) .* (k - size(A,1)) + [matches{k}];
        ij = [row; col].'; %'
        if order, ij=bsxfun(@plus,ij,numel(s)*[-1 1]); end
    otherwise
        error('bad orientation')
end

用循环包装它以在所有方向/方向上搜索以获得wordsearch 函数:

function matches = wordsearch(A,s)
matches = struct('start',[],'orientation',[],'direction',[]);
n=1; o='hvdu';
ostr = {'horizontal','vertical','downward diagonal','upward diagonal'};
for id=0:1,
    for io=1:numel(o),
        ij = wordsearcher(A,s,o(io),id);
        if ~isempty(ij),
            matches(n).start = ij;
            matches(n).orientation = ostr{io};
            matches(n).direction = id;
            n = n+1;
        end
    end
end

我希望这行得通。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多