Scripting Languages G22.3033-002 Summer 2008 All problems and example solutions

Martin Hirzel

http://www.cs.nyu.edu/courses/summer08/G22.3033-002/

Table of Contents


Next: , Up: (dir)

Top


Next: , Previous: Top, Up: Top

About


Up: About

Instructions for example solutions

These are example solutions. Please keep in mind that often, there is not just one correct solution to a question. If you come up with different answers, then it may be that both your answers and these answers here are correct. Of course, these answers here may also contain mistakes. If you spot a mistake, please let me know so I can correct it.


Next: , Previous: About, Up: Top

Scripting Languages G22.3033-002 Summer 2008 All homework problems


Next: , Up: Problems

Reading assignments

Read for lecture on 5/29: Ousterhout'98
John K. Ousterhout. Scripting: Higher-Level Programming for the 21st Century. IEEE Computer 31(3), 1998. Available online at http://www.tcl.tk/doc/scripting.html.


Next: , Previous: hw01-readings, Up: Problems

Concept questions


Next: , Up: hw01-concepts

hw01-1 Dynamic typing

(5+6+6 = 17 points)

  1. Add explicit type annotations to the following VBA program.
              Sub PrintArray(Arr())
                Debug.Print "PrintArray:"
                For I = 0 To UBound(Arr)
                  Debug.Print "  " & I & " " & Arr(I)
                Next I
              End Sub
              Sub Main()
                Dim fruits(2)
                fruits(0) = "apple"
                PrintArray fruits
                fruits(1) = "orange"
                fruits(2) = "banana"
                PrintArray fruits
              End Sub
         
  2. List three advantages of static typing.
  3. List three advantages of dynamic typing.


Previous: hw01-1, Up: hw01-concepts

hw01-2 Precedence and associativity

(5 + 8 = 13 points)

  1. Remove as many parentheses as possible from the following VBA expression without changing its meaning: (2 - ((2 - 2) - (2 * 2)))
  2. The VBA operator table in the 5/22/2008 lecture slides puts all binary logical operators (And, Or, Xor, Eqv, Imp) on the same line, but in fact, they do not all have the same precedence. Does implication (“Imp”) have a higher precedence, lower precedence, or the same precedence as conjunction (“And”) in VBA? Describe experiments for answering this question.


Next: , Previous: hw01-concepts, Up: Problems

Programming exercises


Next: , Up: hw01-programming

hw01-3 Euclidian distance (VBA)

(10 points) Write a function that computes the Euclidian distance between two arrays. The Euclidian distance between two vectors A and B is defined as

sqrt((A0-B0)^2 + ... + (An-Bn)^2)

For example, consider the following test driver:

     Sub Main()
       Dim x1(2) As Double, x2(2) As Double
       x1(0) = 0: x1(1) = 0: x1(2) = 0
       x2(0) = 0: x2(1) = 0: x2(2) = 0
       Debug.Print EuclidDistance(x1, x2)
       x2(0) = 1
       Debug.Print EuclidDistance(x1, x2)
       x1(2) = 1
       Debug.Print EuclidDistance(x1, x2)
     End Sub

The program should print 0, 1, and 1.41421.


Previous: hw01-3, Up: hw01-programming

hw01-4 Average rows (VBA)

(10 points)

Write a function AverageRows that computes the average of each row in a two-dimensional array, and writes the results to a one-dimensional array. For example, consider the following test driver:

     Sub Main()
       Dim x(1, 2) As Double
       x(0, 0) = 1: x(0, 1) = 2: x(0, 2) = 0
       x(1, 0) = 0: x(1, 1) = 0: x(1, 2) = 2
       Dim y(1) As Double
       Call AverageRows(y, x)
       Debug.Print y(0) & ", " & y(1)
     End Sub

The program should print 1, 0.66667.


Next: , Previous: hw01-programming, Up: Problems

Reading assignments

Read for lecture on 6/5: perlintro(1) man page
Kirrily “Skud” Robert. perlintro(1) man page. Perl 5 documentation. Available on machines that have Perl properly installed, and also available online at http://perldoc.perl.org/perlintro.html.


Next: , Previous: hw02-readings, Up: Problems

Concept questions


Next: , Up: hw02-concepts

hw02-1 Properties

(5+5 = 10 points)

  1. Give an example for reading and writing each of the properties of the following VBA class. Briefly explain what it does.
              Option Explicit
              Public Celsius As Double
              Public Property Let Fahrenheit(f As Double)
                Celsius = 5 * (f - 32) / 9
              End Property
              Public Property Get Fahrenheit() As Double
                Fahrenheit = (9 * Celsius / 5) + 32
              End Property
         
  2. How would you implement a write-once property in VBA?


Previous: hw02-1, Up: hw02-concepts

hw02-2 Call-backs

(5 + 5 = 10 points)

  1. Explain briefly how VBA supports call-backs.
  2. Describe another plausible choice that the VBA designers could have made for call-backs.


Next: , Previous: hw02-concepts, Up: Problems

Programming exercises


Next: , Up: hw02-programming

hw02-3 Associative array (VBA)

(15 points) Consider the following abstract class StringMap.

     Option Explicit
     
     Public Function size() As Integer
     End Function
     
     Public Function Contains(key As String) As Boolean
     End Function
     
     Public Property Let Data(key As String, Value As Variant)
     End Property
     
     Public Property Get Data(key As String)
     End Property

StringMap defines the interface for a container that maps strings to values. Write a subclass SimpleStringMap that implements StringMap. For example, consider the following test driver:

     Sub driveStringMap()
       Dim m As StringMap
       Set m = New SimpleStringMap
       m.Data("apple") = "Apfel"
       m.Data("pear") = "Birne"
       Debug.Print m.size & " " & m.Data("apple")
       m.Data("apple") = "pomme"
       Debug.Print m.size & " " & m.Data("apple")
     End Sub

The program should print 2 Apfel, 2 pomme. Don't worry about performance, just write a simple correct implementation of the interface. Make sure that your implementation works for an unbounded number of elements, not just two.


Previous: hw02-3, Up: hw02-programming

hw02-4 Dendrogram (VBA)

(15 points) A dendrogram is a tree diagram that arranges similar items in clusters. For example, the following dendrogram shows items A-E in a hierarchy, annotating each cluster with a similarity score.

A textual specification for the above example dendrogram is

(((A:1.5:B):2.8:(C:1.9:D)):4.8:E)

Your task is to design a dialog box for drawing a dendrogram that looks like this:

This will require you to create a user form, and to wire it up with the appropriate callbacks. To do the actual drawing, you can use the subroutine DrawDendrogram defined below.

     Sub ParseDendrogram(ByVal spec As String, ByRef lspec As String, _
                         ByRef y As Double, ByRef rspec As String)
       Dim c1 As Integer, c2 As Integer, depth As Integer, i As Integer
       c1 = -1: c2 = -1: depth = 0
       For i = 1 To Len(spec)
         Select Case Mid(spec, i, 1)
           Case "("
             depth = depth + 1
           Case ")"
             depth = depth - 1
           Case ":"
             If 1 = depth Then If c1 < 0 Then c1 = i Else c2 = i
         End Select
       Next i
       lspec = Mid(spec, 2, c1 - 2)
       y = CDbl(Mid(spec, c1 + 1, c2 - c1 - 1))
       rspec = Mid(spec, c2 + 1, Len(spec) - c2 - 1)
     End Sub
     
     Sub DrawDendrogram(ByVal cvs As Canvas, ByVal spec As String, _
                        ByRef x As Double, ByRef y As Double)
       ' The original x is the position where the left-most leaf should go.
       ' On return, x = width of subtree and y = height of subtree.
       Dim ox As Double
       ox = x
       If Mid(spec, 1, 1) = "(" Then
         Dim lspec As String, rspec As String
         ParseDendrogram spec, lspec, y, rspec
         Dim lx As Double, ly As Double, rx As Double, ry As Double
         lx = x
         DrawDendrogram cvs, lspec, lx, ly
         rx = ox + lx
         DrawDendrogram cvs, rspec, rx, ry
         x = lx + rx
         Dim x1 As Double, x2 As Double
         x1 = ox + 0.5 * (lx - 1): x2 = ox + lx + 0.5 * (rx - 1)
         With ActiveWindow.Selection.SlideRange.Shapes
           .AddLine(cvs.x(x1), cvs.y(ly), cvs.x(x1), cvs.y( y)).Select
           .AddLine(cvs.x(x1), cvs.y( y), cvs.x(x2), cvs.y( y)).Select
           .AddLine(cvs.x(x2), cvs.y( y), cvs.x(x2), cvs.y(ry)).Select
         End With
       Else
         x = 1: y = 0
         ActiveWindow.Selection.SlideRange.Shapes.AddLabel( _
           msoTextOrientationHorizontal, cvs.x(ox),cvs.y(0), 0.4,0.4).Select
         ActiveWindow.Selection.ShapeRange.TextFrame.TextRange.Text = spec
       End If
     End Sub

The DrawDendrogram subroutine relies on an instance of class Canvas to translate logical x/y positions into physical positions on the slide. The class module Canvas is defined as follows:

     Public xbase As Double, xscale As Double
     Public ybase As Double, yscale As Double
     
     Public Function x(ByVal logicalX As Double)
       x = xbase + xscale * logicalX
     End Function
     
     Public Function y(ByVal logicalY As Double)
       y = ybase - yscale * logicalY
     End Function


Next: , Previous: hw02-programming, Up: Problems

Quiz 1 problems.


Next: , Up: quiz1-problems

quiz1-1 Gradual typing

(10 points) Add explicit type annotations to the following VBA module.

     Function geometricMean(arr())
       geometricMean = 1
       For i = LBound(arr) To UBound(arr)
         geometricMean = geometricMean * arr(i)
       Next i
       n = 1 + UBound(arr) - LBound(arr)
       geometricMean = geometricMean ^ (1.0 / n)
     End Function
     Sub main()
       Dim A(1)
       A(0) = 1: A(1) = 2
       Debug.Print geometricMean(A)
     End Sub


Next: , Previous: quiz1-1, Up: quiz1-problems

quiz1-2 Precedence and associativity

(10 points) Consider the following excerpt of Perl's operator table.

     Operator  Arity  Associativity  Description
     **        2      right          exponentiation
     *         2      left           multiplication
     =         2      right          assignment

Fully parenthesize the following expression: $x = $y = 3 ** 3 ** 3 * 2.


Previous: quiz1-2, Up: quiz1-problems

quiz1-3 Call-backs

(4+3+3 = 10 points)

  1. How are call-backs supported in VBA user forms?
  2. Give an advantage for this language design choice.
  3. Give a disadvantage for this language design choice.


Next: , Previous: quiz1-problems, Up: Problems

Reading assignments

Read for lecture on 6/12:
Gilad Bracha. Pluggable Type Systems. OOPSLA Workshop on Revival of Dynamic Languages (RDL), 2004. Available online at http://pico.vub.ac.be/~wdmeuter/RDL04/papers/Bracha.pdf


Next: , Previous: hw03-readings, Up: Problems

Concept questions


Next: , Up: hw03-concepts

hw03-1 Regular expressions

(7+6 = 13 points)

  1. Consider the following Perl regular expression: (0[xX])?[a-fA-F0-9]+. Rewrite this regular expression using only the “essential” features of formal regular expressions.
  2. Write a regular expression that captures the PID and PPID from a line of output of the “ps -l” command. For example, consider the following output:
              doowop1:~> ps -l
              F S  UID   PID  PPID C PRI NI ADDR SZ WCHAN TTY       TIME CMD
              0 S 1088 23431 23421 0  75  0 - 18991 wait  pts/4 00:00:00 bash
              0 R 1088 23641 23431 0  77  0 - 15863 -     pts/4 00:00:00 ps
         

    The PID and PPID of the line of output for bash are 23431 and 23421.


