Wizard

COMP 524: Programming Language Concepts

Spring, 2008
Jeff Terrell
jsterrel AT cs.unc.edu
(919) 962-1791 (office: Sitterson 138)

View Source of exercise1.php

In the interest of open source, and in the interest of keeping Mr. Webmaster honest, here is the PHP source of exercise1.php. (This encourages him to write clean, easy-to-understand code...well, relatively clean and easy-to-understand, that is.) If you become interested in PHP, you can read more about it at PHP: Hypertext Preprocessor. You will also see plenty of HTML code, which is what makes the World Wide Web go 'round. You can read more about HTML (and CSS, another technology used on this site) here, at the official page of the very official World Wide Web Consortium (W3C). Anyway, enough rambling, here's the code!


<?php include("header1.php"); ?>
<?php $THIS_FILE 
"exercise1.php"?>
  <title>COMP 524-S08 - Exercise 1 (Python)</title>
  <link rel="stylesheet" href="local.css" type="text/css" charset="iso-8859-1" title="Default" />
<?php include("header2.php"); ?>
<?php 
include("localheader.php"); ?>

<h1>COMP 524 Exercise 1 (Python)</h1>

<h2>General Instructions</h2>
<p>First, review the assignment submission policy in the <a href="syllabus.php">syllabus</a>.  Note that there is <strong>no collaboration</strong> allowed.</p>
<p>This assignment is <strong>due at 11:59pm on Tuesday, January 29</strong>.  Submit assignments to me via email.  All of your functions should be included in a file called 'exercise1.py', and 'exercise1.py' should include everything that you turn in.  When I am finished grading your assignment, I will email you your grade and any comments that I have.  There are a total of 100 points and 10 bonus points.</p>
<p>Remember: <strong>start early</strong>!  I guarantee my availability during office hours, but not at 11pm the night it is due.</p>
<p><strong>Update</strong> (Jan 15, 12:50pm): when you turn in exercise1.py, there should be no statements at the top level that produce output or require input.  Merely provide the required functions and anything the functions need--do not include any code related to your testing or debugging.  When I import your functions into another script, I want the import to be silently successful.  Thank you.</p>

<p><a href="exercise1.py">My solutions</a> are available.</p>

