Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
marey committed Mar 3, 2019
0 parents commit a9e406c
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 0 deletions.
136 changes: 136 additions & 0 deletions quizes/quiz01/quiz_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Written by *** and Eric Martin for COMP9021
import re

'''
See https://en.wikipedia.org/wiki/Deterministic_finite_automaton
We consider as alphabet a set of digits.
We accept partial transition functions (that is, there might be no transition
for a given state and symbol).
With the accepts() function, we will deal with a single accept state rather than
a set of accept states.
In the test cases below, transitions_2 is the wikipedia example
(with 'S1' and 'S2' renamed as 'state_1' and 'state_2', respectively),
so the automaton that with 'state_1' as both initial and unique accept state,
accepts words with an even number of occurrences of 0's.
'''


def describe_automaton(transitions):
'''
The output is produced with the print() function.
>>> transitions_1 = {('q0', 0): 'q1', ('q1', 1): 'q0'}
>>> describe_automaton(transitions_1)
When in state "q0" and processing "0", automaton's state becomes "q1".
When in state "q1" and processing "1", automaton's state becomes "q0".
>>> transitions_2 = {('state_1', 0): 'state_2', ('state_1', 1): 'state_1',\
('state_2', 0): 'state_1', ('state_2', 1): 'state_2'}
>>> describe_automaton(transitions_2)
When in state "state_1" and processing "0", automaton's state becomes "state_2".
When in state "state_1" and processing "1", automaton's state becomes "state_1".
When in state "state_2" and processing "0", automaton's state becomes "state_1".
When in state "state_2" and processing "1", automaton's state becomes "state_2".
'''
# 直接遍历
keys = transitions.keys()
for index in range(0, len(transitions)):
(state, code) = keys[index]
value = transitions.get((state, code))
print(f'When in state "{state}" and processing "{code}", \
automaton\'s state becomes "{value}".')

# 利用dict的key
for (state, code) in transitions.keys():
print(f'When in state "{state}" and processing "{code}", \
automaton\'s state becomes "{transitions[(state, code)]}".')

# 高级用法
for (state, code) in transitions:
print(f'When in state "{state}" and processing "{code}", \
automaton\'s state becomes "{transitions[(state, code)]}".')

# 另外一种高级用法
for (state, code), value in transitions.items():
print(f'When in state "{state}" and processing "{code}", \
automaton\'s state becomes "{value}".')


def transitions_as_dict(transitions_as_list):
'''
transitions_as_list is a list of strings of the form 'state_1,symbol:state_2'
where 'state_1' and 'state_2' are words and 'symbol' is one of the 10 digits.
We assume that there is at most one 'state_2' for given 'state_1' and 'symbol'.
>>> transitions_as_dict(['q0,0:q1', 'q1,1:q0'])
{('q0', 0): 'q1', ('q1', 1): 'q0'}
>>> transitions_as_dict(['state_1,0:state_2', 'state_1,1:state_1',\
'state_2,0:state_1', 'state_2,1:state_2'])
{('state_1', 0): 'state_2', ('state_1', 1): 'state_1', \
('state_2', 0): 'state_1', ('state_2', 1): 'state_2'}
'''

# define variables
transitions = {}
# for each line
for line in transitions_as_list:
# split or re
state, code, new_state = re.split('[,:]', line)
# check all the value is correct
if state and code and new_state:
# set result
transitions[state, int(code)] = new_state

return transitions


def accepts(transitions, word, initial_state, accept_state):
'''
Starting in 'initial_state', if the automaton can process with 'transitions'
all symbols in 'word' and eventually reach 'accept_state', then the function
returns True; otherwise it returns False.
>>> transitions_1 = {('q0', 0): 'q1', ('q1', 1): 'q0'}
>>> accepts(transitions_1, '00', 'q0', 'q1')
False
>>> accepts(transitions_1, '2', 'q0', 'q0')
False
>>> accepts(transitions_1, '0101010', 'q0', 'q0')
False
>>> accepts(transitions_1, '01010101', 'q0', 'q0')
True
>>> not accepts(transitions_1, '01', 'q0', 'q1') and\
accepts(transitions_1, '010', 'q0', 'q1')
True
>>> transitions_2 = {('state_1', 0): 'state_2', ('state_1', 1): 'state_1',\
('state_2', 0): 'state_1', ('state_2', 1): 'state_2'}
>>> accepts(transitions_2, '011', 'state_1', 'state_1')
False
>>> accepts(transitions_2, '001110000', 'state_1', 'state_1')
True
>>> accepts(transitions_2, '1011100101', 'state_1', 'state_1')
True
>>> accepts(transitions_2, '10111000101', 'state_1', 'state_1')
False
'''
for char in word:
if (initial_state, int(char)) not in transitions:
return False
initial_state = transitions[initial_state, int(char)]

return initial_state == accept_state


if __name__ == '__main__':
# import doctest

# doctest.testmod()