Previous: hw03-1, Up: hw03-concepts

hw03-2 Static and dynamic scoping

(5 + 7 = 12 points)

  1. What does the following Perl program print, and why?
              #!/usr/bin/perl -w
              $a = "-";
              sub f {
                our $a = "f";
                sub g { local $a = "g"; h() }
                sub h { print $a, "\n" }
                g();
                print $a, "\n"
              }
              f()
         
  2. When a variable in a Perl function has only an implicit declaration, how is it scoped? Give an example that illustrates your answer.


Next: , Previous: hw03-concepts, Up: Problems

Programming exercises

This homework practices the “How to learn a language” steps from the lecture on 5/29/2008:

I. Use peers & gurus.
Ask around among your friends to find out who knows Perl. Try learning things for yourself, but if you get stuck, ask someone for help.
II. Install tools.
Perl is already installed on the CIMS Linux machines, so you just need to double-check that the interpreter works for you. Try it on Linux/x86 machines, for example, doowop1. Here is a list of compute servers: http://www.cims.nyu.edu/systems/resources/computeservers/.
III. Read tutorial.
This was last week's reading assignment: Kirrily “Skud” Robert. perlintro(1) man page. Perl 5 documentation. Available on machines that have Perl properly installed, and also available online at http://perldoc.perl.org/perlintro.html.
IV. Find language & library reference.
The easiest place to look are the man pages, including perlsyn(1), perlop(1), perlfunc(1), perlre(1). See perl(1) for an overview.
V. Read example programs.
There was example code on the lecture slides. Problem hw03-3 below asks you to read and understand another small script.
VI. Write example programs.
Problems hw03-4 and hw03-5 below ask you to write some Perl code that exercises core features.
VII. Understand error messages.
As you solve the programming problems (hw03-4 and hw03-5), you should pay attention to what error messages you get. If any error message is confusing, remember it so that it is familiar the next time you get it.
VIII. Practice
There will be more Perl programming exercises in hw04. But you should also think about little projects of your own. Ideally, Perl will make you more productive at things you have to do anyway outside of this class.


Next: , Up: hw03-programming

hw03-3 CSV to fixed-width (Perl)

