Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
lfa:2024:lab02 [2024/10/11 20:20]
stefan.sterea
lfa:2024:lab02 [2024/10/12 01:40] (current)
stefan.sterea
Line 279: Line 279:
 The program will be interpreted even if ''​Void''​ does not correctly implement the methods in ''​Tree''​ (though there are ways to enforce it at runtime. See [[https://​blog.teclado.com/​python-abc-abstract-base-classes/​|here]]). The program will be interpreted even if ''​Void''​ does not correctly implement the methods in ''​Tree''​ (though there are ways to enforce it at runtime. See [[https://​blog.teclado.com/​python-abc-abstract-base-classes/​|here]]).
  
-The class constructor is the ''​__init__(self):''​ method. Also note the mandatory presence of ''​self'',​ which is the Python equivalent of ''​this''​. Each method will receive the object it is called on as the first argument.+The class constructor is the ''​%%__init__(self):​%%''​ method. Also note the mandatory presence of ''​self'',​ which is the Python equivalent of ''​this''​. Each method will receive the object it is called on as the first argument.
  
-The method ''​def __str__(self):''​ is the Python equivalent for ''​toString()''​. An object can be displayed using the function ''​str''​.+The method ''​%%def __str__(self):​%%''​ is the Python equivalent for ''​toString()''​. An object can be displayed using the function ''​str''​.
  
 ===== The functional style ===== ===== The functional style =====
Line 368: Line 368:
  
   * for functions/​methods:​ ''​def <​func_name>​([<​param>:​ <​type>,​ ...]) -> <​return_type>''​   * for functions/​methods:​ ''​def <​func_name>​([<​param>:​ <​type>,​ ...]) -> <​return_type>''​
-  * you can also type a variable with ''​Callable[[<​param_type1>,​ ...], <​return_type>​]''​ to hold functions or lambdas+  * you can also type a variable with ''​%%Callable[[<​param_type1>,​ ...], <​return_type>​]%%''​ to hold functions or lambdas
  
 <code python> <code python>
Line 412: Line 412:
   * list[type], set[type], frozenset[type],​ dict[key_type,​ val_type]: basic data collections   * list[type], set[type], frozenset[type],​ dict[key_type,​ val_type]: basic data collections
   * * ''​Any'':​ a type is compatible with any other type (if no type hint is specified, this is what type checkers usually default to)   * * ''​Any'':​ a type is compatible with any other type (if no type hint is specified, this is what type checkers usually default to)
-  * ''​Callable[ [<​param_types>​...],​ <​return_type>​]'':​ this defines a function with a given signature+  * ''​%%Callable[[<​param_types>​...],​ <​return_type>​]%%'':​ this defines a function with a given signature
   * ''<​type1>​ | <​type2>'':​ the ''​|''​ operator allows us to indicate that a given object can be one of two(or more) types   * ''<​type1>​ | <​type2>'':​ the ''​|''​ operator allows us to indicate that a given object can be one of two(or more) types
   * ''​None'':​ represents the lack of a value (or an explicit None value); useful to mark functions which have no return value, or that a value may be purposefully missing (in combination with the ''​|''​ operator), and a None check may be necessary   * ''​None'':​ represents the lack of a value (or an explicit None value); useful to mark functions which have no return value, or that a value may be purposefully missing (in combination with the ''​|''​ operator), and a None check may be necessary
 +  * The official typing documentation [[https://​docs.python.org/​3/​library/​typing.html|here]]
 +
 +===== Practice =====
 +
 +The task of this lab will be to implement the accepting procedure of a DFA in Python, in order to get familiar with Python'​s language constructs and get a start into working with DFAs in code.
 +
 +Reading a textual representation of a DFA and a word, output whether or not the DFA accepts the word.
 +The DFA will be represented as:
 +
 +**#states**
 +
 +//the labels of the states, each on a separate line//
 +
 +**#​initial**
 +
 +//the label of the initial state//
 +
 +**#​accepting**
 +
 +//the labels of the final states, each on a separate line//
 +
 +**#​alphabet**
 +
 +//the symbols of the alphabet of the DFA, each on a separate line//
 +
 +**#​transitions**
 +
 +//source state// **:** //read character// **>** //​destination state// ​  //​(each transition on a separate line)//
 +
 +Example:
 +
 +<​code>​
 +#states
 +s0
 +s1
 +s2
 +#initial
 +s0
 +#accepting
 +s1
 +#alphabet
 +a
 +b
 +c
 +#​transitions
 +s0:b>s2
 +s0:c>s0
 +s1:a>s2
 +s1:c>s1
 +s2:a>s1
 +s2:b>s1
 +s2:c>s2
 +</​code>​
 +
 +represents the following DFA:
 +{{:​lfa:​2024:​lab2-dfa-example.png?​200|}}
 +
 +You should write a DFA class to keep the internal state and input left unconsumed and implement an ''​accept''​ method.
 +
 +You may choose how to take input: you can read the DFA from a file, you can receive the path to the file as an argument to the Python program, you can take the word as another argument or in the same file as the DFA.
 +
 +Example of reading command line arguments and working with files:
 +<code python>
 +import sys
 +
 +def read_lines(file_path:​ str) -> list[str]:
 +    try:
 +        # '​with'​ creates a context manager which handles file closing
 +        with open(file_path,​ '​r'​) as file:
 +            return file.readlines()
 +    except FileNotFoundError:​
 +        print(f"​Error:​ File '​{file_path}'​ not found."​)
 +
 +def main():
 +    if len(sys.argv) != 2:
 +        print(f"​Usage:​ python3 <​file_path>"​)
 +        sys.exit(1)
 +
 +    file_path = sys.argv[1]
 +    lines = read_file(file_path)
 +    print(lines)
 +
 +if __name__ == "​__main__":​
 +    main()
 +</​code>​