द रे 2 डी क्लास, पायथन 2
अद्यतन: जोड़ा गया "9. संरेखण" समस्या।
मेरा दृष्टिकोण खोज और मिलान करने के लिए पायथन री मॉड्यूल का उपयोग करना है। Re2d वर्ग प्रसंस्करण के लिए पाठ तैयार करता है, पुनः फ़ंक्शंस निष्पादित करता है, और आउटपुट के परिणामों को प्रारूपित करता है।
ध्यान दें कि यह एक पूरी नई भाषा नहीं है - यह अतिरिक्त 2 डी मोड के लिए जोड़े गए झंडे के साथ 2 आयामों में अनुमानित मानक नियमित अभिव्यक्ति भाषा है।
कक्षा में निम्नलिखित उपयोग हैं:
re2dobject = Re2d(<horizontal pattern>, [<vertical pattern>], [<flags>])
दोनों पैटर्न मानक रैखिक पाठ आरई पैटर्न हैं। यदि एक ऊर्ध्वाधर पैटर्न की आपूर्ति नहीं की जाती है, तो वर्ग क्षैतिज रूप से मिलान के लिए क्षैतिज पैटर्न का भी उपयोग करेगा। झंडे कुछ 2D एक्सटेंशन के साथ मानक आरई झंडे हैं।
परिक्षण
1. Finding chessboards
Chessboard pattern at (2, 1, 4, 3)
print '\n1. Finding chessboards'
reob1 = Re2d('#(_#)+_?|_(#_)+#?')
found = reob1.search('~______~\n~##_#_#~\n~#_#_##~\n~##_#_#~\n~______~')
print 'Chessboard pattern at', found
assert not reob1.search('#_##\n_#_#\n__#_\n#_#_\n#_#_')
खोज विधि में एक शतरंजबोर्ड पैटर्न पाया गया और 4-टपल स्थिति देता है। टपल में x,y
मैच के पहले अक्षर की स्थिति होती है, और
width, height
क्षेत्र का मिलान होता है। केवल एक पैटर्न दिया जाता है, इसलिए इसे क्षैतिज और ऊर्ध्वाधर मिलान के लिए उपयोग किया जाएगा ।
2. Verifying chessboards
Is chess? True
print '\n2. Verifying chessboards'
reob2 = Re2d('^#(_#)*_?|_(#_)*#?$')
print 'Is chess?', reob2.match('_#_#_#_#\n#_#_#_#_\n_#_#_#_#')
assert not reob2.match('_#_#_#__\n__#_#_#_\n_#_#_#__')
बिसात को मैच विधि से सत्यापित किया गया था जो एक बूलियन देता है। ध्यान दें कि ^
और $
आरंभ और समाप्ति वर्णों का मिलान करने के लिए आवश्यक हैं पूरे
पाठ।
3. Rectangle of digits
Found: [(0, 1, 5, 3), (1, 1, 4, 3), (2, 1, 3, 3), (3, 1, 2, 3), (0, 2, 5, 2), (1, 2, 4, 2), (2, 2, 3, 2), (3, 2, 2, 2), (6, 3, 2, 2)]
Not found: None
print '\n3. Rectangle of digits'
reob3 = Re2d(r'\d\d+', flags=MULTIFIND)
print 'Found:', reob3.search('hbrewvgr\n18774gwe\n84502vgv\n19844f22\ncrfegc77')
print 'Not found:', reob3.search('uv88wn000\nvgr88vg0w\nv888wrvg7\nvvg88wv77')
अब हम MULTIFIND
2+ अंक ब्लॉक के लिए सभी संभावित मैचों को वापस करने के लिए ध्वज का उपयोग करते हैं । विधि 9 संभावित मैचों को ढूंढती है। ध्यान दें कि वे अतिव्यापी हो सकते हैं।
4. Word search (orthogonal only)
Words: [(0, 0, 4, 1), (0, 3, 4, 1), (3, 3, -4, -1), (3, 2, -4, -1), (3, 0, -4, -1)] [(0, 0, 1, 4), (3, 0, 1, 4), (3, 3, -1, -4), (0, 3, -1, -4)]
Words: ['SNUG', 'WOLF', 'FLOW', 'LORE', 'GUNS'] ['S\nT\nE\nW', 'G\nO\nL\nF', 'F\nL\nO\nG', 'W\nE\nT\nS']
No words: [] []
print '\n4. Word search (orthogonal only)'
words = 'GOLF|GUNS|WOLF|FLOW|LORE|WETS|STEW|FLOG|SNUG'
flags = HORFLIP | VERFLIP | MULTIFIND
reob4a, reob4b = Re2d(words, '.', flags), Re2d('.', words, flags)
matching = 'SNUG\nTEQO\nEROL\nWOLF'
nomatch = 'ABCD\nEFGH\nIJKL\nMNOP'
print 'Words:', reob4a.search(matching), reob4b.search(matching)
print 'Words:', reob4a.findall(matching), reob4b.findall(matching)
print 'No words:', reob4a.findall(nomatch), reob4b.findall(nomatch)
यह परीक्षण ऊर्ध्वाधर और क्षैतिज फ्लिपिंग के उपयोग को दर्शाता है। यह उन शब्दों को मिलाने की अनुमति देता है जो उलटे होते हैं। विकर्ण शब्द समर्थित नहीं हैं।
MULTIFIND
झंडा सभी 4 दिशाओं में एकाधिक अतिव्यापी मैचों अनुमति देता है। खोज विधि मिलान बॉक्स को खोजने के लिए खोज का उपयोग करती है फिर पाठ के मिलान ब्लॉकों को निकालती है। ध्यान दें कि खोज कैसे रिवर्स दिशा में मैचों के लिए नकारात्मक चौड़ाई और / या ऊंचाई का उपयोग करती है। ऊर्ध्वाधर दिशा में शब्दों में नई लाइन वर्ण हैं - यह 2 डी चरित्र ब्लॉक की अवधारणा के अनुरूप है।
7. Calvins portals
Portals found: [(3, 1, 5, 6)]
Portal not found None
print '\n7. Calvins portals'
reob7 = Re2d(r'X\.{2,22}X|.X{2,22}.', r'X\.{3,22}X|.X{3,22}.', MULTIFIND)
yes = '....X......\n.XXXXXX.XX.\n...X...X...\n.X.X...XXX.\n...X...X.X.\n.XXX...X.X.\nX..XXXXX.X.'
no = 'XX..XXXX\nXX..X..X\nXX..X..X\n..X.X..X\n.X..X.XX'
print 'Portals found:', reob7.search(yes)
print 'Portal not found', reob7.search(no)
इस खोज को प्रत्येक आयाम के लिए अलग-अलग पैटर्न की आवश्यकता थी क्योंकि न्यूनतम आकार प्रत्येक के लिए अलग है।
9. Alignment
Found: ['#.,##', '##'] ['#\n.\n,\n.\n#', '#\n,\n.\n#']
Found: [(3, 4, 5, 1), (6, 4, 2, 1)] [(7, 0, 1, 5), (3, 1, 1, 4)]
Not found: None None
print '\n9. Alignment'
reob9a = Re2d(r'#.*#', r'.', MULTIFIND)
reob9b = Re2d(r'.', r'#.*#', MULTIFIND)
matching = '.,.,.,.#.,\n,.,#,.,.,.\n.,.,.,.,.,\n,.,.,.,.,.\n.,.#.,##.,\n,.,.,.,.,.'
nomatch = '.,.#.,.,\n,.,.,.#.\n.,#,.,.,\n,.,.,.,#\n.#.,.,.,\n,.,.#.,.\n#,.,.,.,\n,.,.,#,.'
print 'Found:', reob9a.findall(matching), reob9b.findall(matching)
print 'Found:', reob9a.search(matching), reob9b.search(matching)
print 'Not found:', reob9a.search(nomatch), reob9b.search(nomatch)
2 खोजों के इस सेट में 2 ऊर्ध्वाधर और 2 क्षैतिज मैच मिलते हैं, लेकिन एम्बेडेड #.,#
स्ट्रिंग नहीं मिल सकती है ।
10. Collinear Points (orthogonal only)
Found: [(0, 1, 7, 1)] [(3, 1, 1, 4)]
Not found: None None
print '\n10. Collinear Points (orthogonal only)'
matching = '........\n#..#..#.\n...#....\n#.......\n...#....'
nomatch = '.#..#\n#..#.\n#....\n..#.#'
reob10h = Re2d(r'#.*#.*#', '.')
reob10v = Re2d('.', r'#.*#.*#')
flags = MULTIFIND
print 'Found:', reob10h.search(matching, flags), reob10v.search(matching, flags)
print 'Not found:', reob10h.search(nomatch, flags), reob10v.search(nomatch, flags)
यहां हम दोनों दिशाओं में मैच खोजने के लिए 2 खोजों का उपयोग करते हैं। यह कई ऑर्थोगोनल मैच खोजने में सक्षम है लेकिन यह दृष्टिकोण विकर्ण मैचों का समर्थन नहीं करता है।
12. Avoid qQ
Found: (2, 2, 4, 4)
Not found: None
print '\n12. Avoid qQ'
reob12 = Re2d('[^qQ]{4,4}')
print 'Found:', reob12.search('bhtklkwt\nqlwQklqw\nvtvlwktv\nkQtwkvkl\nvtwlkvQk\nvnvevwvx')
print 'Not found:', reob12.search('zxvcmn\nxcvncn\nmnQxcv\nxcvmnx\nazvmne')
यह खोज पहला मैच ढूंढती है।
13. Diamond Mining
.X.
X.X
.X.
.X.
X.X
.X.
..X..
./.\.
X...X
.\./.
\.X..
..X..
./.\.
X...X
.\./.
..X..
.XX.\
//.\.
X...X
.\./.
..X..
...X...
../.\..
./.X.\.
X.X.X.X
.\.X.//
..\./X.
.X.X..\
Diamonds: [(2, 2, 3, 3), (0, 6, 3, 3)] [(8, 0, 5, 5), (10, 2, 5, 5), (5, 3, 5, 5)] [(0, 0, 7, 7)]
Not found: None None None
print '\n13. Diamond Mining'
reob13a = Re2d(r'.X.|X.X', flags=MULTIFIND)
reob13b = Re2d(r'..X..|./.\\.|X...X|.\\./.', flags=MULTIFIND)
reob13c = Re2d(r'...X...|../.\\..|./...\\.|X.....X|.\\.../.|..\\./..', flags=MULTIFIND)
match = '''
...X......X....
../.\..../.\...
./.X.\..X...X..
X.X.X.XX.\./.\.
.\.X.//.\.X...X
..\./X...X.\./.
.X.X..\./...X..
X.X....X.......
.X.............
'''.strip().replace(' ', '')
nomatch = '''
.X......./....
.\....X.......
...X.\.\...X..
..X.\...\.X.\.
...X.X...X.\.X
../X\...\...X.
.X...\.\..X...
..\./.X....X..
...X..../.....
'''.strip().replace(' ', '')
for diamond in reob13a.findall(match)+reob13b.findall(match)+reob13c.findall(match):
print diamond+'\n'
print 'Diamonds:', reob13a.search(match), reob13b.search(match), reob13c.search(match)
print 'Not found:', reob13a.search(nomatch), reob13b.search(nomatch), reob13c.search(nomatch)
हीरे की समस्या अधिक कठिन है। तीन आकारों के लिए तीन खोज वस्तुओं की आवश्यकता होती है। यह परीक्षण सेट में छह हीरे पा सकता है, लेकिन यह चर आकार के हीरे के पैमाने पर नहीं है। यह हीरे की समस्या का केवल एक आंशिक समाधान है।
पायथन 2 कोड
import sys
import re
DEBUG = re.DEBUG
IGNORECASE = re.IGNORECASE
LOCALE = re.LOCALE
UNICODE = re.UNICODE
VERBOSE = re.VERBOSE
MULTIFIND = 1<<11
ROTATED = 1<<12 # not implemented
HORFLIP = 1<<13
VERFLIP = 1<<14
WRAPAROUND = 1<<15 # not implemented
class Re2d(object):
def __init__(self, horpattern, verpattern=None, flags=0):
self.horpattern = horpattern
self.verpattern = verpattern if verpattern != None else horpattern
self.flags = flags
def checkblock(self, block, flags):
'Return a position if block matches H and V patterns'
length = []
for y in range(len(block)):
match = re.match(self.horpattern, block[y], flags)
if match:
length.append(len(match.group(0)))
else:
break
if not length:
return None
width = min(length)
height = len(length)
length = []
for x in range(width):
column = ''.join(row[x] for row in block[:height])
match = re.match(self.verpattern, column, flags)
if match:
matchlen = len(match.group(0))
length.append(matchlen)
else:
break
if not length:
return None
height = min(length)
width = len(length)
# if smaller, verify with RECURSIVE checkblock call:
if height != len(block) or width != len(block[0]):
newblock = [row[:width] for row in block[:height]]
newsize = self.checkblock(newblock, flags)
return newsize
return width, height
def mkviews(self, text, flags):
'Return views of text block from flip/rotate flags, inc inverse f()'
# TODO add ROTATED to generate more views
width = len(text[0])
height = len(text)
views = [(text, lambda x,y,w,h: (x,y,w,h))]
if flags & HORFLIP and flags & VERFLIP:
flip2text = [row[::-1] for row in text[::-1]]
flip2func = lambda x,y,w,h: (width-1-x, height-1-y, -w, -h)
views.append( (flip2text, flip2func) )
elif flags & HORFLIP:
hortext = [row[::-1] for row in text]
horfunc = lambda x,y,w,h: (width-1-x, y, -w, h)
views.append( (hortext, horfunc) )
elif flags & VERFLIP:
vertext = text[::-1]
verfunc = lambda x,y,w,h: (x, height-1-y, w, -h)
views.append( (vertext, verfunc) )
return views
def searchview(self, textview, flags=0):
'Return matching textview positions or None'
result = []
for y in range(len(textview)):
testtext = textview[y:]
for x in range(len(testtext[0])):
size = self.checkblock([row[x:] for row in testtext], flags)
if size:
found = (x, y, size[0], size[1])
if flags & MULTIFIND:
result.append(found)
else:
return found
return result if result else None
def search(self, text, flags=0):
'Return matching text positions or None'
flags = self.flags | flags
text = text.split('\n') if type(text) == str else text
result = []
for textview, invview in self.mkviews(text, flags):
found = self.searchview(textview, flags)
if found:
if flags & MULTIFIND:
result.extend(invview(*f) for f in found)
else:
return invview(*found)
return result if result else None
def findall(self, text, flags=0):
'Return matching text blocks or None'
flags = self.flags | flags
strmode = (type(text) == str)
text = text.split('\n') if type(text) == str else text
result = []
positions = self.search(text, flags)
if not positions:
return [] if flags & MULTIFIND else None
if not flags & MULTIFIND:
positions = [positions]
for x0,y0,w,h in positions:
if y0+h >= 0:
lines = text[y0 : y0+h : cmp(h,0)]
else:
lines = text[y0 : : cmp(h,0)]
if x0+w >= 0:
block = [row[x0 : x0+w : cmp(w,0)] for row in lines]
else:
block = [row[x0 : : cmp(w,0)] for row in lines]
result.append(block)
if strmode:
result = ['\n'.join(rows) for rows in result]
if flags & MULTIFIND:
return result
else:
return result[0]
def match(self, text, flags=0):
'Return True if whole text matches the patterns'
flags = self.flags | flags
text = text.split('\n') if type(text) == str else text
for textview, invview in self.mkviews(text, flags):
size = self.checkblock(textview, flags)
if size:
return True
return False