(2+0+2+2 = 6 points) Consider the following Perl script:

     #!/usr/bin/perl -w
     while (<>) {
       chomp;
       push @rows, [ split /,\s/ ];
     }
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         $w = length $row->[$i];
         $widths[$i] = $w if !$widths[$i] || $w > $widths[$i];
       }
     }
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         print " " x (1 + $widths[$i] - length $row->[$i]);
         print $row->[$i];
       }
       print "\n";
     }
  1. Run the script. What does it print for the following input? (To answer this question, you need to put the script in a file, for example, csv2fixed.pl, and the input into another file, for example, table.csv. Then, you do perl csv2fixed.pl < input.csv).
              0, 0, 10, 0
              10, 0, 10, 0
              10, -10, 10, 0
         
  2. Look up functions (what is chomp, push, split), operators (what is “x”), and control constructs (is the “if” a proper statement or a statement modifier?) in the reference.
  3. Where does this Perl script use the default variable $_?
  4. What does @$row return, and why? (This might be one of those cases where you need to ask a Perl-guru if you can't figure it out yourself.)


Next: , Previous: hw03-3, Up: hw03-programming

hw03-4 Average column (Perl)

(8 points) Extend the script from problem hw03-3 so it computes the average of each column, and prints it as an added row at the bottom of the output. For example, given this input:

     3, 4, 3
     0, 0, 0
     4, 5, 2.5
     2, -1, 4

your script should print this output:

        3  4     3
        0  0     0
        4  5   2.5
        2 -1     4
     2.25  2 2.375

For example, the average of column 3,0,4,2 is 2.25.


Previous: hw03-4, Up: hw03-programming

hw03-5 Euclidian distance (Perl)

(8 points) Extend the script from problem hw03-3 so it computes the Euclidian distance of each row to the first row, and prints it as an added column at the right of the output. For example, given this input:

     3, 4, 3
     0, 0, 0
     4, 5, 2.5
     2, -1, 4

your script should print this output:

     3  4   3                0
     0  0   0  5.8309518948453
     4  5 2.5              1.5
     2 -1   4 5.19615242270663

For example, the first row has zero distance from itself. The second row has Euclidian distance 5.8309518948453 from the first row.


Next: , Previous: hw03-programming, Up: Problems

Reading assignments

Read for lecture on 6/19:
W3Schools PHP Tutorial. Read the part “PHP Basics”, which should start with “PHP Intro” and end with “PHP $_POST”. Available online at http://www.w3schools.com/php/. If you don't yet know HTML, read the tutorial for HTML first, at http://www.w3schools.com/html/.


Next: , Previous: hw04-readings, Up: Problems

Concept questions


Next: , Up: hw04-concepts

hw04-1 Weak, strong, static, and dynamic typing

(5+5 = 10 points)

  1. Dynamic typing is not the same as weak typing. Explain the difference.
  2. Look at the picture categorizing language type systems along two axes in the 6/12/2008 lecture slides. Is VBA placed correctly in that picture? Explain.


Previous: hw04-1, Up: hw04-concepts

hw04-2 Context in Perl

(4+4+4 = 12 points)

  1. Consider the following Perl function.
              sub isprime {
                my ($num, $f, @factors) = ($_[0], 2);
                while (1 != $num) {
                  if (0 == $num % $f) {
                    return $f == $num unless wantarray;
                    push @factors, $f;
                    $num /= $f;
                  } else {
                    $f++;
                  }
                }
                return @factors;
              }
         

    Give four examples for calling this function: with a prime or a non-prime, in a list context or a scalar context.

  2. Consider the following Perl function.
              sub map_block (&@) {
                my ($block, @listin) = @_;
                my @listout = ();
                push @listout, &$block() for (@listin);
                return @listout;
              }
         

    Explain where and how this function uses the default variable $_.

  3. Show how to use function map_block above to add 5 to every element of a list. For example, your code should turn the list 1,2,3 into the list 6,7,8.


Next: , Previous: hw04-concepts, Up: Problems

Programming exercises


Next: , Up: hw04-programming

hw04-3 Bidirectional mapping (Perl)

(10 + 4 = 14 points)

  1. Use the object-oriented features of Perl to implement a class TwoWayMap. An instance of this class should behave like an associative array that maps keys to values, but should also work in the reverse direction, mapping values back to keys. For example, the following code:
              use TwoWayMap;
              our $e2g = new TwoWayMap;
              $e2g->put('apple', 'Apfel');
              $e2g->put('pear', 'Birne');
              print $e2g->get('apple'), "\n";
              print $e2g->rev('Apfel'), "\n";
              print $e2g->rev('Birne'), "\n";
         

    should print Apfel, apple, pear. You can assume that all keys and values are strings.

  2. Improve the constructor of your class TwoWayMap so that it also accepts an initialization list. For example, the following code:
              use TwoWayMap;
              our $e2g = new TwoWayMap 'grape' => 'Traube', 'onion' => 'Zwiebel';
              print $e2g->get('grape'), "\n";
              print $e2g->rev('Traube'), "\n";
              print $e2g->rev('Zwiebel'), "\n";
         

    should print Traube, grape, onion.


Previous: hw04-3, Up: hw04-programming

hw04-4 Hierarchical clustering (Perl)

(14 points) Write a Perl script that reads a table and writes a dendrogram specification. Consider this example input:

     A, 4, 0
     B, 8, 5
     C, 4, 4

There are three rows. Hierarchical clustering starts by putting each row in a cluster by itself. Then, it finds the two clusters with the smallest Euclidian distance. The distance between clusters A and C is sqrt((4-4)**2+(4-0)**2)=4, and these two clusters are closest to each other. Hierarchical clustering combines them to obtain a partial dendrogram specification (A:4:C). The combined cluster (A:4:C) has two rows and the arithetic mean [(4+4)/2, (0+4)/2] = [4, 2]. Thus, the current set of clusters is:

     (A:4:C) => 2 x [4, 2]
           B => 1 x [8, 5]

Now, hierarchical clustering repeats the same step. There are only two clusters left, so those are automatically the two clusters with the smallest Euclidian distance. The distance between the two remaining clusters is sqrt((8-4)**2+(5-2)**2)=5. Hierarchical clustering combines them as before, using a weighted average. The set of clusters becomes:

     ((A:4:C):5:B) => 3 x [5.33, 3]

Since there is only one cluster left, hierarchical clustering terminates. Your Perl script should print the final dendrogram specification ((A:4:C):5:B) to standard output.

You can then copy-and-paste the output of your Perl script into the VBA dialog box you designed for hw02-4 to visualize the dendrogram as a tree. With appropriate scaling, this is what it looks like:

Here is the link to the example solution from hw02-4:

http://www.cs.nyu.edu/courses/summer08/G22.3033-002/solutions-hw02-4.ppt


Next: , Previous: hw04-programming, Up: Problems

Reading assignments

Read for lecture on 6/26:
W3Schools JavaScript Tutorial. Read the part “JavaScript Basics”, which should start with “JS Introduction” and end with “JS Guidelines”. Available online at http://www.w3schools.com/js/.


Next: , Previous: hw05-readings, Up: Problems

Concept questions


Next: , Up: hw05-concepts

hw05-1 Properties

(4+4+4 = 12 points) Consider the following PHP code.

     <?php
     class Vector {
       var $x = 0;
       var $y = 0;
       function __construct($x, $y) {
         $this->x = $x;
         $this->y = $y;
       }
       function __get($propName) {
         if ($propName == 'length')
           return sqrt($this->x * $this->x + $this->y * $this->y);
       }
       function __set($propName, $value) {
         if ($propName == 'length') {
           $oldLen = sqrt($this->x * $this->x + $this->y * $this->y);
           $this->x *= $value / $oldLen;
           $this->y *= $value / $oldLen;
         }
       }
     }
     $v = new Vector(2,3);
     printf("|%.2f, %.2f| = %.2f<br/>\n", $v->x, $v->y, $v->length);
     $v->length = 5;
     printf("|%.2f, %.2f| = %.2f<br/>\n", $v->x, $v->y, $v->length);
     ?>
  1. Run the script. What does it print?
  2. Are properties in PHP easier or harder to use than in VBA? Why?
  3. Are properties in PHP more or less expressive than in VBA? Why?


Previous: hw05-1, Up: hw05-concepts

hw05-2 Call-backs

(4+4+4 = 12 points) Consider the following PHP code.

     <?php
     class Vector {
       var $x = 0;
       var $y = 0;
       function __construct($x, $y) {
         $this->x = $x;
         $this->y = $y;
       }
       function length() {
         return sqrt($this->x * $this->x + $this->y * $this->y);
       }
     }
     
     $a = array(new Vector(0,4), new Vector(-3,4), new Vector(2,3));
     function cmp_vector($a, $b) {
       $aa = $a->length(); $bb = $b->length();
       return $aa < $bb ? -1 : $aa == $bb ? 0 : 1;
     }
     usort($a, "cmp_vector");
     foreach ($a as $i => $v)
       printf("%2d => (%d, %d)<br/>\n", $i, $v->x, $v->y);
     ?>
  1. Run the script. What does it print?
  2. Explain where and how the code uses call-backs.
  3. What would you need to change to sort by x-coordinates instead of by length?


Next: , Previous: hw05-concepts, Up: Problems

Programming exercises


Next: , Up: hw05-programming

hw05-3 Installing script on server (PHP)

(5+5+5 = 15 points)

  1. Follow the instructions from the lecture slides to create an HTML page that can be viewed from any web browser using the following URL:

    http://www.cs.nyu.edu/~your_cims_id/hw05-3a.html

    For example, if your_cims_id is hirzel, then the URL would be:

    http://www.cs.nyu.edu/~hirzel/hw05-3a.html

  2. Use a .htaccess file to create a password protected HTML page that can be viewed from any web browser using the following URL:

    http://www.cs.nyu.edu/~your_cims_id/php/hw05-3b.html

    For example, with your_cims_id as hirzel, you get the following URL, which requires you to enter the user name student and the password P_8sh_P:

    http://www.cs.nyu.edu/~hirzel/php/hw05-3b.html

    Please create a user name grader. Please indicate the URL and the password for grader in your submission, so that Robert Soulé can access your web page.

  3. In the same directory that you secured using a .htaccess file, create a PHP script hw05-3c.php with the following code:
              <html><body>
              <?php
                if(!empty($_GET['who'])) { echo "Hi, {$_GET['who']}.";}
              ?>
              <form action="<?php echo $_SERVER[PHP_SELF]; ?>" method=get>
                Who shall be greeted: <input type="text" name="who" />
              </form>
              </body></html>
         

    (See also http://www.cs.nyu.edu/~hirzel/php/hw05-3c.phps). Test it and make sure it works. For example, for your_cims_id hirzel, user name student, and password P_8sh_P, this URL runs the script for you:

    http://www.cs.nyu.edu/~hirzel/php/hw05-3c.php


Previous: hw05-3, Up: hw05-programming

hw05-4 Cooking conversions (PHP)

(11 points) Write a PHP script that converts cooking quantities, units, and ingredients to metric units. For data input, use a form that provides three text fields, one each for Quantity, Unit, and Ingredient. When the user enters values for all three and clicks the submit button, your script should print the converted result at the top of the web page. Your script should be a self-processing page, in other words, use the same page for input and output. For example, if the user enters the values 3, cup, and flour in the three input fields and clicks the Submit button, your script should return a page that looks like this:

Your PHP script should offer the same kinds of conversions as the Perl example from the lecture slides. Please copy-and-paste the source code of your script into your homework submission. In addition, please put the script online at the following URL (replacing your_cims_id by your CIMS id):

http://www.cs.nyu.edu/~your_cims_id/php/hw05-4.php


Next: , Previous: hw05-programming, Up: Problems

Quiz 2 problems.


Next: , Up: quiz2-problems

quiz2-1 Regular expressions

(3+3+4 = 10 points) Consider the following Perl regular expression:

     ^[0-9]+(\.[0-9]*)?$
  1. Give two examples of strings matched by the regular expression.
  2. Give two examples of strings for which the regular expression does not match.
  3. Change the regular expression so that it can only start with a 0 if that 0 is the entire part before the decimal point. For example, the string "0.99" should still match, but the string "001.23" should not match.


Next: , Previous: quiz2-1, Up: quiz2-problems

quiz2-2 Server-side scripting

(3+3+4 = 10 points)

  1. Where does the input for a PHP script come from?
  2. Where does the output of a PHP script go to?
  3. What is a self-processing page?


Previous: quiz2-2, Up: quiz2-problems

quiz2-3 Context

(4+2+2+2 = 10 points) Consider the following Perl code:

     @x = (7, 8, 9);
     $y = (7, 8, 9);
     print @x + 0;
     for $i (@x) { print $i }
     for $i ($y) { print $i }
  1. What does the code print?
  2. What is the implicit conversion for using a list literal in a scalar context in Perl?
    How does the above example illustrate this?
  3. What is the implicit conversion for using an array in a scalar context in Perl?
    How does the above example illustrate this?
  4. What is the implicit conversion for using a scalar in a list context in Perl?
    How does the above example illustrate this?


Next: , Previous: quiz2-problems, Up: Problems

Reading assignments

Read for lecture on 7/3:
Jesse James Garrett. Ajax: A New Approach to Web Applications. Essay and FAQ published on the website of Adaptive Path, February 18, 2005. Available at http://www.adaptivepath.com/ideas/essays/archives/000385.php.


Next: , Previous: hw06-readings, Up: Problems

Concept questions


Next: , Up: hw06-concepts

hw06-1 Closures

(2+4+4+4 = 14 points) Consider the following HTML document with JavaScript.

     <html><head>
       <meta http-equiv="Content-Script-Type" content="text/javascript" />
       <script>
         function curry(f, x) {
           return function(y) {
             return f(x, y);
           }
         }
       </script>
     </head><body>
       <h1><a href="http://en.wikipedia.org/wiki/Currying">Currying</a></h1>
       <script>
         function add(x,y){ return x + y; }
         var inc = curry(add, 1);
         var double = curry(function(x,y){ return x * y; }, 2);
         document.write(inc(5) + "<br/>\n");
         document.write(double(5) + "<br/>\n");
       </script>
     </body></html>
  1. Predict what the code should print. Then run it. What does it print?
  2. A closure is a function plus an environment. For closure inc, what is the function, and what is the environment? And in the environment, what is f bound to, and what is x bound to?
  3. For closure double, what is the function, and what is the environment? And in the environment, what is f bound to, and what is x bound to?
  4. Show how to use function curry to create a closure for squaring a number. For example, square(5) should return 25.


Previous: hw06-1, Up: hw06-concepts

hw06-2 Prototypes

(2+4+4 = 10 points) Consider the following HTML document with JavaScript.

     <html><head>
       <meta http-equiv="Content-Script-Type" content="text/javascript" />
       <script>
         function C() { }
         C.prototype.f = function() { return 'Cf'; }
         C.prototype.g = function() { return 'Cg'; }
         C.prototype.h = function() { return 'Ch'; }
         function D() { }
         D.prototype = new C();
         D.prototype.constructor = D;
         D.prototype.g = function() { return 'Dg'; }
         function E() { }
         E.prototype = new D();
         E.prototype.constructor = E;
         E.prototype.h = function() { return 'Eh'; }
       </script>
     </head><body>
       <script>
         var x = new D();
         document.write(x.f() + ', ' + x.g() + ', ' + x.h() + "\n<br/>");
         var y = new E();
         document.write(y.f() + ', ' + y.g() + ', ' + y.h() + "\n<br/>");
       </script>
     </body></html>
  1. Predict what the code should print. Then run it. What does it print?
  2. What is the chain of prototypes of object x?
  3. What is the chain of prototypes of object y?


Next: , Previous: hw06-concepts, Up: Problems

Programming exercises


Next: , Up: hw06-programming

hw06-3 Temperature conversions (JavaScript)

(12 points) Write an HTML document with a form that has two text input fields and two buttons. When the user enters a value in the “Celsius” field and presses the “To Fahrenheit” button, that should trigger a JavaScript event handler that shows the converted temperature in the “Fahrenheit” input field. Likewise, when the user enters a value in the “Fahrenheit” field and presses the “To Celsius” button, that should trigger a JavaScript event handler that shows the converted temperature in the “Celsius” input field. Below is an example screen shot. Remember to test your code in both the Mozilla Firefox and the Microsoft Internet Explorer web browsers.


Previous: hw06-3, Up: hw06-programming

hw06-4 Priority queue (JavaScript)

(14 points) Write a constructor PriorityQueue that creates an object that supports three methods: push, pop, and peek. A priority queue allows elements to be added in any order, but always returns the smallest element. The push method adds an element to the queue. The pop method removes and returns the smallest element in the queue. The peek method also returns the smallest element in the queue, but does not remove it. If you put your code in a file called PriorityQueue.js, then you can test it with the following driver:

     <html><head>
       <meta http-equiv="Content-Script-Type" content="text/javascript" />
       <script src="PriorityQueue.js"></script>
       <script>
         var q = new PriorityQueue();
         function doPush() {
           var val = document.driver.push.value;
           q.push(val);
           var log = document.getElementById("log");
           log.innerHTML += "push(" + val + ")\n<br/>";
         }
         function doPop() {
           var val = q.pop();
           var log = document.getElementById("log");
           log.innerHTML += "pop() -&gt; " + val + "\n<br/>";
         }
         function doPeek() {
           var val = q.peek();
           var log = document.getElementById("log");
           log.innerHTML += "peek() -&gt; " + val + "\n<br/>";
         }
       </script>
     </head><body>
       <form name="driver">
         <input type="text" name="push">
         <input type="button" value="Push" onclick="doPush();">
         <br/>
         <td><input type="button" value="Pop" onclick="doPop();">
         <br/>
         <td><input type="button" value="Peek" onclick="doPeek();">
       </form>
       <span id="log"></span>
     </body></html>

The following screen snapshot demonstrates the behavior of a priority queue through a sequence of calls.


Next: , Previous: hw06-programming, Up: Problems

Reading assignments

Read for lecture on 7/10:


Next: , Previous: hw07-readings, Up: Problems

Concept questions


Up: hw07-concepts

hw07-1 Google Suggest

(6+6 = 12 points) Try the Google Suggest web application, which is available at http://www.google.com/webhp?complete=1&hl=eN. Now think about what you would need to do to write a similar web application yourself.

  1. Briefly explain how would you use AJAX.
  2. Briefly explain where, and in what scope, you would store state.


Next: , Previous: hw07-concepts, Up: Problems

Programming exercises


Next: , Up: hw07-programming

hw07-2 Natural language translation (PHP + SQL)

(6+6+6 = 18 points) Consider the following PHP script.

     <html><head>
       <title>Translation Database</title>
     </head><body>
       <!-- show form for user input -->
       <form action="<?php echo $_SERVER[PHP_SELF]; ?>" method=get>
         <table border=0>
           <tr><td>English:    <td><input type="text" name="eng"><br/>
           <tr><td>Translated: <td><input type="text" name="tra"><br/>
         </table>
         <input type="radio" name="request" value="add">
           Add</br>
         <input type="radio" name="request" value="e2f">
           Get (English to Translated)</br>
         <input type="radio" name="request" value="f2e">
           Get (Translated to English)</br>
         <input type="radio" name="request" value="del">
           Delete</br>
         <input type="submit" value="submit">
       </form>
       <!-- open database, and create table if it does not yet exist -->
       <?php
         $db = sqlite_open("/home/hirzel/data/sqlite2", 0666, $err);
         if ($err) { die($err); }
         sqlite_query($db, "SELECT * FROM Translate", SQLITE_BOTH, $err);
         if ($err) {
           echo "Table 'Translate' does not yet exist, creating it ...<br/>";
           $q = "CREATE TABLE Translate"
              . "(English VARCHAR(50), Translated VARCHAR(50))";
           sqlite_query($db, $q, SQLITE_BOTH, $err);
           if ($err) { die($err); }
         } else {
           echo "Reopened table 'Translate'.<br/>";
         }
       ?>
       <!-- process input, if any -->
       <?php
         if ("add" == $_GET[request]) {
           $q = "INSERT INTO Translate VALUES("
              . "'" . addslashes($_GET[eng]) . "', "
              . "'" . addslashes($_GET[tra]) . "')";
           sqlite_query($db, $q);
           if ($err) { die($err); }
           echo "Add English '" . htmlentities($_GET[eng]) . "', " .
                "Translated '" . htmlentities($_GET[tra]) . "' succeeded.";
         } else if ("e2f" == $_GET['request']) {
           $q = "SELECT Translated FROM Translate WHERE English = "
              . "'" . addslashes($_GET[eng]) . "'";
           $rows = sqlite_query($db, $q);
           if ($err) { die($err); }
           $row = sqlite_fetch_array($rows, SQLITE_BOTH);
           if ($err) { die($err); }
           echo "Get English '" . htmlentities($_GET[eng]) . "' returned "
                . "Translated '" . htmlentities($row[Translated]) . "'.";
         } else if ("f2e" == $_GET['request']) {
           # put your code here
           echo "Sorry, lookup from Translated to English not yet implemented.";
         } else if ("del" == $_GET['request']) {
           # put your code here
           echo "Sorry, deletion not yet implemented.";
         }
       ?>
     </body>
  1. Set up the script to work in your own public_html directory at NYU. You will need to create your own data directory, for example, like this:
              cd ~
              mkdir data
              chmod 777 data
         

    The file permissions must enable the web server to read and write your data directory. You will also need to change the line

              $db = sqlite_open("/home/hirzel/data/sqlite2", 0666, $err);
         

    to use your own directory. When you submit this homework, please indicate the URL at which the script is running.

  2. Implement the missing reverse translation feature (lookup from Translated to English).
  3. Implement the missing deletion feature.


Next: , Previous: hw07-2, Up: hw07-programming

hw07-3 Session visit counter (PHP)

(8 points) Write a PHP script that uses a session variable to count how often the user has visited it. For example, after the second visit, the page should look like this:


Previous: hw07-3, Up: hw07-programming

hw07-4 Word reversal AJAX (JavaScript + PHP)

(6 + 6 = 12 points) Consider the AJAX application from the lecture slides from 7/3/2008, repeated here for your convenience.

a.html

     <html><head>
       <meta http-equiv="Content-Script-Type" content="text/javascript" />
       <script src="c.js"></script>
     </head><body bgColor="#00ff00">
       Time: <span id="time">(please click button)</span>
       <form name="in">
         <input type="button" value="Toggle Color" onclick="localChange();">
         <input type="button" value="Request Time" onclick="sendRequest();">
       </form>
     </body></html>

b.php

     <?php sleep(3); echo date('h:i:s') ?>

c.js

     function localChange() {
       var blue = document.bgColor == '#0000ff'
       document.bgColor = blue ? '#00ff00' : '#0000ff';
     }
     function sendRequest() {
       document.getElementById('time').innerHTML = '(please wait)';
       var xhr = false;
       function handleResponse() {
         if (4 == xhr.readyState && 200 == xhr.status)
           document.getElementById('time').innerHTML = xhr.responseText;
       }
       try { xhr = new XMLHttpRequest(); } catch(e1) {
         try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e2) {
           try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e3) {
             alert('Could not create XMLHttpRequest object.'); } } }
       xhr.open('GET', 'b.php?nonce=' + Math.random(), true);
       xhr.onreadystatechange = handleResponse;
       xhr.send(null);
     }

