# Tests for Exercise Sheet 5
# Python 2 - SS13

import unittest

from l5_dfa import DFA
from l5_nfa_2 import NFA

class TestDFA(unittest.TestCase):
    def test_intersection(self):
        # construct two autom. which accept strings of 'a's

        mod3_dfa = DFA(0, [(0, 'a', 1), (1, 'a', 2), (2, 'a', 0)], [0])
        mod2_dfa = DFA(0, [(0, 'a', 1), (1, 'a', 0)], [0])

        # check that the auto. accept what we expect
        mod2_words = ['', 'aa', 'aaaa', 'a'*6]
        for word in mod2_words:
            self.assertTrue(mod2_dfa.recognize(word))
        mod3_words = ['', 'aaa', 'aaaaaa']
        for word in mod3_words:
            self.assertTrue(mod3_dfa.recognize(word))


        intersection = mod3_dfa.intersect(mod2_dfa)
        # check that the intersection is correct, ie: strings of 'a' of multiples of 6
        for i in range(0, 25):
            word = 'a'*i
            if i%6 == 0:
                self.assertTrue(intersection.recognize(word))
            else:
                self.assertFalse(intersection.recognize(word))

class TestNFA(unittest.TestCase):
    def test_infrastructure(self):
        trans = [(0,'a',1), (0, 'b', 2), (2, 'a', 1)]
        start = 0
        end = [1]
        nfa = NFA(start, trans, end)
        self.assertCountEqual(trans, nfa.transitions())

    def test_is_deterministic(self):
        dfa = NFA(0, [(0, 'a', 0)], [0])
        nfa = NFA(0, [(0, 'a', 1), (0, 'a', 2), (1, 'b', 0), (2, 'b', 3)], [3])
        nfa2 = NFA(1, [(1, 'a', 2), (1, '', 3), (2, 'd', 1), (2, 'b', 3), (3, 'a', 3), (3, 'c', 4), (4, 'b', 4), (4, '', 3)], [3])
        self.assertTrue(dfa.is_deterministic())
        self.assertFalse(nfa.is_deterministic())
        self.assertFalse(nfa2.is_deterministic())

    def test_determininize(self):
        nfa = NFA(0, [(0, 'a', 1), (0, 'a', 2), (1, 'b', 0), (2, 'b', 3)], [3])
        self.assertFalse(nfa.is_deterministic())

        dfa = nfa.determinize()
        self.assertTrue(dfa.is_deterministic())
        
        test_words = ['', 'a', 'b', 'ba', 'aa', 'ab', 'abab', 'abba', 'baba', 'aab', 'abb', 'ababab']
        for word in test_words:
            self.assertEqual(nfa.recognize(word), dfa.recognize(word))
 
        

        
if __name__ == '__main__':
    unittest.main()    
