Kenali nomor seni ASCII

15

Tantangan

Kenali nomor seni ASCII. Untuk membuat hal-hal menarik, tiga titik acak dalam gambar mungkin terbalik. Sebagai contoh:

 ***** 
 *  ** 
    ** 

   **  
  **   
 **    

Memasukkan

Nomor seni ASCII 7x7 dihasilkan oleh skrip Python di bawah ini.

Keluaran

Digit.

Skrip pengujian

Berikut skrip Python (2.6+) untuk menghasilkan kasus uji:

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))
Blender
sumber
Apakah Anda yakin jarak Hamming antara masing-masing dua digit lebih dari 6?
John Dvorak
@ JanDvorak: Saya mengutak-atik font sehingga ini tidak akan menjadi masalah. Apakah kamu melihat satu?
Blender

Jawaban:

9

APL ( 87 85)

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

Penjelasan:

Setiap nomor ASCII yang mungkin dikodekan dalam 48 bit. (Bit 49 selalu nol). String 嵝䍝뫂傁ဣ␋䠁䊫낫䢝䊅넂垵僡ᑨ嘙쐅嘹䜝䪀슪퀪岹亝尵䌧뮢memiliki tiga karakter per nomor ASCII, yang masing-masing mengkodekan 16 bit.

  • ↓10 3⍴: pisahkan string data menjadi 10 grup 3-char, yang masing-masing mengkodekan angka.
  • {... : untuk masing-masing grup:
    • (16/2)⊤⎕UCS⍵: dapatkan 16 bit pertama dari masing-masing tiga karakter
    • ,: menyatukan bit array menjadi satu array
    • 49↑: ambil 49 elemen pertama. Hanya ada 48, jadi ini setara dengan menambahkan 0di akhir.
  • ,↑{7↑'*'=⍞}¨⍳7: baca 7 baris 7 karakter dari keyboard, buatlah bit array untuk setiap baris yang 1berarti karakter itu a *, dan gabungkan bersama.
  • (+.=)¨: untuk setiap digit yang mungkin, hitung berapa banyak bit input yang memiliki kesamaan dengan digit tersebut.
  • : dapatkan indeks untuk daftar urutan ke bawah, sehingga item pertama dalam hasilnya adalah indeks jumlah terbesar di daftar sebelumnya.
  • : ambil item pertama, yang merupakan indeks digit
  • 1-⍨: kurangi satu, karena indeks APL berbasis 1.
marinus
sumber
3
wow 87? harus menjadi program APL terlama yang pernah ada.
izabera
4
Saya selalu berpikir APL selalu terlihat seperti bahasa Yunani. Sekarang orang Cina juga?!?
Digital Trauma
5

Python

Saya yakin akan ada solusi OCR, tetapi probabilitas saya akurat jauh lebih tinggi.

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))

Masukkan satu baris teks pada satu waktu.

Tidak yakin cara yang lebih baik untuk berurusan dengan tanda bintang tanpa menambah jumlah karakter.

grovesNL
sumber
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))

Pemakaian:

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

Versi tidak golf:

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)
)
Florent
sumber
3
Apakah ini berfungsi jika input tidak persis sama dengan salah satu digit? Menurut pertanyaan, tiga piksel mungkin dibalik dan masih harus bekerja.
marinus
3

Bash + ImageMagick + tesseract, 316 karakter

Berikut adalah bacokan pada solusi OCR. Ini tidak terlalu akurat, bahkan ketika mengatakan pada tesseract bahwa kita hanya punya satu char dan itu digit. Golf sedang, tapi masih bisa dibaca:

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

Script mengambil input dari stdin, jadi kita bisa mem-pipe dari script tes.

Catatan Saya telah memasukkan tee >( cat 1>&2 )pipeline supaya kita bisa melihat apa script tes yang sebenarnya dihasilkan.

Contoh output (Ini adalah proses yang cukup bagus dengan hanya 1 karakter yang salah dari 6):

$ python ./asciitest.py | tee> (cat 1> & 2) | ./scanascii.sh
  ***  
 ** ** 
* **
 ** * 
  **** 
    ***
 ****  
Tesseract Open Source OCR Engine v3.02 dengan Leptonica
9

$ python ./asciitest.py | tee> (cat 1> & 2) | ./scanascii.sh
   *   
 *** *
   *   
   *   
   *   
   *   
 ***** 
Tesseract Open Source OCR Engine v3.02 dengan Leptonica
1

$ python ./asciitest.py | tee> (cat 1> & 2) | ./scanascii.sh
  ***  
 ** ** 
** **
** **
** **
  * ** 
  ***  
Tesseract Open Source OCR Engine v3.02 dengan Leptonica
0

$ python ./asciitest.py | tee> (cat 1> & 2) | ./scanascii.sh
 ***** 
 **    
 ****  
     * 
     * 
 ** * 
  ***  
Tesseract Open Source OCR Engine v3.02 dengan Leptonica
5

$ python ./asciitest.py | tee> (cat 1> & 2) | ./scanascii.sh
  **** 
 **    
 ***** 
 * * 
*** ***
 ** **
  **** 
Tesseract Open Source OCR Engine v3.02 dengan Leptonica
5

$ python ./asciitest.py | tee> (cat 1> & 2) | ./scanascii.sh
  ***  
 * ** 
     * 
    ** 
   *** 
  **   
 ******
Tesseract Open Source OCR Engine v3.02 dengan Leptonica
2

$ 
Trauma Digital
sumber
1

LÖVE2D, 560 Bytes

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)

Pertama, gambarkan representasi gumpal dari teks input, lalu, untuk setiap angka 0 - 9, tumpang tindih satu angka, periksa berapa banyak piksel serupa yang ada, dan cetak angka yang paling dekat. OCR yang sangat mendasar. Ini cocok dengan semua Uji Kasus, dan berkinerja cukup baik dengan mutasi.

Telepon dengan:

love.exe "" "INPUT"
ATaco
sumber