Questions

  1. Install these scripts on your own CIMS web page. When you submit this homework, please indicate the URL at which the script is running.
  2. Change the application so that instead of just getting the time from the server, it reads a string from the user, sends it to the server in an AJAX call, the server reverses it, and the response handler displays it. Make sure to test your application on both Firefox and Internet Explorer. Below is a snapshot of what your application should look like.


Next: , Previous: hw07-programming, Up: Problems

Quiz 3 problems.


Next: , Up: quiz3-problems

quiz3-1 Closures

(4+3+3 = 10 points) Consider the following JavaScript code:

     var a = 1;
     function outer(b) {
       function inner() {
         document.write("a=" + a + ", b=" + b + "</br>\n");
       }
       return inner;
     }
     var my_closure = outer(2);
     my_closure();
     a = 3;
     my_closure();
  1. What does the code print?
  2. What is the function of closure my_closure?
  3. What is the environment of closure my_closure?


Next: , Previous: quiz3-1, Up: quiz3-problems

quiz3-2 AJAX

(2+5+3 = 10 points) Consider a web email application that lets the user create an attachment. After the user selects the file to attach, the application uploads it to the server in the background. At the same time, the user can interact normally with the application. When the file is uploaded, the page changes so the user knows the file is at the server.

  1. What do the letters A, J, A, X stand for in the acronym AJAX?
  2. Draw an interaction diagram that illustrates how the web email application uses AJAX. Your diagram should start as follows:

  3. What is the advantage of using AJAX for this application?


Previous: quiz3-2, Up: quiz3-problems

quiz3-3 Security

(4+3+3 = 10 points)

  1. What is a SQL injection vulnerability in a server-side script?
  2. Give an example for a bad thing that could happen due to a SQL injection attack.
  3. How can you prevent SQL injection attacks on your applications?


Next: , Previous: quiz3-problems, Up: Problems

Reading assignments

Read for lecture on 7/17:
Andreas Zeller. From Automated Testing to Automated Debugging. 2000. Available at http://www.infosun.fim.uni-passau.de/st/papers/computer2000


Next: , Previous: hw09-readings, Up: Problems

Concept questions


Up: hw09-concepts

hw09-1 Scientific Method

(3+12 = 15 points) Consider the following buggy Perl script:

     #!/usr/bin/perl                                               # 1
     use strict; use warnings;                                     # 2
                                                                   # 3
     sub compute_avg {                                             # 4
       my @sums;                                                   # 5
       my $nrows = $#_;                                            # 6
       for (my $i=0; $i<$nrows; $i++) {                            # 7
         my $row = $_[$i];                                         # 8
         for (my $j = 0; $j < @$row; $j++) {                       # 9
           $sums[$j] += $row->[$j];                                #10
         }                                                         #11
       }                                                           #12
       my @result;                                                 #13
       for (my $i = 0; $i < @sums; $i++) {                         #14
         $result[$i] = $sums[$i] / $nrows;                         #15
       }                                                           #16
       return @result;                                             #17
     }                                                             #18
                                                                   #19
     sub to_string {                                               #20
       my $result = "";                                            #21
       for my $row (@_) {                                          #22
         $result .= " " . $_ for (@$row);                          #23
         $result .= "\n";                                          #24
       }                                                           #25
       return $result;                                             #26
     }                                                             #27
                                                                   #28
     our @input = ([2, 1, 3], [0, 1, 1], [4, 1, 2]);               #29
     print "initial input:\n" . to_string @input;                  #30
     our @expected = ([2, 1, 3], [0, 1, 1], [4, 1, 2], [2, 1, 2]); #31
     print "expected output:\n" . to_string @expected;             #32
     our @avg = compute_avg @input;                                #33
     our @output = @input;                                         #34
     push @output, [ @avg ];                                       #35
     print "actual output:\n" . to_string @output;                 #36
  1. Run the script. What does it print?
  2. Debug the script using the scientific method. Your answer should be a debugging log book, similar to the example in the lecture slides. The format should be similar to this:
              1 Hypothesis  (e.g., variable has wrong value in given line)
                Experiment  (e.g., run debugger, set breakpoint, inspect value)
                Observation (e.g., the value of the variable at that place)
                Conclusion  (e.g., hypothesis verified, falsified, inconclusive)
              2 Hypothesis  ...
                Experiment  ...
                Observation ...
                Conclusion  ...
              3 ...
              ...
         


Next: , Previous: hw09-concepts, Up: Problems

Programming exercises


Up: hw09-programming

hw09-2 Delta Debugging

(0 points) When you learn a new language, a good way to make progress is by solving some moderately difficult programming problems. At the same time, when you learn a new algorithm, a good way to understand and remember it is by implementing it. Therefore, I suggest you combine the two by using one of the new languages you learned in prior lectures to implement one of the debugging algorithms you learned in the most recent lecture.


Next: , Previous: hw09-programming, Up: Problems

Concept questions


Next: , Up: hw10-concepts

hw10-1 Iterating with Coroutines

(4+6 = 10 points) Consider the following Python script.

     #!/usr/bin/env python
     class Tree:
         def __init__(self, value, left=None, right=None):
             self.value = value
             self.left = left
             self.right = right
         def preorder(self):
             yield self.value
             if self.left:
                 for v in self.left.preorder():
                     yield v
             if self.right:
                 for v in self.right.preorder():
                     yield v
     
     my_tree = Tree(1,
                 Tree(2,Tree(4),Tree(5)),
                 Tree(3,Tree(6),Tree(7)))
     
     def print_preorder(tree):
         print 'preorder:'
         for y in my_tree.preorder():
             print y
     
     print_preorder(my_tree)
  1. Predict what the code should print. Then run it. What does it print?
  2. Add another generator method Tree.inorder that walks the tree in-order instead of pre-order. An in-order walk first visits all nodes in the left subtree, then the current node, then all nodes in the right subtree. The following picture shows a tree for which an in-order walk would visit nodes in alphabetical order:
                   d
                 /   \
                b     f
               / \   / \
              a   c e   g
         

    After you write the generator Tree.inorder, the following code:

              def print_inorder(tree):
                  print 'inorder:'
                  for y in my_tree.inorder():
                      print y
              
              print_inorder(my_tree)
         

    should cause the following output to be printed:

              inorder:
              4
              2
              5
              1
              6
              3
              7
         


Next: , Previous: hw10-1, Up: hw10-concepts

hw10-2 Iterating with Block Parameters

(4+6 = 10 points) Consider the following Ruby script.

     #!/usr/bin/env ruby
     class Tree
       attr_accessor :value, :left, :right
       def initialize(value, *leftRight)
         @value = value
         if 0 < leftRight.length()
           @left = leftRight[0]
           @right = leftRight[1]
         end
       end
       def preorder()
         yield @value
         if @left
           @left.preorder {|v| yield v }
         end
         if @right
           @right.preorder {|v| yield v }
         end
       end
     end
     
     $my_tree = Tree.new(1,
                  Tree.new(2, Tree.new(4), Tree.new(5)),
                  Tree.new(3, Tree.new(6), Tree.new(7)))
     
     def print_preorder(tree)
       puts 'preorder:'
       tree.preorder {|y| puts y.to_s + "\n" }
     end
     
     print_preorder($my_tree)
  1. Predict what the code should print. Then run it. What does it print?
  2. Add another top-level function print_sum that uses the iterator to compute the sum of all values in the tree. For example, the following call:
              print_sum($my_tree)
         

    should cause the following output to be printed:

              sum:
              28
         


Previous: hw10-2, Up: hw10-concepts

hw10-3 Coroutines vs. Block Parameters

(7+4+4=15 points)


     
  1. Briefly explain the difference between coroutines and block parameters.
  2. Give an advantage of coroutines compared to block parameters.
  3. Give an advantage of block parameters compared to coroutines.


Next: , Previous: hw10-concepts, Up: Problems

Programming exercises


Up: hw10-programming

hw10-4 Iterating with Closure Parameters (PHP)

(15 points) Consider the following skeleton PHP script:

     #!/usr/bin/env php
     <?php
     class Tree {
       # --- add your code here ---
     }
     
     $myTree = new Tree(1,
                      new Tree(2, new Tree(4), new Tree(5)),
                      new Tree(3, new Tree(6), new Tree(7)));
     
     function printPreorder($tree) {
       echo "preorder:\n";
       $tree->preorder(create_function('$v', 'echo "$v\n";'));
     }
     
     printPreorder($myTree);
     ?>

Implement the body of class Tree so that the construction (new Tree(...)) and iteration ($tree->preorder(...)) at the bottom of the script work, and produce the same output as the equivalent Python and Ruby scripts above.


Previous: hw10-programming, Up: Problems

Final exam problems.