transitions_1 = {('q0', 0): 'q1', ('q1', 1): 'q0'}
describe_automaton(transitions_1)
Binary file added quizes/quiz02/quiz_2.pdf
Binary file not shown.
142 changes: 142 additions & 0 deletions quizes/quiz02/quiz_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Written by *** and Eric Martin for COMP9021


def rule_encoded_by(rule_nb):
'''
"rule_nb" is supposed to be an integer between 0 and 15.
'''
values = [int(d) for d in f'{rule_nb:04b}']
return {(p // 2, p % 2): values[p] for p in range(4)}


def describe_rule(rule_nb):
'''
"rule_nb" is supposed to be an integer between 0 and 15.
>>> describe_rule(3)
The rule encoded by 3 is: {(0, 0): 0, (0, 1): 0, (1, 0): 1, (1, 1): 1}
After 0 followed by 0, we draw 0
After 0 followed by 1, we draw 0
After 1 followed by 0, we draw 1
After 1 followed by 1, we draw 1
>>> describe_rule(4)
The rule encoded by 4 is: {(0, 0): 0, (0, 1): 1, (1, 0): 0, (1, 1): 0}
After 0 followed by 0, we draw 0
After 0 followed by 1, we draw 1
After 1 followed by 0, we draw 0
After 1 followed by 1, we draw 0
>>> describe_rule(11)
The rule encoded by 11 is: {(0, 0): 1, (0, 1): 0, (1, 0): 1, (1, 1): 1}
After 0 followed by 0, we draw 1
After 0 followed by 1, we draw 0
After 1 followed by 0, we draw 1
After 1 followed by 1, we draw 1
>>> describe_rule(14)
The rule encoded by 14 is: {(0, 0): 1, (0, 1): 1, (1, 0): 1, (1, 1): 0}
After 0 followed by 0, we draw 1
After 0 followed by 1, we draw 1
After 1 followed by 0, we draw 1
After 1 followed by 1, we draw 0
'''
rule = rule_encoded_by(rule_nb)
print('The rule encoded by', rule_nb, 'is: ', rule)
# print()
# INSERT YOUR CODE HERE TO PRINT 4 LINES
for (first, second), last in rule.items():
print(f"After {first} followed by {second}, we draw {last}")


def draw_line(rule_nb, first, second, length):
'''
"rule_nb" is supposed to be an integer between 0 and 15.
"first" and "second" are supposed to be the integer 0 or the integer 1.
"length" is supposed to be a positive integer (possibly equal to 0).
Draws a line of length "length" consisting of 0's and 1's,
that starts with "first" if "length" is at least equal to 1,
followed by "second" if "length" is at least equal to 2,
and with the remaining "length" - 2 0's and 1's determined by "rule_nb".
>>> draw_line(3, 0, 0, 1)
0
>>> draw_line(3, 1, 0, 5)
10101
>>> draw_line(4, 1, 0, 9)
100000000
>>> draw_line(4, 0, 1, 13)
0110000000000
>>> draw_line(11, 1, 0, 16)
1010101010101010
>>> draw_line(11, 1, 1, 19)
1111111111111111111
>>> draw_line(14, 0, 0, 21)
001101101101101101101
>>> draw_line(14, 1, 0, 22)
1011011011011011011011
'''
rule = rule_encoded_by(rule_nb)
# INSERT YOUR CODE HERE TO PRINT ONE LINE
result = []
if length >= 1:
result.append(first)
if length >= 2:
result.append(second)
for i in range(2, length):
temp = rule[(first, second)]
result.append(temp)
first = second
second = temp

print("".join((str(item) for item in result)))


def uniquely_produced_by_rule(line):
'''
"line" is assumed to be a string consisting of nothing but 0's and 1's.
Returns an integer n between 0 and 15 if the rule encoded by n is the
UNIQUE rule that can produce "line"; otherwise, returns -1.
>>> uniquely_produced_by_rule('1100110011')
12
>>> uniquely_produced_by_rule('01100000')
4
>>> uniquely_produced_by_rule('001101101')
14
>>> uniquely_produced_by_rule('11111111')
-1
>>> uniquely_produced_by_rule('00011')
-1
>>> uniquely_produced_by_rule('11001')
-1
>>> uniquely_produced_by_rule('0010001')
-1
>>> uniquely_produced_by_rule('0010001')
-1
>>> uniquely_produced_by_rule('11111111111111110')
-1
'''
# REPLACE pass ABOVE WITH YOUR CODE
rules = {}
if len(line) >= 2:
first, second = line[0], line[1]

for last in line[2:]:
if (first, second) in rules and rules[(first, second)] != last:
return -1
else:
rules[(first, second)] = last
first, second = second, last

if len(rules) == 4:
keys = [('0', '0'), ('0', '1'), ('1', '0'), ('1', '1')]
result = ""
for key in keys:
result += rules[key]
return int(result, 2)
else:
return -1


if __name__ == '__main__':
import doctest
doctest.testmod()
# print(uniquely_produced_by_rule('1100110011'))

0 comments on commit a9e406c

Please sign in to comment.