在文本正文中找到一个ASCII艺术图像,并具有一定的容错性

时间:2013-01-09 20:44:15

标签: java algorithm search ascii-art

是否有任何算法可以找到以下ASCII艺术图像?

     +
     +
    +++
  +++++++
  ++   ++
 ++  +  ++
 ++ +++ ++
 ++  +  ++
  ++   ++
  +++++++
    +++

在以下正文中?

complete_file_here

              + +    +              ++           +       +++    +     +
 +  ++     +   + ++++    + +       +         +          +  +   +++     +++ +
     +            + +   ++      ++  ++    + ++       +     +      +  +   +
+   ++      +  ++       +          + +       ++        ++  +           +
 ++++++ + +    +   ++  +  +   +   +  ++      +         +                     +
  + +   +      +               +      ++     +  ++            +   +    + +
+++   + ++   +  +            +  +++       + +       ++                     +
  +++++  +      +                            +  + +            +   +  +
 +   +   +              +    +      +            +  +   +      +    +     +
 ++    +              +     +       ++   +          +       +           ++

我必须以黄色突出显示与完整形状相对应的ASCII艺术图像。见附图:

Enter image description here

我必须搜索包含粗糙形状的文件,但不完全,可能会丢失一些+。应该手动设置形状中缺失+的容差。

现在,我有两个2D数组数据数组:[100] [100]和SlimeTorpedo数组:[13] [11]。

如@kjartan所说的如何进行检测的代码(3-4子弹):

     int match = 0;
     for (int i = 0; i < 100; i++) {
         for (int j = 0; j < 100; j++) {
             //Compare DataArr[i][j] with SlimeTorpedoArr[i][j]
             //Look for "checked" position in the picture ("+"), 
             //which corresponds to a checked position in the 
             //slime torpedo array.
             //match++;
        }
    }

如何解决这个问题的一般指导是什么?

3 个答案:

答案 0 :(得分:4)

假设您的第一个形状已知宽度和高度参数(以字符数表示)。让他们成为widthheight

  • 将输入编码为2D数组(或+符号)。所以你有了 int[][] inputBits = new int[height][width];你应该填充 它正确。 (这是你的任务,老兄。)
  • 然后在较大的形状上应用简单的搜索(假设它是 编码到另一个2D数组中)。将枢轴区域向右移动 每次一个(枢轴区域相当于第一个区域) 形状)并检查枢轴区域(2D阵列)是否具有其所有元素 等于第一个形状。那是一种蛮力算法=)

答案 1 :(得分:4)

尝试使用匹配分数进行暴力破解:

  • 在“泥鱼雷”周围定义一个“方形”;这是一个2D阵列,宽度和高度比你的鱼雷略宽一些。
  • 在该2D阵列中,根据需要将单元格标记为已选中或未选中,以创建所需的图像。
  • 现在遍历每个角色(让我们称之为“索引”位置)在整个图像中,并为每个角色比较它附近的位置与2D阵列中相应角色的位置。
  • 在图片中查找“已检查”(或未选中)位置,该位置对应于粘液鱼雷阵列中的已检查(或未检查)位置(例如,上方的字符X和当前索引位置的左侧)图片,匹配上面的状态X和粘液鱼雷阵列中心点的Y左侧。对于每个这样的“匹配”,将一个“点”添加到图片中的索引位置。

现在这就是诀窍:为了使这个更有效,只需检查粘液鱼雷中的一些位置 - 例如,每10个位置甚至更少。粗略地说,这应该将运行时间减少10倍。

这意味着您必须为整张图片中的每个字符检查(1/10) * the number of characters in the 2D array

现在跟踪最高得分位置。得分最高的位置应该是最佳匹配。

如果你愿意,你可以多次运行,具有不同程度的细节,例如第一次检查位置的1/20,然后是1/2,接下来,但这次只关注例如第一轮中最高的20(或50?100?)得分位置。

(或者,您可以对所有得分高于某个阈值S的位置进行更详细的扫描。)

希望你能告诉我们你的决定是什么,有趣的问题! :)

响应以下评论进行更新:

也许我的解释有点不清楚。简而言之,伪代码,你需要做这样的事情来找到每个单元格的分数:

foreach(DataArraRow dataRow in dataArray){
    foreach(IndexCell index in dataRow){        

        // initialy, no score for this cell in the data array:
        indexCell.score = 0;

        // Now iterate through all SlimeTorpedo cells, and compare the 
        // symbol in it to the corresponding symbol in te data array:
        foreach(SlimeArrayRow slimeRow in slimeTorpedoArray){
            foreach(SlimeTorpedoCell slimeCell in slimeRow){
                if(IsMatchingSymbol(slimeCell.xPosition, 
                                    slimeCell.yPosition, 
                                    slimeCell.symbol, 
                                    indexCell){
                    indexCell.score += 1;
                }else{
                    indexCell.score -= 1;
                }
            }              
        }

    }
}


Function IsMatchingSymbol(x, y, slimeSymbol, indexCell){
   // Find the cell in the data array corresponding to the 
   // "slimeCell" currently being checked:
   var cellToCheck = getCell(indexCell.xPosition + x, 
                             indexCell.yPosition + y);

   if(cellToCheck.symbol == slimeSymbol){
       return true;
   }else{
       return false;
   }

}

这显然有点混乱,我不确定所有的细节,但我希望它显示出应该有效的一般概念。当您完成迭代后,再次遍历所有单元格,并获取最高得分单元格(或沿途构建单独的高分列表 - 这可能会更快)。

您必须进行一些更改,例如将ForEach循环替换为常规For(int i=0; i < someArrayLength; i = i + levelOfDetail){ ... }或类似内容,其中levelOfDetail是一个整数,您可以使用它来调整细节(即要检查的SlimeTorpedoArray中有多少个单元格)。我相信你可以解决这个问题......;)

答案 2 :(得分:1)

对于那些感兴趣的人,我使用Java中的XOR映射解决了这个问题:

https://bitbucket.org/bluegod1/blifoscope-java/

它还考虑到可能存在误报或重复,它可以选择指定良好匹配的最小阈值,添加自定义数据图像文件等...