Next: , Up: final-problems

final-1 BNF and regular expressions

(3+3+4 = 10 points) Consider the following BNF grammar rules:

identifier ::= id_start | id_start id_rest
id_rest ::= id_inner | id_inner id_rest
id_start ::= _ | letter
id_inner ::= _ | letter | digit
letter ::= A | B | ... | Z | a | b | ... | z
digit ::= 0 | 1 | ... | 9

  1. Give two examples of strings matched by the nonterminal identifier.
  2. Give two examples of strings for which the nonterminal identifier does not match.
  3. Write a Perl regular expression that matches the same strings as the nonterminal identifier in the BNF grammar.


Next: , Previous: final-1, Up: final-problems

final-2 Web programming

(2+2+2+2+2 = 10 points) Please keep your answers to the following questions short.

  1. How does PHP code read user input?
  2. How does JavaScript code read user input?
  3. Where does the output from an echo statement in PHP go?
  4. Where does the output from a document.write() call in JavaScript go?
  5. How can PHP store information on the hard drive of the client?


Next: , Previous: final-2, Up: final-problems

final-3 Type conversions

(5+5 = 10 points)

  1. Consider the Perl code snippet "pe" . ("a", "rl").
    3-a(1)
    What is the context provider for subexpression ("a", "rl")?
    3-a(2)
    What is the type conversion context for subexpression ("a", "rl")?
    3-a(3)
    What is the value of subexpression ("a", "rl") after type conversion, but before the converted value gets used?
    3-a(4)
    What is the end result of the entire code snippet "pe" . ("a", "rl")?
  2. Consider the Perl code snippet sqrt @a, assuming array @a has the value (1,9,4,9).
    3-b(1)
    What is the context provider for subexpression @a?
    3-b(2)
    What is the type conversion context for subexpression @a?
    3-b(3)
    What is the value of subexpression @a after type conversion, but before the converted value gets used?
    3-b(4)
    What is the end result of the entire code snippet sqrt @a?


Next: , Previous: final-3, Up: final-problems

final-4 List comprehensions

(4+6 = 10 points) Consider the following Python code.

     numbers = [1, 2]
     extensions = ["html", "pdf"]
     quizzes = [("quiz%d.%s" % (n, e)) for n in numbers for e in extensions]
  1. What is the value of variable quizzes at the end of the code snippet?
  2. The first two lines of the Python code translate to Perl as follows:
              @numbers = (1, 2);
              @extensions = ("html", "pdf");
         

    Translate the third line of the Python code to Perl.


Next: , Previous: final-4, Up: final-problems

final-5 Web application security

(3+3+4 = 10 points) Consider the following PHP script editor_poll.php.

     <html><body>
       <?php if (empty($_GET['editor'])) { ?>
         <form action="editor_poll.php">
           <input type="radio" name="editor" value="emacs"   /> Emacs
           <input type="radio" name="editor" value="notepad" /> Notepad
           <input type="radio" name="editor" value="vi"      /> Vi
           <input type="radio" name="editor" value="other"   /> Other
           <br />
           <input type="submit" value="submit" />
         </form>
       <?php } else { ?>
         You selected: <?php echo $_GET['editor'] ?>
       <?php } ?>
     </body></html>
  1. What security vulnerability does the script have?
  2. How could an attacker exploit the security vulnerability?
  3. How can you change the code to prevent the vulnerability?


Previous: final-5, Up: final-problems

final-6 Prototypes and constructors

(2+2+2+4 = 10 points) Consider the following JavaScript code.

     function Vector(x, y) { this.x = x; this.y = y; }
     Vector.prototype.length = function() {
       q = this.x * this.x + this.y * this.y;
       return Math.sqrt(q);
     }
     v = new Vector(3, 4);
     document.write(v.length());
  1. What does it print?
  2. What is the constructor of the object v?
  3. What is the prototype of the object v?
  4. Explain in detail what the operator new in JavaScript does.


Previous: Problems, Up: Top

Scripting Languages G22.3033-002 Summer 2008 All example solutions


Next: , Up: Solutions

Example solutions for Homework 1


Next: , Up: Solutions-hw01

solutions-hw01-1 Dynamic typing

  1.           Sub PrintArray(Arr() As String)
                Debug.Print "PrintArray:"
                For I% = 0 To UBound(Arr)
                  Debug.Print "  " & I & " " & Arr(I)
                Next I
              End Sub
              Sub Main()
                Dim fruits(2) As String
                fruits(0) = "apple"
                PrintArray fruits
                fruits(1) = "orange"
                fruits(2) = "banana"
                PrintArray fruits
              End Sub
         


Next: , Previous: solutions-hw01-1, Up: Solutions-hw01

solutions-hw01-2 Precedence and associativity

  1. 2 - (2 - 2 - 2 * 2)


Next: , Previous: solutions-hw01-2, Up: Solutions-hw01

solutions-hw01-3 Euclidian distance (VBA)

     Function EuclidDistance(A() As Double, B() As Double) As Double
       EuclidDistance = 0
       Dim I As Integer
       For I = LBound(A) To UBound(A)
         EuclidDistance = EuclidDistance + (A(I) - B(I)) ^ 2
       Next I
       EuclidDistance = EuclidDistance ^ 0.5
     End Function


Previous: solutions-hw01-3, Up: Solutions-hw01

solutions-hw01-4 Average rows (VBA)

     Sub AverageRows(Result() As Double, Rows() As Double)
       Dim I As Integer, J As Integer
       For I = LBound(Rows, 1) To UBound(Rows, 1)
         Result(I) = 0
         For J = LBound(Rows, 2) To UBound(Rows, 2)
           Result(I) = Result(I) + Rows(I, J)
         Next J
         Result(I) = Result(I) / (1 + UBound(Rows, 2) - LBound(Rows, 2))
       Next I
     End Sub


Next: , Previous: Solutions-hw01, Up: Solutions

Example solutions for Homework 2


Next: , Up: Solutions-hw02

solutions-hw02-1 Properties

  1. There are two properties: Celsius, which is defined like a variable, and Fahrenheit, which is defined by two property methods Let and Get. The following code reads and writes both:
              Dim t As Temperature
              Set t = New Temperature
              t.Celsius = 25
              Debug.Print t.Celsius & " C = " & t.Fahrenheit & " F"
              t.Fahrenheit = 25
              Debug.Print t.Celsius & " C = " & t.Fahrenheit & " F"
         

    These properties encapsulate a temperature value, which is stored internally as Celsius, but can be accessed as both Celsius and Fahrenheit. The user can not tell the difference between the two properties.

  2. To implement a write-once property, I would use a private variable for storing the actual value; a private boolean for keeping track of whether the actual value has already been written; and a pair of Get and Let methods for reading and writing the value, and checking that the value is written only once. For example:
              Private myPropValue
              Private myPropWritten As Boolean
              Sub Class_Initialize()
                myPropWritten = False
              End Sub
              Public Property Let myProp(val)
                If Not myPropWritten Then
                  myPropValue = val
                  myPropWritten = True
                End If
              End Property
              Public Property Get myProp()
                myProp = myPropValue
              End Property
         


Next: , Previous: solutions-hw02-1, Up: Solutions-hw02

solutions-hw02-2 Call-backs

  1. VBA supports call-backs by naming conventions. If a user form contains a control named myControl, then the VBA execution engine calls back to subroutine myControl_Click when the user clicks a button.
  2. The VBA designers could have implemented call-backs by passing an object on which the runtime system invokes a method. This is a common approach taken by other object-oriented languages such as Java.


Next: , Previous: solutions-hw02-2, Up: Solutions-hw02

solutions-hw02-3 Associative array (VBA)

     Option Explicit
     Implements StringMap
     
     Private used As Integer
     Private keys() As String
     Private values() As String
     
     Sub Class_Initialize()
       used = 0
       ReDim keys(2)
       ReDim values(2)
     End Sub
     
     Public Function StringMap_Size() As Integer
       StringMap_Size = used
     End Function
     
     Public Function StringMap_Contains(key As String) As Boolean
       Dim i As Integer
       For i = 0 To used - 1
         If keys(i) = key Then StringMap_Contains = True: Exit Function
       Next i
       StringMap_Contains = False
     End Function
     
     Public Property Let StringMap_Data(key As String, val As Variant)
       Dim i As Integer
       For i = 0 To used - 1
         If keys(i) = key Then values(i) = val: Exit Property
       Next i
       If UBound(keys) = used - 1 Then ReDim keys(2 * used)
       keys(i) = key
       values(i) = val
       used = used + 1
     End Property
     
     Public Property Get StringMap_Data(key As String)
       Dim i As Integer
       For i = 0 To used - 1
         If keys(i) = key Then StringMap_Data = values(i): Exit Property
       Next i
     End Property


Previous: solutions-hw02-3, Up: Solutions-hw02

solutions-hw02-4 Dendrogram (VBA)

You can find the full example solution in the following Powerpoint presentation:

http://www.cs.nyu.edu/courses/summer08/G22.3033-002/solutions-hw02-4.ppt

Here, we just describe the most important parts. The GUI is illustrated in the questions. The code sheet requires two event handlers, for the two buttons:

     Private Sub cmdDraw_Click()
       Dim cvs As Canvas
       Set cvs = New Canvas
       Const dpi As Double = 72
       cvs.xbase = dpi * CDbl(txtXbase.Value)
       cvs.xscale = dpi * CDbl(txtXscale.Value)
       cvs.ybase = dpi * CDbl(txtYbase.Value)
       cvs.yscale = dpi * CDbl(txtYscale.Value)
       Dim spec As String, x As Double, y As Double
       spec = txtSpec.Value: x = 0: y = 0
       DrawDendrogram cvs, spec, x, y
       End
     End Sub
     
     Private Sub UserForm_Click()
       End
     End Sub

The handler code assumes that you have renamed the different form elements appropriately. For example, the text box for the specification is called txtSpec. To do the renaming, right-click on a form element, select “properties” from the context menu, then edit the “(Name)” field. While you are there, you should also initialize the “Value” properties with reasonable defaults.


Next: , Previous: Solutions-hw02, Up: Solutions

Example solutions for Quiz 1


Next: , Up: Solutions-quiz1

solutions-quiz1-1 Gradual typing

     Function geometricMean(arr() As Double) As Double
       Dim i As Integer, n As Integer
       geometricMean = 1
       For i = LBound(arr) To UBound(arr)
         geometricMean = geometricMean * arr(i)
       Next i
       n = 1 + UBound(arr) - LBound(arr)
       geometricMean = geometricMean ^ (1.0 / n)
     End Function
     Sub main()
       Dim A(1) As Double
       A(0) = 1: A(1) = 2
       Debug.Print geometricMean(A)
     End Sub


Next: , Previous: solutions-quiz1-1, Up: Solutions-quiz1

solutions-quiz1-2 Precedence and associativity

$x = ($y = ((3 ** (3 ** 3)) * 2))


Previous: solutions-quiz1-2, Up: Solutions-quiz1

solutions-quiz1-3 Call-backs

  1. By name mangling conventions. When there is an event E on a user interface control C, then the VBA interpreter calls routine C_E in the form's code sheet.
  2. This rule is easy to understand, the programmer isn't likely to get confused about the interaction.
  3. Name mangling is brittle, because if the programmer changes the name of a control, they might forget to change the name of all associated call-backs.


Next: , Previous: Solutions-quiz1, Up: Solutions

Example solutions for Homework 3


Next: , Up: Solutions-hw03

