Skip to content
This repository
tree: 3b09560f9d
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 156 lines (142 sloc) 4.848 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
'''AutoMineDict
Copyright(C) 2012 idobatter, All Rights Reserved.
pattern (same as maptbl code)
f: not opened
o: opened any number or wall
n(1-8): opened and number
9: flagged

m = mirror mode (0: なし, 1: 線非対称(縦線|), 2: 線非対称(斜線\))
-> 1 or 2 どちらの線非対称でも 4 種 rotate 全て持てば 1 or 2 の区別は無くなる
r = rotate angle (0: 0, 1: 90, 2: 180, 3: 270)
lop = delta points list to be opened
lmk = delta points list to be marked
※pattern (と mirror / rotate 処理) は今のところ 3 x 3 専用だが
delta points の範囲は 3 x 3 以上に離れた場所 (1-3-1) のときなどにも使える
ただし枠外に出るケースに注意
※現状は検索を高速化するため mirror した pattern も持っているが
pattern のサイズが大きくなると組み合わせが増えるので注意
-> amd.add() で mirror ありのときは amd.add() 内で自動生成
'''

DATAFILE = u'AutoMineDict.txt'

class AutoMineDict(object):
  def __init__(self):
    self.flush()

  def flush(self):
    self.d = [None, {}, {}, {}, {}, {}, {}, {}, {}]

  def reload(self, fn=DATAFILE):
    self.flush()
    f = open(fn, 'rb')
    c, sw, sh, m, dw, dh, p, q = 0, 0, 0, 0, 0, 0, [], []
    for l in f.readlines():
      if l[0] == '#' or len(l.rstrip()) == 0: continue
      if l[0] == 'p':
        d, sw, sh, m, dw, dh, e = map(
          lambda x: int(x) if x.isdigit() else x, l.split(',', 6))
        c, o, p, q = 0, (dw - 1) / 2, [], []
        continue
      p.append(l[1:1 + dw])
      q.append(l[7:7 + dw])
      c += 1
      if c < dh: continue
      ptn = ''.join(p[1 + n][1:1 + sw] for n in xrange(sh))
      lop, lmk = [], []
      for y in xrange(dh):
        for x in xrange(dw):
          r = q[y][x]
          if r == 'o': lop.append((x - o, y - o))
          elif r == 'm': lmk.append((x - o, y - o))
      self.add(ptn, m, lop, lmk)
    f.close()

  def add(self, ptn, m, lop, lmk):
    '''mirror ありのときは自動生成'''
    n = int(ptn[4])
    for i in xrange(2 if m else 1):
      if i:
        ptn = self.ptnmirror(ptn, m)
        lop = [self.pmirror(p, m) for p in lop]
        lmk = [self.pmirror(p, m) for p in lmk]
      for r in xrange(4):
        k = self.ptnrrotate(ptn, r)
        if self.d[n].has_key(k): print 'key conflicts: [%s]\a' % k # with beep
        self.d[n][k] = [ptn, m, r,
          [self.prrotate(p, r) for p in lop],
          [self.prrotate(p, r) for p in lmk]]

  def match(self, ptn):
    '''ptn must be a string length 9'''
    n = int(ptn[4]) # center is always a number 1-8, bat arounds may be 'f09?'
    for k in self.d[n].keys():
      for i, c in enumerate(k):
        if c == '-': continue
        elif c == 'o':
          if not ptn[i].isdigit() or int(ptn[i]) == 9: break
        elif c == 'f':
          if ptn[i] != '9' and ptn[i] != 'f': break
        else:
          if c != ptn[i]: break
      else: return k, self.d[n][k]
    else: return None, None

  @classmethod
  def ptnmirror(cls, ptn, m=0):
    '''mirror'''
    l = list(ptn)
    if m == 1: l = [l[n] for n in (2, 1, 0, 5, 4, 3, 8, 7, 6)]
    if m == 2: l = [l[n] for n in (0, 3, 6, 1, 4, 7, 2, 5, 8)]
    return ''.join(l)

  @classmethod
  def pmirror(cls, p, m=0):
    '''reverse mirror'''
    x, y = p[0], p[1]
    if m == 1: return (-x, y)
    if m == 2: return (y, x)
    return (x, y)

  @classmethod
  def ptnrrotate(cls, ptn, r=1):
    '''rotate right'''
    l = list(ptn)
    for i in xrange(r): l = [l[n] for n in (6, 3, 0, 7, 4, 1, 8, 5, 2)]
    return ''.join(l)

  @classmethod
  def prrotate(cls, p, r=1):
    '''rotate right'''
    x, y = p[0], p[1]
    for i in xrange(r): x, y = -y, x
    return (x, y)

  @classmethod
  def plrotate(cls, p, r=1):
    '''rotate left'''
    x, y = p[0], p[1]
    for i in xrange(r): x, y = y, -x
    return (x, y)

if __name__ == '__main__':
  amd = AutoMineDict()
  amd.reload()
  ptn = '123456789'
  print 'mirror'
  print amd.ptnmirror(ptn, m=1),
  print amd.ptnmirror(amd.ptnmirror(ptn, m=1), m=1),
  print amd.ptnmirror(ptn, m=2),
  print amd.ptnmirror(amd.ptnmirror(ptn, m=2), m=2)
  print 'rrotate'
  print amd.ptnrrotate(ptn),
  print amd.ptnrrotate(ptn, r=2),
  print amd.ptnrrotate(ptn, r=3),
  print amd.ptnrrotate(ptn, r=4),
  print amd.ptnrrotate(ptn, r=5)
  print '----'
  for n, d in enumerate(amd.d):
    if not n: continue
    for ptn in d.keys():
      print n, ptn, d[ptn]
      m = d[ptn][1]
      if m: print 'reverse mirror',
      print n, amd.ptnmirror(ptn, m=m), \
        [amd.pmirror(p, m=m) for p in d[ptn][3]], \
        [amd.pmirror(p, m=m) for p in d[ptn][4]]
      print '----'
  print 'match'
  print amd.match('o2fo2fo9f')
  print amd.match('52f52f59f')
  print amd.match('f1of4offf')
  print amd.match('f16f46fff')
Something went wrong with that request. Please try again.