김창준씨의 코드를 보고 느끼는 점이 많아 흉내를 내 보았습니다.

재밌는 시간이었구요. ^^

~cpp #!python
# -*- coding: euc-kr -*-

'''
 
* slurpy (slimp and slump)

* slump - (D or E) and F+ and (slump or G)
* slimp - A and (H or ((B and slimp and C) or (slump and C))

** find slurpy!

[example]
Slumps : DFG, EFG, DFFFFFG, DFDFDFDFG, DFEFFFFFG 
Not Slumps: DFEFF, EFAHG, DEFG, DG, EFFFFDG 
Slimps: AH, ABAHC, ABABAHCC, ADFGC, ADFFFFGC, ABAEFGCC, ADFDFGC 
Not Slimps: ABC, ABAH, DFGC, ABABAHC, SLIMP, ADGC 
Slurpys: AHDFG, ADFGCDFFFFFG, ABAEFGCCDFEFFFFFG 
Not Slurpys: AHDFGA, DFGAH, ABABCC 
'''

import unittest


class UnitPattern:
    def __init__(self, *args):
        self.args = args
        self._remain = ''

    def match(self, target):
        raise NotImplementedError 

    def remain(self):
        return self._remain


class Word(UnitPattern):
    def match(self, target):
        if not target: return False
        self._remain = target[1:]
        return self.args[0][0] == target[0]


class And(UnitPattern):
    def match(self, target):
        for arg in self.args:
            if not arg.match(target):
                return False
            target = arg.remain()
        self._remain = target
        return True


class Or(UnitPattern):
    def match(self, target):
        for arg in self.args:
            if arg.match(target): 
                self._remain = arg.remain()
                return True
        return False


class More(UnitPattern):
    def match(self, target):
        if not target: return False
        moreword = self.args[0][0]
        for count, t in enumerate(target):
            if t != moreword:
                if count == 0 : return False
                break
        self._remain = target[count:]
        return True
        

class MultiPattern:
    def match(self, target):
        return self.pat.match(target)

    def remain(self):
        return self.pat.remain()


class Slump(MultiPattern):
    ''' slump - (D or E) and F+ and (slump or G) '''

    def __init__(self):
        self.pat = And(
                Or(Word('D'), Word('E')),
                More('F'),
                Or(self, Word('G'))
            )


class Slimp(MultiPattern):
    ''' slimp - A and (H or ((B and slimp and C) or (slump and C)) '''

    def __init__(self):
        self.pat = And(
                Word('A'),
                Or(
                    Word('H'),
                    Or(
                        And(Word('B'), self, Word('C')),
                        And(Slump(), Word('C'))
                    )
                )
            )


def isSlurpy(target):
    ''' slurpy (slimp and slump) '''
    pat = And(Slimp(), Slump())
    result = pat.match(target)
    if pat.remain(): return False
    return result



### test code   ##########################################################


class SlurpyTest(unittest.TestCase):    
    def testWord(self):
        word = Word('D')
        self.assertEquals(True, word.match('DEF'))
        self.assertEquals('EF', word.remain())
        
    def testAnd(self):
        D = Word('D')
        E = Word('E')
        andDE = And(D,E)
        self.assertEquals(True, andDE.match('DE'))

    def testMore(self):
        self.assertEquals(True, More('F').match('FFFF'))
        self.assertEquals(True, And(Word('D'), More('F')).match('DFFF'))
        more = More('F')
        more.match('FGHG')
        self.assertEquals('GHG', more.remain())

    def testOr(self):
        self.assertEquals(True, Or(Word('F'), Word('E')).match('F'))
        self.assertEquals(True, Or(Word('F'), Word('E')).match('E'))
        self.assertEquals(True, 
            And(More('K'), Or(Word('F'), Word('E'))).match('KKKKE'))

    def testSlump(self):
        #Slumps : DFG, EFG, DFFFFFG, DFDFDFDFG, DFEFFFFFG 
        self.assertEquals(True, Slump().match('DFG'))
        self.assertEquals(True, Slump().match('EFG'))
        self.assertEquals(True, Slump().match('DFFFFFG'))
        self.assertEquals(True, Slump().match('DFDFDFDFG'))
        self.assertEquals(True, Slump().match('DFEFFFFFG'))
        #Not Slumps : DFEFF, EFAHG, DEFG, DG, EFFFFDG 
        self.assertEquals(False, Slump().match('DFEFF'))
        self.assertEquals(False, Slump().match('EFAHG'))
        self.assertEquals(False, Slump().match('DEFG'))
        self.assertEquals(False, Slump().match('DG'))
        self.assertEquals(False, Slump().match('EFFFFDG'))

    def testSlimp(self):
        #Slimps: AH, ABAHC, ABABAHCC, ADFGC, ADFFFFGC, ABAEFGCC, ADFDFGC 
        self.assertEquals(True, Slimp().match('AH'))
        self.assertEquals(True, Slimp().match('ABAHC'))
        self.assertEquals(True, Slimp().match('ABABAHCC'))
        self.assertEquals(True, Slimp().match('ADFGC'))
        self.assertEquals(True, Slimp().match('ADFFFFGC'))
        self.assertEquals(True, Slimp().match('ABAEFGCC'))
        self.assertEquals(True, Slimp().match('ADFDFGC'))
        #Not Slimps: ABC, ABAH, DFGC, ABABAHC, SLIMP, ADGC 
        self.assertEquals(False, Slimp().match('ABC'))
        self.assertEquals(False, Slimp().match('ABAH'))
        self.assertEquals(False, Slimp().match('DFGC'))
        self.assertEquals(False, Slimp().match('ABABAHC'))
        self.assertEquals(False, Slimp().match('SLIMP'))
        self.assertEquals(False, Slimp().match('ADGC'))
        
    def testSlurpy(self):
        #Slurpys: AHDFG, ADFGCDFFFFFG, ABAEFGCCDFEFFFFFG 
        self.assertEquals(True, isSlurpy('AHDFG'))
        self.assertEquals(True, isSlurpy('ADFGCDFFFFFG'))
        self.assertEquals(True, isSlurpy('ABAEFGCCDFEFFFFFG'))
        #Not Slurpys: AHDFGA, DFGAH, ABABCC
        self.assertEquals(False, isSlurpy('AHDFGA'))
        self.assertEquals(False, isSlurpy('DFGAH'))
        self.assertEquals(False, isSlurpy('ABABCC'))


if __name__ == '__main__':
    unittest.main(argv=('', '-v'))
Retrieved from http://wiki.zeropage.org/wiki.php/Slurpys/박응용
last modified 2021-02-07 05:28:02