solutions-hw03-1 Regular expressions

  1.           (|0x|0X)
              (a|b|c|d|e|f|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9)
              (a|b|c|d|e|f|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9)*
         
  2. ^\s*(?:\S+\s+){3}(\S+)\s+(\S+)


Next: , Previous: solutions-hw03-1, Up: Solutions-hw03

solutions-hw03-2 Static and dynamic scoping

  1. The program prints g f. Variable $a in Function g uses dynamic scoping. Therefore, it is visible in the callee function h: since g is the closest calling function, it hides variable $a from the nesting function f. The second print statement in function f, on the other hand, does not see $a from function g anymore, because it has already returned, and is not a calling function anymore, let alone the closest one.
  2. Consider this example:
              #!/usr/bin/perl -w
              sub g { $a = "g" }
              g();
              print $a, "\n";
              sub f { print $a, "\n" }
              f()
         

    This code prints g g. That means that the assignment $a = "g" implicitly declared a fresh global variable $a that is visible both at the top level and in another function f that is neither nested in nor called by function g.


Next: , Previous: solutions-hw03-2, Up: Solutions-hw03

solutions-hw03-3 CSV to fixed-width (Perl)

  1.                          0                 0 10 0
                            10                 0 10 0
                            10               -10 10 0
              6.66666666666667 -3.33333333333333 10 0
         
  2. (Look at the manual pages!)
  3. The while (<>) loop header reads lines from standard input to $_. The function chomp trims whitespace away from $_. The function split divides $_ up into comma-separated values to initialize an array reference to store in @rows.
  4. Variable $row holds a reference to an array, and @$row dereferences it to get the array. Since it gets used like a scalar, Perl interprets it as the length of the referred-to array.


Next: , Previous: solutions-hw03-3, Up: Solutions-hw03

solutions-hw03-4 Average column (Perl)

     #!/usr/bin/perl -w
     while (<>) {
       chomp;
       push @rows, [ split /,\s/ ];
     }
     #-------- added code for hw03-4 start --------
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         $sums[$i] += $row->[$i];
         $count[$i]++;
       }
     }
     for ($i = 0; $i < @sums; $i++) {
       $avg[$i] = $sums[$i] / $count[$i];
     }
     push @rows, [ @avg ];
     #-------- added code for hw03-4 end --------
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         $w = length $row->[$i];
         $widths[$i] = $w if !$widths[$i] || $w > $widths[$i];
       }
     }
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         print " " x (1 + $widths[$i] - length $row->[$i]);
         print $row->[$i];
       }
       print "\n";
     }


Previous: solutions-hw03-4, Up: Solutions-hw03

solutions-hw03-5 Euclidian distance (Perl)

     #!/usr/bin/perl -w
     while (<>) {
       chomp;
       push @rows, [ split /,\s/ ];
     }
     #-------- added code for hw03-5 start --------
     for ($r = 0; $r < @rows; $r++) {
       $delta = 0;
       for ($i = 0; $i < @{$rows[$r]}; $i++) {
         $delta += ($rows[$r]->[$i] - $rows[0]->[$i]) ** 2;
       }
       push @{$rows[$r]}, $delta ** .5;
     }
     #-------- added code for hw03-5 end --------
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         $w = length $row->[$i];
         $widths[$i] = $w if !$widths[$i] || $w > $widths[$i];
       }
     }
     for $row (@rows) {
       for ($i = 0; $i < @$row; $i++) {
         print " " x (1 + $widths[$i] - length $row->[$i]);
         print $row->[$i];
       }
       print "\n";
     }


Next: , Previous: Solutions-hw03, Up: Solutions

Example solutions for Homework 4


Next: , Up: Solutions-hw04

solutions-hw04-1 Weak, strong, static, and dynamic typing

  1. Weak typing means that there are many implicit type conversions. In other words, the same value will be interpreted differently depending on what type is expected. This increases flexibility, but may surprise the programmer and thus cause bugs.

    Dynamic typing means that most type checks occur at runtime rather than at compile time. This is not the same as weak typing, because the dynamic checks need not be weak. For instance, Scheme has strong dynamic typing: checks are deferred until runtime, but conversions have to be explicit in most cases.

  2. I put VBA half-way between static and dynamic typing, because it has gradual typing, allowing the programmer to choose how many checks happen at compile time and how many at runtime. I put VBA half-way between weak and strong typing because there are not as many implicit conversions as, for example, in Perl.


Next: , Previous: solutions-hw04-1, Up: Solutions-hw04

solutions-hw04-2 Context in Perl

  1.           print "12 ", (isprime 12) ? "is" : "is not", " a prime\n";
              print "prime factors of 12: ";
              for $f (isprime 12) { print "$f " }
              print "\n";
              print "13 ", (isprime 13) ? "is" : "is not", " a prime\n";
              print "prime factors of 13: ";
              for $f (isprime 13) { print "$f " }
         
  2. The line push @listout, &$block() for (@listin); makes heavy use of the default variable $_. The statement modifier for(@listin) iterates over the elements of @listin, putting each one in $_. Therefore, when the block gets called by &$block(), the variable $_ holds an array element. The code in the block can use this for computation.
  3.           @in = (1, 2, 3);
              my @out = map_block { $_ + 5 } @in;
              for (@out) { print $_, ' ' }
         


Next: , Previous: solutions-hw04-2, Up: Solutions-hw04

solutions-hw04-3 Bidirectional mapping (Perl)

     use strict; use warnings;
     package TwoWayMap;
     sub new {
       my ($cls, %init) = @_;
       my $self = bless( { MAP => {}, REV => {} }, $cls );
       for my $key (keys %init) {
         $self->put($key, $init{$key});
       }
       return $self;
     }
     sub put {
       my ($self, $key, $val) = @_;
       $self->{MAP}{$key} = $val;
       $self->{REV}{$val} = $key;
     }
     sub get {
       my ($self, $key) = @_;
       return $self->{MAP}{$key};
     }
     sub rev {
       my ($self, $val) = @_;
       return $self->{REV}{$val};
     }
     1


Previous: solutions-hw04-3, Up: Solutions-hw04

solutions-hw04-4 Hierarchical clustering (Perl)

     #!/usr/bin/perl
     use strict; use warnings;
     
     # hash, mapping from string to array reference
     #   key = cluster name, such as '(A:4:C)' or 'B'
     #   first array element = weight (number of clustered elements)
     #   remaining array elements = sum (of columns of all elements)
     our %clusters = ();
     
     sub sanity_print {
       print "{\n";
       for my $key (keys %clusters) {
         my $weight = $clusters{$key}->[0];
         printf "%20s => %d x [", $key, $weight;
         for (my $col = 1; $col < @{$clusters{$key}}; $col++) {
           print ", " unless $col == 1;
           print $clusters{$key}->[$col] / $weight;
         }
         print "]\n";
       }
       print "}\n";
     }
     
     while(<>) {
       chomp;
       my @row = split /\s*,\s*/;
       my $key = $row[0];
       $row[0] = 1; # weight 1 = cluster contains one row
       $clusters{$key} = [ @row ];
     }
     
     sub euclid_distance {
       my ($cluster1, $cluster2) = @_;
       my ($weight1, $weight2) = ($$cluster1[0], $$cluster2[0]);
       my $result = 0;
       for (my $i = 1; $i < @$cluster1; $i++) {
         my ($c1, $c2) = ($$cluster1[$i], $$cluster2[$i]);
         $result += ($c1 / $weight1 - $c2 / $weight2) ** 2.0;
       }
       $result **= 0.5;
       return $result;
     }
     
     sub find_closest_pair {
       my %cls = @_;
       my @keys = keys %cls;
       my ($res1, $res2) = ($keys[0], $keys[1]);
       my $min_dist = euclid_distance($cls{$res1}, $cls{$res2});
       for my $i (@keys) {
         for my $j (@keys) {
           if ($i ne $j) {
             my $dist = euclid_distance($cls{$i}, $cls{$j});
             if ($dist < $min_dist) {
               $res1 = $i;
               $res2 = $j;
               $min_dist = $dist;
             }
           }
         }
       }
       return ($min_dist, $res1, $res2);
     }
     
     sub combine_clusters {
       my ($cluster1, $cluster2) = @_;
       my @result = ();
       for (my $i = 0; $i < @$cluster1; $i++) {
         push @result, $$cluster1[$i] + $$cluster2[$i];
       }
       return [ @result ];
     }
     
     while (1 < scalar(keys %clusters)) {
       #sanity_print();  # uncomment this line to test/debug
       my ($dist, $k1, $k2) = find_closest_pair(%clusters);
       my $new_key = "($k1:$dist:$k2)";
       my $new_val = combine_clusters($clusters{$k1}, $clusters{$k2});
       delete $clusters{$k1};
       delete $clusters{$k2};
       $clusters{$new_key} = $new_val;
     }
     
     print keys %clusters, "\n";


Next: , Previous: Solutions-hw04, Up: Solutions

Example solutions for Homework 5


Next: , Up: Solutions-hw05

solutions-hw05-1 Properties

  1.           |2.00, 3.00| = 3.61
              |2.77, 4.16| = 5.00
         
  2. One could convincingly argue either way. Properties are easier to use in PHP than in VBA, because in PHP, they are just special methods, whereas in VBA, they require a whole separate syntax. Properties are harder to use in PHP than in VBA, because in PHP, you have to look at the nested if-statement in the special method, whereas in VBA, the property is an official part of the top-level signature of a class.
  3. Again, one could convincingly argue either way. Properties are more expressive in PHP than in VBA, because in PHP, they can have arbitrary names at runtime, whereas in in VBA, the set of names must be fixed at compile time. Properties are less expressive in PHP than in VBA, because in PHP, they always have a field-like look-and-feel, whereas in VBA, they can also have an array-like look-and-feel.


Next: , Previous: solutions-hw05-1, Up: Solutions-hw05

solutions-hw05-2 Call-backs

  1.           0 => (2, 3)<br/>
              1 => (0, 4)<br/>
              2 => (-3, 4)<br/>
         
  2. The code passes the string "cmp_vector" as a parameter to library function usort(). That way, the library function makes a call-back to function cmp_vector() whenever it needs to compare two vectors for sorting.
  3. Either change the body of function "cmp_vector", or write a new function, and pass a different string for the call-back. Here is an example for the second solution:
              function cmp_vector_by_x($a, $b) {
                $aa = $a->x; $bb = $b->x;
                return $aa < $bb ? -1 : $aa == $bb ? 0 : 1;
              }
              usort($a, "cmp_vector_by_x");
         


Next: , Previous: solutions-hw05-2, Up: Solutions-hw05

solutions-hw05-3 Installing script on server (PHP)

  1. http://www.cs.nyu.edu/~hirzel/hw05-3a.html

    No user name or password required.

  2. http://www.cs.nyu.edu/~hirzel/php/hw05-3b.html

    User name grader, password hype3.

  3. http://www.cs.nyu.edu/~hirzel/php/hw05-3c.php

    User name grader, password hype3.


Previous: solutions-hw05-3, Up: Solutions-hw05

