识别ASCII艺术编号


15

挑战

识别ASCII艺术编号。为了使事情变得有趣,可能会翻转图像中的三个随机点。例如:

 ***** 
 *  ** 
    ** 

   **  
  **   
 **    

输入值

以下Python脚本生成的7x7 ASCII艺术编号。

输出量

一个数字。

测试脚本

这是生成测试用例的Python脚本(2.6+):

import random

digits = '''\
  ***  
 ** ** 
**   **
**   **
**   **
 ** ** 
  ***  

   *   
 ***   
   *   
   *   
   *   
   *   
 ***** 

  ***  
 *  ** 
     * 
    ** 
   **  
  **   
 ******

  ***  
 *  ** 
     * 
  ***  
     * 
 *  ** 
  ***  

   **  
  ***  
 * **  
*  **  
****** 
   **  
   **  

 ***** 
 **    
 ****  
     * 
     * 
 *   * 
  ***  

  **** 
 **    
 ***** 
 *   * 
 **  **
 **  * 
  **** 

 ***** 
    ** 
    ** 
   **  
   **  
  **   
 **    

  **** 
 **  **
 **  **
  **** 
 **  **
 **  **
  **** 

  ***  
 ** ** 
**   **
 **  * 
  **** 
    ** 
 ****  '''.split('\n\n')

def speckle(image, num_speckles):
    grid = [list(row) for row in image.split('\n')]

    for i in range(num_speckles):
        row = random.choice(grid)
        row[random.randint(0, 6)] = random.choice([' ', '*'])

    return '\n'.join([''.join(row) for row in grid])

digit = random.choice(digits)

print(speckle(digit, 3))

您确定每两位数字之间的汉明距离是否大于6?
约翰·德沃夏克

@JanDvorak:我调整了字体,这样就不会有问题了。你看到一个吗?
Blender 2014年

Answers:


9

杀伤人员地雷(87 85)

1-⍨⊃⍒(,↑{7↑'*'=⍞}¨⍳7)∘(+.=)¨{49↑,(16/2)⊤⎕UCS⍵}¨↓10 3⍴'嵝䍝뫂傁ဣ␋䠁䊫낫䢝䊅넂垵僡ᑨ嘙쐅嘹䜝䪀슪퀪岹亝尵䌧뮢'

说明:

每个可能的ASCII码都以48位编码。(无论如何,第49位始终为零)。该字符串嵝䍝뫂傁ဣ␋䠁䊫낫䢝䊅넂垵僡ᑨ嘙쐅嘹䜝䪀슪퀪岹亝尵䌧뮢每个ASCII码包含三个字符,每个字符编码16位。

  • ↓10 3⍴:将数据字符串分成10个3字符组,每个组编码一个数字。
  • {... :对于每个组:
    • (16/2)⊤⎕UCS⍵:获取三个字符中每个字符的前16位
    • ,:将位数组连接为一个数组
    • 49↑:采用前49个元素。只有48个,所以这等效0于在末尾添加a 。
  • ,↑{7↑'*'=⍞}¨⍳7:从键盘读取7行,每行7个字符,对每行做一个位数组,1表示该字符是a *,然后将它们连接在一起。
  • (+.=)¨:对于每个可能的数字,计算输入与该数字共有多少位。
  • :获取该列表的向下排序的索引,以便结果中的第一项是上一个列表中编号最大的索引。
  • :取第一项,即数字的索引
  • 1-⍨:减去1,因为APL索引基于1。

3
哇87?必须是有史以来最长的APL程序。
izabera 2014年

4
我一直认为APL总是看起来像希腊文。现在也是中文?!?
Digital Trauma 2014年


5

蟒蛇

我敢肯定会有OCR解决方案,但是我的准确率要高得多。

import difflib as x;r=range;s='2***3**1**1**3****3****3**1**1**3***23*4***6*6*6*6*4*****12***3*2**6*5**4**4**4******2***3*2**6*3***7*2*2**3***23**4***3*1**2*2**2******4**5**21*****2**5****7*6*2*3*3***22****2**5*****2*3*2**2**1**2*3****11*****5**5**4**5**4**4**42****2**2**1**2**2****2**2**1**2**2****12***3**1**1**3**1**2*3****5**2****2'
for c in r(8):s=s.replace(str(c),' '*c)
s=map(''.join,zip(*[iter(s)]*7));a=[raw_input("") for i in r(7)];l=[[x.SequenceMatcher('','|'.join(a),'|'.join(s[i*7:(i+1)*7])).ratio()] for i in r(10)];print l.index(max(l))

一次输入一行文字。

不确定在不增加字符数的情况下处理星号的更好方法。


4

JavaScript(ES6),89

f=n=>(a=1,[a=(a+a^c.charCodeAt())%35 for(c of n)],[4,25,5,16,0,11,32,13,10,1].indexOf(a))

用法:

> f("  ***  \n *  ** \n     * \n    ** \n   **  \n  **   \n ******")
2

非高尔夫版本:

f = (n) => (
  // Initialize the digit's hash.
  a=1,
  // Hash the digit.
  // 35 is used because the resulting hash is unique for the first ten digits.
  // Moreover, it generates 4 1-digit hashes.
  [a = (a + a ^ c.charCodeAt()) % 35 for(c of n)],
  // Compare the hash to pre-computed digit hash.
  // The matching hash index is the digit.
  [4,25,5,16,0,11,32,13,10,1].indexOf(a)
)

3
如果输入不完全等于一位数字,这是否有效?根据问题,三个像素可能会翻转,并且仍然可以正常工作。
marinus 2014年

3

Bash + ImageMagick + tesseract,316个字符

这是OCR解决方案的一个突破口。即使它告诉tesseract我们只有一个字符,而且它是一个数字,它也不是很准确。中等程度的打高尔夫球,但仍然有些可读性:

w=0
c()((w=${#2}>w?${#2}:w))
mapfile -c1 -Cc -t l
h=${#l[@]}
{
echo "# ImageMagick pixel enumeration: $w,$h,1,gray"
for y in ${!l[@]};{
for((x=0;x<w;x++));{
[ "${l[$y]:$x:1}" != " " ]
echo "$x,$y: ($?,$?,$?)"
}
}
}|convert txt:- i.png
tesseract i.png o -psm 10 <(echo "tessedit_char_whitelist 0123456789")
cat o.txt

该脚本从stdin接收输入,因此我们可以从测试脚本中进行管道传输。

注意,我已经放入tee >( cat 1>&2 )管道中,以便我们可以看到测试脚本实际生成了什么。

输出示例(这是一个很好的运行,其中只有6个错误的char中有1个不正确)。

$ python ./asciitest.py | 三通>(cat 1>&2)| ./scanascii.sh
  ***  
 ** ** 
* **
 ** * 
  **** 
    ***
 ****  
带Leptonica的Tesseract开源OCR引擎v3.02
9

$ python ./asciitest.py | 三通>(cat 1>&2)| ./scanascii.sh
   *   
 *** *
   *   
   *   
   *   
   *   
 ***** 
带Leptonica的Tesseract开源OCR引擎v3.02
1个

$ python ./asciitest.py | 三通>(cat 1>&2)| ./scanascii.sh
  ***  
 ** ** 
** **
** **
** **
  * ** 
  ***  
带Leptonica的Tesseract开源OCR引擎v3.02
0

$ python ./asciitest.py | 三通>(cat 1>&2)| ./scanascii.sh
 ***** 
 **    
 ****  
     * 
     * 
 ** * 
  ***  
带Leptonica的Tesseract开源OCR引擎v3.02
5

$ python ./asciitest.py | 三通>(cat 1>&2)| ./scanascii.sh
  **** 
 **    
 ***** 
 * * 
*** ***
 ** **
  **** 
带Leptonica的Tesseract开源OCR引擎v3.02
5

$ python ./asciitest.py | 三通>(cat 1>&2)| ./scanascii.sh
  ***  
 * ** 
     * 
    ** 
   *** 
  **   
 ******
带Leptonica的Tesseract开源OCR引擎v3.02
2

$ 

1

LÖVE2D,560字节

t=...;g=love.graphics g.setNewFont(124)g.setBackgroundColor(255,255,255)A=g.newCanvas()B=g.newCanvas()x=1 y=1 g.setColor(255,255,255)g.setCanvas(B)g.clear(0,0,0)for i=1,#t do x=x+1 if t:sub(i,i)=="\n"then x=1 y=y+1 end if t:sub(i,i)=="*"then g.rectangle("fill",x*16,y*16,16,16)end end u=B:newImageData()g.setCanvas(A)S={}for i=0,9 do g.clear(0,0,0,0)g.print(i,48,0)r=A:newImageData()s={i=i,s=0}for x=0,16*8 do for y=0,16*8 do a=u:getPixel(x,y)b=r:getPixel(x,y)s.s=s.s+math.abs(a-b)end end S[i+1]=s end table.sort(S,function(a,b)return a.s<b.s end)print(S[1].i)

首先,绘制输入文本的块状表示,然后对于每个数字0-9,覆盖一个数字,检查其中有多少个相似像素,并打印出最接近的数字。非常基本的OCR。它与所有测试用例匹配,并且在突变情况下表现良好。

致电:

love.exe "" "INPUT"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.