<h3>1. Matching</h3>
<dl>
  <dt>Summary</dt>
  <dd>Write a program that can recognize identifiers, number literals, and string literals.</dd>
  <dt>Background</dt>
  <dd>Working with strings is an essential part of a programming language.  After all, what is a program except one big string?  Python has a large set of <a href="http://docs.python.org/lib/string-methods.html">string methods</a>.  In addition, Python supports <a href="http://docs.python.org/lib/module-re.html">regular expressions (RE's)</a>, which are a powerful tool for strings.  The basic string methods will suffice for any task; however, RE's provide a powerful, concise way to perform many operations.  Check out the <a href="http://docs.python.org/dev/howto/regex.html">RE howto</a>.</dd>
  <dt>Details</dt>
  <dd><p>Write a function named <tt>categorize_token</tt> that accepts a single string as an argument.  If the string is an identifier, return the string 'ID'; if the string is a number literal, return the string 'NUMBER_LIT'; and if the string is a string literal, return the string 'STRING_LIT'.  Otherwise, return 'NONE'.</p>
    <p>Identifiers start with a letter (uppercase or lowercase) or an underscore (_), and afterwards have some combination of letters, digits, or underscores, but no other characters.  There can be multiple underscores at the beginning, but the first non-underscore character must be a letter.</p>
    <p>Number literals start with an optional sign (either '+' or '-').  There must be at least one digit in the number.  There may be a decimal point ('.') in the number, but not more than one.  Other than the optional sign and optional decimal point, only digits may appear in a number literal.</p>
    <p>String literals must begin and end with a tick ('), and any ticks inside the string must be immediately preceded by a backslash (\).  There can be 0 or more characters inside the enclosing ticks.  (Note: to pass a string literal to the function, you must use two sets of quotes; for example, <tt>categorize_token(&quot;'a string literal'&quot;).</tt>  The first set of quotes tells Python about the string; the second set are actually included in the string.)</p></dd>
  <dt>FAQ</dt>
  <dd>Q: For the string literal definition, what do you mean by 'character'?<br/>
      A: Any character, including alphanumeric, whitespace, special ($, #, etc), and so on.  The only character that you can easily type on your keyboard that I don't care about is the newline character.  (Note that there is a built-in character class with this definition.)<br/><br/>
      Q: Is _ a valid identifier?  What about __ or ___?<br/>
      A: No, there must be at least one letter in the identifier.<br/><br/>
      Q: I'm having problems getting all those backslashes into my regular expressions.  What should I do?<br/>
      A: Use <a href="http://docs.python.org/ref/strings.html">raw strings</a>.  That way, you don't have to escape your backslashes.  In other words, &quot;\n&quot; is a newline character, but r&quot;\n&quot; is two characters, a backslash and an n.<br/><br/>
      Q: If I use raw strings in my regular expressions, do I need to have a work-around so that I can accept regular strings also?<br/>
      A: No, raw string literals is merely a piece of syntactic sugar for string literals containing backslashes.  They are both represented as strings behind the scenes, and in fact I'm pretty sure there's no way to distinguish them from within a program.  So, if your categorize_token() function uses raw strings, you don't need to add support for regular strings--they are already supported.
  </dd>
  <dt>Points</dt>
  <dd>25 points.  5 bonus points if you use regular expressions exclusively.  5 bonus points if you can find and fix a bug with the definition of the string literals.  (My definition of a bug: there exists a string which cannot be represented with the current definition.)</dd>
  <dt>Par (i.e. instructor's solution time)</dt>
  <dd>20 minutes (using regular expressions)<br/>23 minutes extra for the string literal bug fix</dd>
</dl>

<h3>2. Counting Characters</h3>
<dl>
  <dt>Summary</dt>
  <dd>Count each character appearing in a string.</dd>
  <dt>Background</dt>
  <dd>Dictionaries are a very useful built-in type.  This problem gives you practice using them.  Check out the <a href="http://docs.python.org/tut/node7.html#SECTION007500000000000000000">tutorial section on dictionaries</a> and the <a href="http://docs.python.org/lib/typesmapping.html">library reference on dicts</a> for more details.</dd>
  <dt>Details</dt>
  <dd><p>Write a function named <tt>count_chars</tt> that accepts a single string as an argument.  The function counts the frequency of each character in the string, and returns a dictionary of the results.  The keys of the dictionary are the unique characters in the string, and the values are the corresponding counts.</p>
  <p>For example:<br/>
    <code>&gt;&gt;&gt; count_chars('banana')<br/>
    {'a': 3, 'b': 1, 'n': 2}</code></p></dd>
  <dt>FAQ</dt>
  <dd>No questions yet.</dd>
  <dt>Points</dt>
  <dd>15 points.</dd>
  <dt>Par</dt>
  <dd>6 minutes</dd>
</dl>

<h3>3. Mutable Immutables</h3>
<dl>
  <dt>Summary</dt>
  <dd>&quot;Modify&quot; a tuple by creating a new one.</dd>
  <dt>Background</dt>
  <dd>Python <a href="http://docs.python.org/tut/node7.html#SECTION007300000000000000000">tuples</a> are like lists, except that they are (like strings) immutable (i.e. unchangeable).  Immutable types are important because they can make a programming language's job much easier.  (Why?)  For example, only immutable objects can be used as keys in a dictionary.  Trying to use mutable objects for dictionary keys is one of the most common mistakes when using Python.  Note: to specify a single-element tuple, an extra comma is needed, e.g. <tt>(1,)</tt>.</dd>
  <dt>Details</dt>
  <dd><p>Write a function named <tt>mod_tuple</tt> that accepts 3 arguments: a base tuple (call it <tt>base</tt>), a tuple of indexes (call it <tt>indexes</tt>), and a tuple of values (call it <tt>values</tt>).  The length of <tt>indexes</tt> and <tt>values</tt> must be equal.  The function returns a new tuple (not a list) in which every index of <tt>base</tt> has been updated to the corresponding value.  If the lengths of <tt>indexes</tt> and <tt>values</tt> are not equal, return <tt>base</tt> unmodified.  Do not worry about a specified index being out of bounds; I guarantee that this will not happen.</p>
  <p>For example:<br/><code>
  &gt;&gt;&gt; mod_tuple( (7, 8, 9, 10, 42), (1, 2, 3), ('X', 'Yo!') )<br/>
  (7, 8, 9, 10, 42)<br/>
  &gt;&gt;&gt; mod_tuple( (7, 8, 9, 10, 42), (1, 3), ('X', 'Yo!') )<br/>
  (7, 'X', 9, 'Yo!', 42)</code></p></dd>
  <dt>FAQ</dt>
  <dd>No questions yet.</dd>
  <dt>Points</dt>
  <dd>15 points</dd>
  <dt>Par</dt>
  <dd>10 minutes</dd>
</dl>

<h3>4. Nested Lists</h3>
<dl>
  <dt>Summary</dt>
  <dd>Add and concatenate items in a nested list.</dd>
  <dt>Background</dt>
  <dd>Lists can contain lists (which can contain lists, and so on).  Typically, a nested list is a giveaway that you should use recursion.  Note: for this problem, you will need to use the <a href="http://docs.python.org/lib/module-types.html">type</a> function and module (i.e. <tt>import types</tt> or <tt>from types import *</tt>).</dd>
  <dt>Details</dt>
  <dd><p>Write a function named <tt>reduce_list</tt> that accepts a single list as an argument.  Note that this list might contain other lists, which might in turn contain yet more lists, and so on.  The non-list &quot;leaf&quot; items will be either strings or numbers.  The function will return a tuple of two items.  The first item is a single string, the concatenation of every string item in the list.  The second item is a single number, the sum of every number item in the list.</p>
  <p>For example:<br/><code>
  &gt;&gt;&gt; reduce_list( [1, 17, ['EyeA', -2, ['mmS', 7], -7], [26, 'tring!']])<br/>
  ('EyeAmmString!', 42)</code></p>
  <p>Note: the string concatenation depends on the order in which one encounters each string leaf.  To avoid ambiguity, you must process each sub-list as it occurs (i.e. immediately recur when you encounter a sub-list).  This is called an <em>in-order traversal</em> of a tree.  (Note that a nested list is really a general tree.)</p></dd>
  <dt>FAQ</dt>
  <dd>No questions yet.</dd>
  <dt>Points</dt>
  <dd>20 points</dd>
  <dt>Par</dt>
  <dd>10 minutes</dd>
</dl>

<h3>5. Memoization with dicts</h3>
<dl>
  <dt>Summary</dt>
  <dd>Create a recursive function to compute Fibonacci numbers, and explore the concept of memoization using Python's dictionary objects.</dd>
  <dt>Background</dt>
  <dd><p>Consider the following function to compute the i-th Fibonacci number:</p>
<pre>def fibonacci(n):
    if n == 1 or n == 2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)</pre>
    <p>This function is very inefficient because it ends up computing the same thing multiple times.  For example, if you call <tt>fibonacci(21)</tt>, then <tt>fibonacci(3)</tt> gets computed 4,181 times, and fibonacci(50) computes fibonacci(20) 1,346,269 times!  Clearly, this solution will not scale to large numbers.  (This sort of problem is called a <em>branched recursion</em> problem.)</p>
    <p>This problem can be solved by a technique called <em>memoization</em>, also called &quot;dynamic programming&quot;.  Instead of computing fibonacci(N) many times, fibonacci(N) is computed exactly once, and the result is saved for future computations.  To achieve memoization in Python, simply store the result of fibonacci(i) in a global dictionary, and check the dictionary before recurring.</p></dd>
  <dt>Details</dt>
  <dd>Write a function named <tt>fibonacci</tt> that accepts one argument: an integer specifying which Fibonacci number to compute.  Use recursion and memoization as discussed above to achieve an efficient recursive solution.  (You may assume that you will always receive a positive integer as input.)</dd>
  <dt>FAQ</dt>
  <dd>Q: You mean that I can define a dictionary outside of my fibonacci() function?  I thought you said you didn't want anything outside of a function in exercise1.py.<br/>
      A: Yes, you can define the dictionary outside of the function.  I don't want anything that will hinder me importing your exercise1.py--specifically, input and output routines.  But defining a global variable is fine.
  </dd>
  <dt>Points</dt>
  <dd>25 points.  Full points awarded only for solutions involving recursion and memoization.</dd>
  <dt>Par</dt>
  <dd>23 minutes</dd>
</dl>

<?php include("footer.php"); ?>
viewsource.php: Last Modified: 02/06/08@14:19:08 | Size: 2795 bytes | View Source Valid XHTML 1.1 Valid CSS