solutions-hw05-4 Cooking conversions (PHP)

     <html>
     <head>
       <?php
         function convert($qty, $unit, $ing) {
           $cup2g = array('flour' => '110', 'sugar' => 225, 'butter' => 225);
           $volume = array('cup' => 1, 'tbsp' => 16, 'tsp' => 48, 'ml' => 236);
           $weight = array('lb' => 1, 'oz' => 16, 'g' => 453);
           if (array_key_exists($ing, $cup2g) && array_key_exists($unit, $volume)) {
             $qty = 1.0 * $qty * $cup2g[$ing] / $volume[$unit];
             $unit = 'g';
           } elseif (array_key_exists($unit, $volume)) {
             $qty = 1.0 * $qty * $volume[ml] / $volume[$unit];
             $unit = 'ml';
           } elseif (array_key_exists($unit, $weight)) {
             $qty = 1.0 * $qty * $weight[g] / $weight[$unit];
             $unit = 'g';
           }
           return ((int)($qty + .5)) . " $unit $ing";
         }
       ?>
     </head>
     <body>
       <?php if(!empty($_GET['qty'])) { ?>
       Converted result:
       <?php    echo convert($_GET['qty'], $_GET['unit'], $_GET['ing']); ?>
       <br/>
       <?php } ?>
       <form action="<?php echo $_SERVER[PHP_SELF]; ?>" method=get>
         <table border=1>
           <tr><td>Quantity
             <td><input type="text" name="qty"  value=<?php echo $_GET[qty] ?> />
           <tr><td>Unit
             <td><input type="text" name="unit" value=<?php echo $_GET[unit] ?> />
           <tr><td>Ingredient
             <td><input type="text" name="ing"  value=<?php echo $_GET[ing] ?> />
         </table>
         <input type="submit" value="Submit" />
       </form>
     </body>
     </html>


Next: , Previous: Solutions-hw05, Up: Solutions

Example solutions for Quiz 2


Next: , Up: Solutions-quiz2

solutions-quiz2-1 Regular expressions

  1. "3.141", "1000"
  2. "3.1a", "12.34.56"
  3. ^(0|[1-9][0-9]*)(\.[0-9]*)?$


Next: , Previous: solutions-quiz2-1, Up: Solutions-quiz2

solutions-quiz2-2 Server-side scripting

  1. The user enters input in an HTML form. When the form is submitted, the input turns into arguments of an HTTP GET or POST message. When the server runs the PHP script in response to the HTTP method, it makes the arguments available in the PHP superglobals $_GET or $_POST.
  2. When the server runs the PHP script, it replaces each snippet of PHP code embedded in HTML with the output (echo, print()) of running the PHP snippet.
  3. A self-processing page is a PHP script that serves both as input (via a form) and output. In other words, when the form is submitted, the same PHP script runs again, this time showing the output as well as the form. A good example is the Google search engine: the query input box appears again alongside the search results.


Previous: solutions-quiz2-2, Up: Solutions-quiz2

solutions-quiz2-3 Context

  1. 3 7 8 9 9
  2. A list literal in scalar context gets converted to its last element. For example, the assignment $y = (7, 8, 9) provides a scalar context to the list literal (7, 8, 9), and therefore assigns 9.
  3. An array in scalar context gets converted to its length. For example, the addition @x + 0 provides a scalar context to the array @x, and therefore returns 3.
  4. A scalar in list context gets converted to a list of one element. For example, the loop for $i ($y) { print $i } provides a list context to the scalar $y, and therefore uses it as a list of one element, 9.


Next: , Previous: Solutions-quiz2, Up: Solutions

Example solutions for Homework 6


Next: , Up: Solutions-hw06

solutions-hw06-1 Closures

  1. 6, 10
  2. The function is the anonymous inner function nested in curry. The environment is a call object for curry, with f=add and x=1.
  3. The function is the anonymous inner function nested in curry. The environment is a call object for curry, with f bound to the anonymous function function(x,y){x/y} and x=2.
  4.           var square = curry(
                function(n,x){ for(var z=1;n>0;n--,z*=x); return z; },
                2);
         


Next: , Previous: solutions-hw06-1, Up: Solutions-hw06

solutions-hw06-2 Prototypes

  1.           Cf, Dg, Ch
              Cf, Dg, Eh
         
  2. D.prototype, C.prototype, Object.prototype
  3. E.prototype, D.prototype, C.prototype, Object.prototype


Next: , Previous: solutions-hw06-2, Up: Solutions-hw06

solutions-hw06-3 Temperature conversions (JavaScript)

     <html><head>
       <meta http-equiv="Content-Script-Type" content="text/javascript" />
       <script>
         function c2f() {
           var c = document.converter.celsius.value;
           var f = c * 9 / 5 + 32;
           document.converter.fahrenheit.value = f;
         }
         function f2c() {
           var f = document.converter.fahrenheit.value;
           var c = (f - 32) * 5 / 9;
           document.converter.celsius.value = c;
         }
       </script>
     </head><body>
       <form name="converter">
         <table border=0>
           <tr>
             <td>Celsius:
             <td><input type="text" name="celsius">
             <td><input type="button" value="To Fahrenheit" onclick="c2f();">
           <tr>
             <td>Fahrenheit:
             <td><input type="text" name="fahrenheit">
             <td><input type="button" value="To Celsius" onclick="f2c();">
         </table>
       </form>
     </body></html>


Previous: solutions-hw06-3, Up: Solutions-hw06

solutions-hw06-4 Priority queue (JavaScript)

     function PriorityQueue() {
       this.data = [];
     }
     PriorityQueue.prototype.push = function(x) {
       this.data.push(x);
     }
     PriorityQueue.prototype.minIndex = function() {
       var result;
       for (var i in this.data)
         if (undefined == result || this.data[i] < this.data[result])
           result = i;
       return result;
     }
     PriorityQueue.prototype.peek = function() {
       return this.data[this.minIndex()];
     }
     PriorityQueue.prototype.pop = function() {
       var i = this.minIndex();
       var result = this.data[i];
       delete this.data[i];
       return result;
     }


Next: , Previous: Solutions-hw06, Up: Solutions

Example solutions for Homework 7


Next: , Up: Solutions-hw07

solutions-hw07-1 Google Suggest

  1. Each time the user changes a character in the search box, I would send an XMLHttpRequest to the server with the entire contents of the search box. Then, the server would send back a list of suggested completions.
  2. The server would store a database of suggestions at application scope. All users would use the same database, it would survive longer than any individual request or even session.


Next: , Previous: solutions-hw07-1, Up: Solutions-hw07

solutions-hw07-2 Natural language translation (PHP + SQL)

  1. http://www.cs.nyu.edu/~hirzel/hw07/2.php
  2.           <html><head>
                <title>Translation Database</title>
              </head><body>
                <!-- show form for user input -->
                <form action="<?php echo $_SERVER[PHP_SELF]; ?>" method=get>
                  <table border=0>
                    <tr><td>English:    <td><input type="text" name="eng"><br/>
                    <tr><td>Translated: <td><input type="text" name="tra"><br/>
                  </table>
                  <input type="radio" name="request" value="add">
                    Add</br>
                  <input type="radio" name="request" value="e2f">
                    Get (English to Translated)</br>
                  <input type="radio" name="request" value="f2e">
                    Get (Translated to English)</br>
                  <input type="radio" name="request" value="del">
                    Delete</br>
                  <input type="submit" value="submit">
                </form>
                <!-- open database, and create table if it does not yet exist -->
                <?php
                  $db = sqlite_open("/home/hirzel/data/sqlite2", 0666, $err);
                  if ($err) { die($err); }
                  sqlite_query($db, "SELECT * FROM Translate", SQLITE_BOTH, $err);
                  if ($err) {
                    echo "Table 'Translate' does not yet exist, creating it ...<br/>";
                    $q = "CREATE TABLE Translate"
                       . "(English VARCHAR(50), Translated VARCHAR(50))";
                    sqlite_query($db, $q, SQLITE_BOTH, $err);
                    if ($err) { die($err); }
                  } else {
                    echo "Reopened table 'Translate'.<br/>";
                  }
                ?>
                <!-- process input, if any -->
                <?php
                  if ("add" == $_GET[request]) {
                    $q = "INSERT INTO Translate VALUES("
                       . "'" . addslashes($_GET[eng]) . "', "
                       . "'" . addslashes($_GET[tra]) . "')";
                    sqlite_query($db, $q);
                    if ($err) { die($err); }
                    echo "Add English '" . htmlentities($_GET[eng]) . "', " .
                         "Translated '" . htmlentities($_GET[tra]) . "' succeeded.";
                  } else if ("e2f" == $_GET['request']) {
                    $q = "SELECT Translated FROM Translate WHERE English = "
                       . "'" . addslashes($_GET[eng]) . "'";
                    $rows = sqlite_query($db, $q);
                    if ($err) { die($err); }
                    $row = sqlite_fetch_array($rows, SQLITE_BOTH);
                    if ($err) { die($err); }
                    echo "Get English '" . htmlentities($_GET[eng]) . "' returned "
                         . "Translated '" . htmlentities($row[Translated]) . "'.";
                  } else if ("f2e" == $_GET['request']) {
                    # echo "Sorry, lookup from Translated to English not yet implemented.";
                    $q = "SELECT English FROM Translate WHERE Translated = "
                       . "'" . addslashes($_GET[tra]) . "'";
                    $rows = sqlite_query($db, $q);
                    if ($err) { die($err); }
                    $row = sqlite_fetch_array($rows, SQLITE_BOTH);
                    if ($err) { die($err); }
                    echo "Get Translated '" . htmlentities($_GET[tra]) . "' returned "
                         . "English '" . htmlentities($row[English]) . "'.";
                  } else if ("del" == $_GET['request']) {
                    # echo "Sorry, deletion not yet implemented.";
                    $q = "DELETE FROM Translate WHERE "
                       . "English = '" . addslashes($_GET[eng]) . "' AND "
                       . "Translated = '" . addslashes($_GET[tra]) . "'";
                    sqlite_query($db, $q);
                    if ($err) { die($err); }
                    echo "Delete English '" . htmlentities($_GET[eng]) . "', " .
                         "Translated '" . htmlentities($_GET[tra]) . "' succeeded.";
                  }
                ?>
              </body>
         


Next: , Previous: solutions-hw07-2, Up: Solutions-hw07

solutions-hw07-3 Session visit counter (PHP)

     <?php session_start(); ?>
     <html><head>
       <title>Session counter</title>
     </head><body>
       In this session, you have visited this page
       <?php
         if (empty($_SESSION[count]))
           $_SESSION[count] = 0;
         $_SESSION[count]++;
         echo $_SESSION[count];
       ?>
       times.
     </body>


Previous: solutions-hw07-3, Up: Solutions-hw07

solutions-hw07-4 Word reversal AJAX (JavaScript + PHP)

  1. http://www.cs.nyu.edu/~hirzel/a.html
  2. a.html
              <html><head>
                <meta http-equiv="Content-Script-Type" content="text/javascript" />
                <script src="c.js"></script>
              </head><body bgColor="#00ff00">
                Reversed: <span id="reverse">(please click button)</span>
                <form name="in">
                  String to reverse: <input type="text" name="forward"><br/>
                  <input type="button" value="Toggle Color" onclick="localChange();">
                  <input type="button" value="Reverse String" onclick="sendRequest();">
                </form>
              </body></html>
         

    b.php

              <?php sleep(3); echo htmlentities(strrev($_GET[fwd])) ?>
         

    c.js

              function localChange() {
                var blue = document.bgColor == '#0000ff'
                document.bgColor = blue ? '#00ff00' : '#0000ff';
              }
              function sendRequest() {
                document.getElementById('reverse').innerHTML = '(please wait)';
                var xhr = false;
                function handleResponse() {
                  if (4 == xhr.readyState && 200 == xhr.status)
                    document.getElementById('reverse').innerHTML = xhr.responseText;
                }
                try { xhr = new XMLHttpRequest(); } catch(e1) {
                  try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e2) {
                    try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e3) {
                      alert('Could not create XMLHttpRequest object.'); } } }
                xhr.open('GET', 'b.php?fwd=' + document.in.forward.value, true);
                xhr.onreadystatechange = handleResponse;
                xhr.send(null);
              }
         


