This is a slightly shortened assignment (due to the midterm in-class on Thursday). It's due at the usual time (11:59 pm on Monday, 3/8).
The problems in this assignment exercise rex's ability to specify functions that themselves return functions. In addition, it introduces data structures more complex than lists (trees and graphs), which in rex are necessarily implemented as lists. We will use these data structures in the next assignment as the basis for two interactive applications.
This assignment covers much of the material through Chapter 4 in the text. You may also want to experiment with functions returning functions and anonymous functions in rex.
If you would like a few more practice problems to try either before or after the assignment, there are several (with solutions) in /cs/cs60/assignments/assignment7/practice.probs.
You should submit your rex functions in a single file named hw7.rex using
cs60submit hw7.rexor
cs60submitall
As in the previous assignments, commenting your functions and your file are important. Be sure your comments indicate what each function does, as well as what the inputs are.
As you gain experience writing code in rex, in addition, it is a good idea (and very much the spirit of rex and functional programming) to try to devise programs as elegant and concise as possible.
For an example of a thoroughly commented function, look at the file
insert.rex in the directory /cs/cs60/assignments/assignment7.
This file also provides an illustrative example of efficient tree-handling
code using rex and recursion.
rex > erdos(42);
21
rex > erdos(109);
328
erdos(erdos(erdos(3))) = 16.Continuing in this way,
erdos(erdos(erdos(erdos(erdos(erdos(erdos(3))))))) = 1with erdos iterated 7 times. Thus, collapse([3]) == [7]. Further examples of collapse in action include
rex > collapse([3, 10, 5, 16]); [7, 6, 5, 4] rex > collapse([129, 55, 85]); [121, 112, 9]Will every positive integer collapse to 1? No one knows, though many mathematicians have worked on it. The mathematician Paul Erdos actually felt that "mathematics is not yet ready for such problems." This problem is known as the Collatz problem or "3x+1" problem -- if you're in the hallways of Pomona's math department, you'll find a poster on this problem and what's currently known about it displayed on the wall! Check out the site http://www.paulerdos.com/0.html for more on Paul Erdos.
// Here I'm using the erdos function from the example above. // since the first argument is 1, the desired result is erdos(3), // and erdos(3) equals 10. rex > iterate(1, erdos, 3); 10 // Now I'm iterating twice and computing erdos(erdos(3)): rex > iterate(2, erdos, 3); 5 // And this is finding erdos(erdos(erdos(3))) rex > iterate(3, erdos, 3); 16 // Iterating the anonymous function below two times is equivalent to adding 2. rex > iterate(2, (x)=>x+1, 9); 11
// Here I'm using the erdos function from the example above. // since the first argument is 1, the desired result is erdos(3), // and erdos(3) equals 10. rex > iterate(1, erdos)(3); 10 // Now I'm iterating twice and computing erdos(erdos(3)): rex > iterate(2, erdos)(3); 5 // And this is finding erdos(erdos(erdos(3))) rex > e3 = iterate(3, erdos); 1 rex > e3(3); 16 // Iterating the anonymous function below two times is equivalent to adding 2. rex > iterate(2, (x)=>x+1)(9); 11
rex > ADD(n) => iterate(n, (x)=>x+1); 1where ADD(n) now returns a function that adds n to its argument:
rex > ADD(42)(100); 142For this problem, use iterate and ADD to define the MULT(n) function, which returns a function that multiplies its inputs by n. (You will have to add the above definition of ADD to your file in order that REX can use it.) Like ADD, MULT should be able to handle all nonnegative integers (including 0). For instance,
rex > m10 = MULT(10); 1 rex > m10(42); 420; rex > MULT(19)(17); 323
// To demonstrate, I'll first define two functions called foo and goo.
rex > foo(X) => 2*X + 1;
foo
rex > goo(X) => 3*X - 2;
goo
// Now, envelope(foo, goo) returns a function and here we let moo
// represent that function.
rex > moo = envelope(foo, goo);
1
// Now, let's evaluate the function moo with input of 5.
rex > moo(5);
13
Create the function biggestFan(G) that takes a directed graph G (as a binary relation) as input and outputs the node of G that has the biggest fan-in. The fan-in of a node is simply the number of parents of that node, so biggestFan returns the node with the most parents. You may assume that biggestFan will only receive input graphs that do have at least one edge.
If there is a tie for the biggest fan-in, you may return any one of the correct nodes. For example:
rex > biggestFan([ ["A","D"], ["B","D"], ["C","D"], ["A","E"],
["D","E"], ["E","F"], ["F","A"] ]);
D
rex > biggestFan([ ["A","B"], ["B","C"] ]);
B
where the last answer could also have been C. NOTE Your predicate will only be given ACYCLIC graphs as input. Thus, you don't have to worry about "running around in circles" searching for whether there is a path from a to b, because there will be no cycles in the graph. Also, remember the graphs are directed. For example,
rex > reachable("A", "F", [ ["A","D"], ["B","D"], ["C","D"], ["A","E"],
["D","E"], ["E","F"] ]);
1
rex > reachable("C", "A", [ ["A","B"], ["B","C"] ]);
0
rex > reachable("D", "D", [ ["A","B"], ["B","C"] ]);
1
As the last example illustrates, your function should acknowledge
that any node can be reached from itself. What's more the node
does not even need to be in the graph! (This is because the
graph does not have to be connected -- an unlisted node
is one with neither outgoing nor incoming edges.)
[ rootValue, leftSubtree, rightSubtree ]. The
rootValue will always be an integer, and the left and right
subtrees are binary search trees. Write the function delete(X,
T) that takes a value X and a list T representing a
binary search tree and returns a binary search tree with all of the elements
of T except with X removed. You can assume that
X is definitely in the tree T. For example, the list
[10, [3, [], []], [42, [20, [], []], [60, [], []] ] ]represents the tree

We will go over the algorithm for removing an item from a binary search tree in detail in class. As a brief reminder, the problem is "straightforward" (not a value judgment!) if the node to be deleted has zero children or one child. If it has two children, replace the note to be deleted with the next largest node in the tree.
For example, here is an example:
rex > mytree = [10, [3, [], []], [42, [20, [], []], [60, [], []] ] ]; 1 rex > delete(10, mytree); [20, [3, [], []], [42, [], [60, [], []]]]
Hint: you will need to write a function that finds the minimum element in a binary search tree. (Code for findMin will be written in class.)
Note that a variant on tHis function would allow a more efficient solution to the bestThree problem on the previous assignment, as there are at most 140 different three-letter substrings formable from seven characters. (You do not have to redo that problem!)
For instance,
rex > sublists([1]);
[ [], [1] ]
rex > sublists([42,100]);
[ [], [100], [42], [42,100] ]
For instance,
rex > readInteger(111221);
312211
rex > readInteger(8777511);
18371521