{ "cells": [ { "cell_type": "markdown", "source": [ "###
Assignment 1 \n", "####
January 18, 2024\n", "#####
Isaac Shoebottom (3429069)" ], "metadata": { "collapsed": false }, "id": "9ec6bd31bcc8447b" }, { "cell_type": "code", "execution_count": 1, "id": "7709a8186ebbb39a", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.482159200Z", "start_time": "2024-01-18T20:59:35.470889900Z" } }, "outputs": [], "source": [ "# util contains functions that make it easier to form strings \n", "# from languages, and give output that matches with expected \n", "# output for the homework, (replace empty string with epsilon)\n", "from util import *" ] }, { "cell_type": "markdown", "source": [ "
\n", "Question 1" ], "metadata": { "collapsed": false }, "id": "cf6146860173f94f" }, { "cell_type": "markdown", "source": [ "(a) $L_1 = \\{0^m 1^n | m,n \\in \\mathbb{Z}^*, n \\leq 2, m \\leq n\\}$" ], "metadata": { "collapsed": false }, "id": "b12165c136baa772" }, { "cell_type": "code", "execution_count": 2, "id": "a3ebc6e89e38cc93", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.494611400Z", "start_time": "2024-01-18T20:59:35.477374Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['ε', '1', '01', '11', '011', '0011']\n" ] } ], "source": [ "# Language rule 1, n is less than or equal to 2\n", "n = 2\n", "# Language rule 2, m is less than or equal to n\n", "m = n\n", "strings = []\n", "# Language rule 3, n and m are both non-negative integers\n", "for i in range(0, n + 1):\n", "\tfor j in range(0, m + 1):\n", "\t\tif j > i:\n", "\t\t\tcontinue\n", "\t\tstrings.append('0' * j + '1' * i)\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "b821cc2e0085663a", "metadata": { "collapsed": false }, "source": [ "(b) $L_2 = \\{a^m b^n | m,n \\in \\mathbb{Z}^*, 2 \\leq n \\leq 6, n \\text{ is a multiple of } m\\}$" ] }, { "cell_type": "code", "execution_count": 3, "id": "1d32fddeec3be96f", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.536014100Z", "start_time": "2024-01-18T20:59:35.486263100Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['abb', 'aabb', 'abbb', 'aaabbb', 'abbbb', 'aabbbb', 'aaaabbbb', 'abbbbb', 'aaaaabbbbb', 'abbbbbb', 'aabbbbbb', 'aaabbbbbb', 'aaaaaabbbbbb']\n" ] } ], "source": [ "possible_n = [2, 3, 4, 5, 6]\n", "\n", "strings = []\n", "for i in possible_n:\n", "\tinteger_divisors = []\n", "\tfor j in range(1, i + 1):\n", "\t\tif i % j == 0:\n", "\t\t\tinteger_divisors.append(j)\n", "\tfor j in integer_divisors:\n", "\t\tstrings.append('a' * j + 'b' * i)\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "2056f304860447ea", "metadata": { "collapsed": false }, "source": [ "(c) $L_3 = \\{a^n b^{2n-1} c^{3n-2} | n \\in \\mathbb{Z}^+, n \\leq 3\\}$" ] }, { "cell_type": "code", "execution_count": 4, "id": "a5ba1ad20a2b94e0", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.536014100Z", "start_time": "2024-01-18T20:59:35.491094800Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['abc', 'aabbbcccc', 'aaabbbbbccccccc']\n" ] } ], "source": [ "possible_n = [1, 2, 3]\n", "\n", "strings = []\n", "for i in possible_n:\n", "\tan = i\n", "\tbn = 2 * i - 1\n", "\tcn = 3 * i - 2\n", "\tstrings.append('a' * an + 'b' * bn + 'c' * cn)\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "520023ded45b27da", "metadata": { "collapsed": false }, "source": [ "(d) $L_4 = \\{w \\in \\{a,b\\}^* | |w| \\leq 3 \\text{ and } w \\text{ is a palindrome} \\}$" ] }, { "cell_type": "code", "execution_count": 5, "id": "452a62fd365b4f58", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.539017300Z", "start_time": "2024-01-18T20:59:35.497609900Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['ε', 'a', 'b', 'aa', 'bb', 'aaa', 'aba', 'bab', 'bbb']\n" ] } ], "source": [ "alphabet = ['a', 'b']\n", "# include empty string\n", "strings = get_all_strings_with_a_given_alphabet_and_length(alphabet, 3)\n", "def is_palindrome(s):\n", "\treturn s == s[::-1]\n", "strings = list(filter(is_palindrome, strings))\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "9dff8b1af013d957", "metadata": { "collapsed": false }, "source": [ "
\n", "Question 2" ] }, { "cell_type": "markdown", "id": "ad64b6ae580ba4dd", "metadata": { "collapsed": false }, "source": [ "(a) $L_5 = \\{w \\in \\{a,b\\}^* | |w| \\leq 3 \\text{ and } n_a(w) \\text{ is even} \\}$" ] }, { "cell_type": "code", "execution_count": 6, "id": "d5167f62fda41135", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.581083800Z", "start_time": "2024-01-18T20:59:35.542564Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['ε', 'b', 'aa', 'bb', 'aab', 'aba', 'baa', 'bbb']\n" ] } ], "source": [ "alphabet = ['a', 'b']\n", "strings = get_all_strings_with_a_given_alphabet_and_length(alphabet, 3)\n", "\n", "def number_of_a_is_even(s):\n", "\treturn s.count('a') % 2 == 0\n", "\n", "strings = list(filter(number_of_a_is_even, strings))\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "9f8b05d94c453058", "metadata": { "collapsed": false }, "source": [ "(b) $L_6 = \\{a^m b^n c^p | m,n,p \\in \\mathbb{Z}^*, m + n + p \\leq 4, m > n, n = p\\}$" ] }, { "cell_type": "code", "execution_count": 7, "id": "9b3b29ce2400f4ab", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.594528300Z", "start_time": "2024-01-18T20:59:35.585083400Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['a', 'aa', 'aabc', 'aaa', 'aaaa']\n" ] } ], "source": [ "possible_m = [0, 1, 2, 3, 4]\n", "possible_n = [0, 1, 2, 3, 4]\n", "possible_p = [0, 1, 2, 3, 4]\n", "\n", "strings = []\n", "for m in possible_m:\n", "\tfor n in possible_n:\n", "\t\tfor p in possible_p:\n", "\t\t\t# First rule\n", "\t\t\tif m + n + p <= 4:\n", "\t\t\t\t# Second rule\n", "\t\t\t\tif m > n:\n", "\t\t\t\t\t# Third rule\n", "\t\t\t\t\tif n == p:\n", "\t\t\t\t\t\tstrings.append('a' * m + 'b' * n + 'c' * p)\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "7626dea00c2aeda4", "metadata": { "collapsed": false }, "source": [ "(c) $L_7 = \\{w \\in \\{a,b,c\\}^* | |w| \\leq 4, n_a(w) > n_b(w), n_b(w) = n_c(w)\\}$" ] }, { "cell_type": "code", "execution_count": 8, "id": "8cbf5de6f2655673", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.649706300Z", "start_time": "2024-01-18T20:59:35.597530600Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['a', 'aa', 'aaa', 'aaaa', 'aabc', 'aacb', 'abac', 'abca', 'acab', 'acba', 'baac', 'baca', 'bcaa', 'caab', 'caba', 'cbaa']\n" ] } ], "source": [ "alphabet = ['a', 'b', 'c']\n", "strings = get_all_strings_with_a_given_alphabet_and_length(alphabet, 4)\n", "\n", "def number_of_a_is_greater_than_number_of_b(s):\n", "\treturn s.count('a') > s.count('b')\n", "\n", "def number_of_b_is_equal_to_number_of_c(s):\n", "\treturn s.count('b') == s.count('c')\n", "\n", "strings = list(filter(number_of_a_is_greater_than_number_of_b, strings))\n", "strings = list(filter(number_of_b_is_equal_to_number_of_c, strings))\n", "\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "88faa9e0347d6fd8", "metadata": { "collapsed": false }, "source": [ "
\n", "Question 3" ] }, { "cell_type": "markdown", "id": "efdcdcb4f9a0298", "metadata": { "collapsed": false }, "source": [ "First it could be helpful to find the set of all valid games to compare against. This is a little tricky as first you need to know the rules of the game and encode them correctly. The rules that I have discerned are as follows:\n", "1. Each valid game has 3 a's or 3 b's, denoting a victory for one side\n", "2. Once it has either victories on either side, the game does not continue, and the string is complete\n", "\n", "$$L = \\{w \\in \\{a,b\\}^* | n_a(w) = 3 \\text{ or } n_b(w) = 3 \\text{ and } w \\text{ does not end with the opposite letter}\\}$$" ] }, { "cell_type": "code", "execution_count": 9, "id": "660a123373b6ff39", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.650706300Z", "start_time": "2024-01-18T20:59:35.603524100Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['aaa', 'bbb', 'aaba', 'abaa', 'abbb', 'baaa', 'babb', 'bbab', 'aabba', 'aabbb', 'ababa', 'ababb', 'abbaa', 'abbab', 'baaba', 'baabb', 'babaa', 'babab', 'bbaaa', 'bbaab']\n" ] } ], "source": [ "alphabet = ['a', 'b']\n", "strings = get_all_strings_with_a_given_alphabet_and_length(alphabet, 5)\n", "\n", "def number_of_a_is_equal_to_3(s):\n", "\treturn s.count('a') == 3\n", "\n", "def number_of_b_is_equal_to_3(s):\n", "\treturn s.count('b') == 3\n", "\n", "# A game stops when a player has 3 a's or 3 b's, so there should be no trailing wins from the losing player\n", "def valid_game(s):\n", "\tif number_of_a_is_equal_to_3(s):\n", "\t\treturn not s.endswith('b')\n", "\telif number_of_b_is_equal_to_3(s):\n", "\t\treturn not s.endswith('a')\n", "\n", "valid_strings = list(filter(valid_game, strings))\n", "print_strings(valid_strings)" ] }, { "cell_type": "markdown", "id": "bcbd29f7048b2af2", "metadata": { "collapsed": false }, "source": [ "(a) $L_1 = \\{w \\in \\{a,b\\}^* | n_a(w) = 3 \\text{ or } n_b(w) = 3 \\}$\n", "\n", "This one is not representable with code, as the set is produces is infinite. This language places no restrictions on the length of the string, so \"aaabbbbbbbbbbbbbbbbbbbbbbbbbbb\" is a valid string in this language. So here is a few examples of valid strings in this language that are not valid in the original language L but are in this language:\n", "\n", "1. \"aaabbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n", "2. \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaa\"\n", "3. \"bababaaaaaaaaaaaaaaaaaaaaaaaaaa\"" ] }, { "cell_type": "markdown", "id": "7afad368b9ad3a09", "metadata": { "collapsed": false }, "source": [ "(b) $L_2 = \\{w \\in \\{a,b\\}^* | |w| \\leq 5, \\text{ and } n_a(w) = 3 \\text{ or } n_b(w) = 3 \\}$\n", "\n", "This language has the problem is not encoding the rule that the game stops once a player has 3 a's or 3 b's. This can be seen in these strings that are valid in this language but not in the original language L:" ] }, { "cell_type": "code", "execution_count": 10, "id": "53dc46669ffac28c", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.652706Z", "start_time": "2024-01-18T20:59:35.612375700Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['aaab', 'bbba', 'aaabb', 'aabab', 'abaab', 'abbba', 'baaab', 'babba', 'bbaba', 'bbbaa']\n" ] } ], "source": [ "strings = get_all_strings_with_a_given_alphabet_and_length(alphabet, 5)\n", "\n", "def number_of_a_or_b_is_equal_to_3(s):\n", "\treturn s.count('a') == 3 or s.count('b') == 3\n", "\n", "strings = list(filter(number_of_a_or_b_is_equal_to_3, strings))\n", "strings = [i for i in strings if i not in valid_strings] # strings - valid_strings\n", "print_strings(strings)" ] }, { "cell_type": "markdown", "id": "990482f3b9b9e5b6", "metadata": { "collapsed": false }, "source": [ "(c) $L_3 = \\{w \\in \\{a,b\\}^* | (n_a(w) = 3 \\text{ and } n_b(w) < 3) \\text{ or } (n_b(w) = 3 \\text{ and } n_a(w) < 3) \\}$\n", "\n", "This language has a similar problem to the previous one, in that it does not encode the rule that the game stops once a player has 3 a's or 3 b's. The difference in this language is that the limit of string length 5 is not explicitly stated, however it is encoded to be that way by saying that if there are 3 a's then there must be less than 3 b's, and vice versa. This means that the effective maximum length of the string is 5, and thus the language is equivalent to the language from the previous question.\n", "$$\n", "x, y \\in \\mathbb{Z}^* \\\\\n", "x = 3 \\\\\n", "y = < 3 \\\\\n", "< 3 = \\{0, 1, 2\\} \\\\\n", "x + y = \\{3, 4, 5\\}\n", "$$" ] }, { "cell_type": "code", "execution_count": 11, "id": "397defd138f4789a", "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-18T20:59:35.691666Z", "start_time": "2024-01-18T20:59:35.656707400Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['aaab', 'bbba', 'aaabb', 'aabab', 'abaab', 'abbba', 'baaab', 'babba', 'bbaba', 'bbbaa']\n" ] } ], "source": [ "strings = get_all_strings_with_a_given_alphabet_and_length(alphabet, 5)\n", "\n", "def opposite_number_of_winner_is_less_than_3(s):\n", "\tif number_of_a_is_equal_to_3(s):\n", "\t\treturn s.count('b') < 3\n", "\telif number_of_b_is_equal_to_3(s):\n", "\t\treturn s.count('a') < 3\n", "\n", "strings = list(filter(opposite_number_of_winner_is_less_than_3, strings))\n", "strings = [i for i in strings if i not in valid_strings] # strings - valid_strings\n", "print_strings(strings)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 5 }