Next: , Previous: Solutions-hw07, Up: Solutions

Example solutions for Homework 8


Next: , Up: Solutions-hw08

solutions-hw08-1 Same Origin Policy

        result   motivation
     1  success  same domain+protocol+port
     2  success  same domain+protocol+port
     3  failure  different protocol ftp
     4  failure  different domain www.columbia.edu
     5  success  same domain+protocol+port (port 80 is default)
     6  failure  different port 8080
     7  failure  same domain nyu.edu but different server www2


Next: , Previous: solutions-hw08-1, Up: Solutions-hw08

solutions-hw08-2 SQL Injection Vulnerability

  1. Let's assume that the variable $name comes from user input, for example, from $_GET['name']. Then, the attacker can provide the following input:
              foo'; drop table custid; --
         

    This is the same input as on the slides. If embedded in SQL, it will end the current string and statement, then start a new statement that destroys a table.

  2. PHP already provides a sanitization function for this purpose, called addslashes. It is easy to reimplement from first principle:
              function my_addslashes($str) {
                $badchar = array("\\", '"', "'", "\0");
                $replace = array();
                foreach ($badchar as $c) array_push($replace, "\\" . $c);
                $result = str_replace($badchar, $replace, $str);
                return $result;
              }
         


Previous: solutions-hw08-2, Up: Solutions-hw08

solutions-hw08-3 Cross-Site Scripting

Somewhere along the way of information flowing from user input to HTML output, the data must be sanitized. PHP already provides the function htmlspecialchars for this purpose. If written from first principle, it looks a lot like the SQL sanitization function from the previous question:

     function my_htmlspecialchars($str) {
       $badchar = array("&", '"', "'", "<", ">");
       $replace = array("&amp;", "&quot;", "&#039;", "&lt;", "&gt;");
       $result = str_replace($badchar, $replace, $str);
       return $result;
     }


Next: , Previous: Solutions-hw08, Up: Solutions

Example solutions for Quiz 3


Next: , Up: Solutions-quiz3

solutions-quiz3-1 Closures

  1.           a=1, b=2
              a=3, b=2
         
  2. inner
  3. The call object for the call outer(2), with the binding b=2. Since the call object refers to the same global object both during and after the call, the binding for a changes from a=1 to a=3.


Next: , Previous: solutions-quiz3-1, Up: Solutions-quiz3

solutions-quiz3-2 AJAX

  1. Asynchronous Javascript And XML.
  2. The user does not have to wait while the script communicates with the server.


Previous: solutions-quiz3-2, Up: Solutions-quiz3

solutions-quiz3-3 Security

  1. User input that contains malicious SQL code, which gets used as part of a SQL query.
  2. The malicious SQL code could delete data from the database.
  3. By sanitizing all user data. Any user data that gets used as part of SQL must be cleaned of anything that looks like SQL.


Next: , Previous: Solutions-quiz3, Up: Solutions

Example solutions for Homework 9


Next: , Up: Solutions-hw09

solutions-hw09-1 Scientific Method

  1.           initial input:
               2 1 3
               0 1 1
               4 1 2
              expected output:
               2 1 3
               0 1 1
               4 1 2
               2 1 2
              actual output:
               2 1 3
               0 1 1
               4 1 2
               1 1 2
         
  2.           1 Hypothesis  compute_avg returns wrong value
                            (expected value would be 2 1 2)
                Experiment  perl -wd script.pl
                            b 17
                            c
                            p @result
                Observation 1 1 2
                Conclusion  @result is wrong, hypothesis verified
              2 Hypothesis  at Line 15, numerator $sums[0] is wrong;
                            (expected value would be 2+0+4 == 6)
                Experiment  perl -wd script.pl
                            b 15
                            c
                            p $i, " ", $sums[$i]
                Observation 0 2
                Conclusion  $i == 0 and $sums[$i] == 2 != 6
                            $sums[0] is wrong, hypothesis verified
              3 Hypothesis  Line 10 adds the wrong numbers into $sums[0]
                            (expected 3 iterations with $j==0, values 2 0 4)
                Experiment  perl -wd script.pl
                            a 10 print "==> " . $row->[$j] . "\n" if $j==0;
                            c
                Observation ==> 2
                            ==> 0
                            Debugged program terminated.
                Conclusion  Line 10 adds the correct values from the first two
                            rows, but is missing the value from the third row.
              4 Hypothesis  the outer loop iterates for the wrong number of rows
                            (expected $nrows would be 3)
                Experiment  perl -wd script.pl
                            b 7
                            c
                            p $nrows
                Observation 2
                Conclusion  $nrows == 2, but should be == 3
              5 Hypothesis  the defect is in Line 6, since $#_ gives the index
                            of the last element, but we want the size, which is
                            one larger
                Experiment  change Line 6 to:
                              my $nrows = @_;
                            then rerun script
                Observation expected output and actual output are identical
                Conclusion  done, the bug is fixed
         


Previous: solutions-hw09-1, Up: Solutions-hw09

solutions-hw09-3 Delta Debugging

No example solutions.


Next: , Previous: Solutions-hw09, Up: Solutions

Example solutions for Homework 10


Next: , Up: Solutions-hw10

solutions-hw10-1 Iterating with Coroutines

  1.           preorder:
              1
              2
              4
              5
              3
              6
              7
         
  2.           #!/usr/bin/env python
              class Tree:
                  def __init__(self, value, left=None, right=None):
                      self.value = value
                      self.left = left
                      self.right = right
                  def preorder(self):
                      yield self.value
                      if self.left:
                          for v in self.left.preorder():
                              yield v
                      if self.right:
                          for v in self.right.preorder():
                              yield v
                  def inorder(self):
                      if self.left:
                          for v in self.left.inorder():
                              yield v
                      yield self.value
                      if self.right:
                          for v in self.right.inorder():
                              yield v
              
              my_tree = Tree(1,
                          Tree(2,Tree(4),Tree(5)),
                          Tree(3,Tree(6),Tree(7)))
              
              def print_preorder(tree):
                  print 'preorder:'
                  for y in my_tree.preorder():
                      print y
              
              print_preorder(my_tree)
              
              def print_inorder(tree):
                  print 'inorder:'
                  for y in my_tree.inorder():
                      print y
              
              print_inorder(my_tree)
         


Next: , Previous: solutions-hw10-1, Up: Solutions-hw10

solutions-hw10-2 Iterating with Block Parameters

  1.           preorder:
              1
              2
              4
              5
              3
              6
              7
         
  2.           #!/usr/bin/env ruby
              class Tree
                attr_accessor :value, :left, :right
                def initialize(value, *leftRight)
                  @value = value
                  if 0 < leftRight.length()
                    @left = leftRight[0]
                    @right = leftRight[1]
                  end
                end
                def preorder()
                  yield @value
                  if @left
                    @left.preorder {|v| yield v }
                  end
                  if @right
                    @right.preorder {|v| yield v }
                  end
                end
              end
              
              $my_tree = Tree.new(1,
                           Tree.new(2, Tree.new(4), Tree.new(5)),
                           Tree.new(3, Tree.new(6), Tree.new(7)))
              
              def print_preorder(tree)
                puts 'preorder:'
                tree.preorder {|y| puts y.to_s + "\n" }
              end
              
              print_preorder($my_tree)
              
              def print_sum(tree)
                puts "sum:"
                sum = 0
                tree.preorder {|y| sum += y }
                puts sum
              end
              
              print_sum($my_tree)
         


Next: , Previous: solutions-hw10-2, Up: Solutions-hw10

solutions-hw10-3 Coroutines vs. Block Parameters

  1. Method Tree.preorder in the Python example above is a coroutine. Every time the co-routine yields, it returns control to the caller. When the caller calls it again, the coroutine resumes where it left off.

    Method Tree.preorder in the Ruby example above takes a block as a parameter. Every time the Ruby method Tree.preorder yields, it calls the block. When the block returns, the method continues just like after a normal call.

    The difference is that the Python coroutine uses yield to return to its caller, whereas the Ruby method uses yield to call its block.

  2. From the user's perspective, Python's coroutines more completely hide the complexity of what's going on. Another advantage that is not illustrated by this example is that a coroutine call need not happen in a loop, it can be called from multiple places in regular computation.
  3. Most scripting languages already provide closures in one form or another. Block parameters are a simple variation on that. This makes it easier to implement the script interpreter. Also, if the user already understands closures, block parameters are easier to understand.


Previous: solutions-hw10-3, Up: Solutions-hw10

solutions-hw10-4 Iterating with Closure Parameters (PHP)

     #!/usr/bin/env php
     <?php
     class Tree {
       var $value, $left, $right;
       function __construct($value, $left=null, $right=null) {
         $this->value = $value;
         $this->left  = $left;
         $this->right = $right;
       }
       function preorder($closure) {
         $closure($this->value);
         if ($this->left):
           $this->left->preorder($closure);
         endif;
         if ($this->right):
           $this->right->preorder($closure);
         endif;
       }
     }
     
     $myTree = new Tree(1,
                      new Tree(2, new Tree(4), new Tree(5)),
                      new Tree(3, new Tree(6), new Tree(7)));
     
     function printPreorder($tree) {
       echo "preorder:\n";
       $tree->preorder(create_function('$v', 'echo "$v\n";'));
     }
     
     printPreorder($myTree);
     ?>


Previous: Solutions-hw10, Up: Solutions

Example solutions for final exam


Next: , Up: Solutions-final

solutions-final-1 BNF and regular expressions

  1. apple1, _weight
  2. 1apple, weight=
  3. [A-Za-z_][A-Za-z0-9_]*


Next: , Previous: solutions-final-1, Up: Solutions-final

solutions-final-2 Web programming

  1. From the EGPCS superglobals ($_ENV, $_GET, $_POST, $_COOKIE, $_SESSION).
  2. By reading user input out of forms, using DOM tree properties during an event handler.
  3. In the same place where the code snippet was embedded in HTML.
  4. In the same place where the code snippet was embedded in HTML.
  5. By setting a cookie.


Next: , Previous: solutions-final-2, Up: Solutions-final

solutions-final-3 Type conversions

  1.           3-a(1) context provider:   operator .
              3-a(2) conversion context: scalar (string)
              3-a(3) converted value:    "rl"
              3-a(4) end result:         "perl"
         
  2.           3-b(1) context provider:   function sqrt
              3-b(2) conversion context: scalar (number)
              3-b(3) converted value:    4
              3-b(4) end result:         2
         


Next: , Previous: solutions-final-3, Up: Solutions-final

solutions-final-4 List comprehensions

  1. ["quiz1.html", "quiz1.pdf", "quiz2.html", "quiz2.pdf"]
  2. for $n (@numbers) { for $e (@extensions) { push @quizzes, "quiz$n.$e" } }


Next: , Previous: solutions-final-4, Up: Solutions-final

solutions-final-5 Web application security

  1. The script is vulnerable to XSS (cross-site scripting).
  2. By constructing a URL that uses malicious JavaScript code where the value for parameter editor is expected. For example: http://www.cs.nyu.edu/~hirzel/editor_poll.php?editor=<script>alert("boo!")</script>.
  3. By sanitizing the user input before writing it to HTML. After “You selected”, the code should be: <?php echo htmlentities($_GET['editor']) ?>.


Previous: solutions-final-5, Up: Solutions-final

solutions-final-6 Prototypes and constructors

  1. 5
  2. The constructor is the function Vector.
  3. The prototype is the object Vector.prototype.