CSE 130, FALL 05 - Programming Assignment #1
CSE 130, FALL 05 - Programming Assignment #1
html
(click your browser's refresh button to ensure that you have the most recent version)
Note: See this for instructions on starting SML in the ACS lab machines. To download and install SML/NJ version 110.55 on your home machines see the
instructions here. To get the code provided for problem 4 to work on Windows Install ImageMagick. Remember that this is only to enable you to play with
the assignment at home: the final version turned in must work on the ACS Linux machines. While you can use windows to begin working with SML, the code
you turn in must be that required for the Linux environment.
Integrity of Scholarship
University rules on integrity of scholarship will be strictly enforced. By completing this assignment, you implicitly agree to abide by the UCSD Policy on
Integrity of Scholarship described beginning on page 62 of the Academic Regulations section (PDF) of the 2002-2003 General Catalog, in particular, "all
academic work will be done by the student to whom it is assigned, without unauthorized aid of any kind."
You are expected to do your own work on this assignment; there are no group projects in this course. You may (and are encouraged to) engage in general
discussions with your classmates regarding the assignment, but specific details of a solution, including the solution itself, must always be your own work.
Incidents that violate the University's rules on integrity of scholarship will be taken seriously: In addition to receiving a zero (0) on the assignment, students
may also face other penalties, up to and including, expulsion from the University. Should you have any doubt about the moral and/or ethical implications of an
activity associated with the completion of this assignment, please see the instructors.
Code for all programming assignments should be well documented. A working program with no comments will receive only partial credit. Documentation
entails writing a description of each function/method, class/structure, as well as comments throughout the code to explain the program logic. Comments in
SML/NJ are enclosed within (* *), and may be nested. It is understood that some of the exercises in this programming assignment require extremely little code
and will not require extensive comments.
While few programming assignments pretend to mimic the "real" world, they may, nevertheless, contain some of the ambiguity that exists outside the
classroom. If, for example, an assignment is amenable to differing interpretations, such that more than one algorithm may implement a correct solution to the
assignment, it is incumbent upon the programmer to document not only the functionality of the algorithm (and more broadly his/her interpretation of the
program requirements), but to articulate clearly the reasoning behind a particular choice of solution.
Assignment Overview
The overall objective of this assignment is for you to gain some hands-on experience with SML. All the problems require relatively little code ranging from 2
to 15 lines. If any function requires more than that, you can be sure that you need to rethink your solution. The assignment is spread over four files misc.sml,
expr.sml, art.sml, test.sml, that you need to download. The first three files contain several skeleton SML functions, with missing bodies, i.e. expressions,
which currently contain the text raise Failure "to be written" . Your task is to replace the text in those files with the the appropriate SML code for each
of those expressions.
Note: All the solutions can be done using the purely functional fragment of SML, using constructs covered in class, and most require the use of recursion.
Solutions using imperative features such as references, while loops or library functions will receive no credit.
It is a good idea to start this assignment early; ML programming, while quite simple (when you know how), often seems somewhat foreign at first, particularly
when it comes to recursion and list manipulation.
Your functions/programs must compile and/or run on a Linux ACS machine (e.g. ieng6.ucsd.edu , as this is where the verification of your solutions will
occur. While you may develop your code on any system, ensure that your code runs as expected on an ACS machine prior to submission. You should test your
code in the directories from which the zip files (see below) will be created, as this will approximate the environment used for grading the assignment.
Most of the points, except those for comments and style, will be awarded automatically, by evaluating your functions against a given test suite. The
fourth file, test.sml contains a very small suite of tests which gives you a flavor of of these tests. At any stage, by typing at the UNIX shell :
sml < test.sml | grep "130>>" > log
you will get a report on how your code stacks up against the simple tests.
The last line of the file log must contain the word "Compiled" otherwise you get a zero for the whole assignment. If for some problem, you cannot get
1 of 5 2/18/2021, 6:58 AM
CSE 130, FALL 05: Programming Assignment #1 https://cseweb.ucsd.edu/classes/fa05/cse130/pa1/pa1.html
the code to compile, leave it as is with the raise ..., with your partial solution enclosed below as a comment. There will be no exceptions to this rule. The
second last line of the log file will contain your overall score, and the other lines will give you a readout for each test. You are encouraged to try to understand
the code in test.sml, and subsequently devise your own tests and add them to test.sml, but you will not be graded on this.
and it should return a pair of integers, reflecting your score and the max possible score on the sample tests. If instead an error message appears, your code will
receive a zero.
Submission Instructions
Your solutions to this assignment will be stored in separate files under a directory called solution/, inside which you will place the files:
misc.sml, expr.sml, art.sml, art_g_sample.jpg, gray1.jpg, gray2.jpg, gray3.jpg, color1.jpg, color2.jpg, color3.jpg. The
first three files listed above are the versions of the corresponding supplied file that you will have modified. The last seven .jpg files are described
below. There should be no other files in the directory.
After creating and populating the directory as described above, create a zip file called <LastName>_<FirstName>_cse130_pa1.zip by going into
the directory solution and executing the UNIX shell command:
zip <LastName>_<FirstName>_cse130_pa1.zip *
Once you've created the zip file with your solutions, you will use the turnin program to submit this file for grading by going into the directory
solution/ and executing the UNIX shell command:
The turnin program will provide you with a confirmation of the submission process; make sure that the size of the file indicated by turnin
matches the size of your tar file. See the ACS Web page on turnin for more information on the operation of the program.
Write an SML function digitsPos : int -> int list that takes an integer n as an argument and if the integer is positive, returns the list of digits of n in
the order in which they appear in n . Once you have implemented the function, you should get the following behavior at the SML prompt:
- digitsPos 3124;
val it = [3,1,2,4] : int list
- digitsPos 352663;
val it = [3,5,2,6,6,3] : int list
(b) 10 points
Now write an SML function listAdd : int list -> int that takes an integer list l and returns the sum of the elements of l . Once you have implemented
the function, you should get the following behavior at the SML prompt:
- listAdd [1,2,3,4];
val it = 10 : int
- listAdd [1,~2,3,5];
val it = 7 : int
Consider the process of taking a number, adding its digits, then adding the digits of the number derived from it, etc., until the remaining number has only one
digit. The number of additions required to obtain a single digit from a number n is called the additive persistence of n, and the digit obtained is called the
digital root of n. For example, the sequence obtained from the starting number 9876 is (9876, 30, 3), so 9876 has an additive persistence of 2 and a digital root
of 3. Write two SML functions additivePersistence : int -> int and digitalRoot : int -> int that take integer arguments n and return
respectively the additive persistence and the digital root of n . Once you have implemented the functions, you should get the following behavior at the SML
prompt:
- additivePersistence 9876;
val it = 2 : int
- digitalRoot 9876;
2 of 5 2/18/2021, 6:58 AM
CSE 130, FALL 05: Programming Assignment #1 https://cseweb.ucsd.edu/classes/fa05/cse130/pa1/pa1.html
val it = 3 : int
Without using any built-in SML functions, write an SML function listReverse : 'a list -> 'a list that takes a list l as an argument and returns a list
of the elements of l in the reversed order. Once you have implemented the function, you should get the following behavior at the SML prompt:
- listReverse [1,2,3,4];
val it = [4,3,2,1] : int list
- listReverse ["a","b","c","d"];
val it = ["d","c","b","a"] : string list
(b) 5 points
A palindrome is a word that reads the same from left-to-right and right-to-left. Write an SML function palindrome : string -> bool that takes a string w
and returns true if the string is a palindrome and false otherwise. You may want to use the SML function explode . Once you have implemented the function,
you should get the following behavior at the SML prompt:
- palindrome "malayalam";
val it = true : bool
- palindrome "myxomatosis";
val it = false : bool
Without using any built-in SML functions, write an SML function isMember : (int * int list) -> bool that takes a pair (e,l) and returns true if the
integer e appears in l and false otherwise. Once you have implemented the function, you should get the following behavior at the SML prompt:
- isMember (4, [1,6,2,4,12]);
val it = true : bool
- isMember (4, [1,6,2,12]) ;
val it = false : bool
(b) 20 points
Without using any built-in SML functions, modify the skeleton for cleanList to obtain a function of type int list -> int list that takes a list l and
returns the list of elements of l with the duplicates, i.e. second, third, etc. occurrences, removed, and where the remaining elements appear in the same order
as in l . Once you have implemented the function, you should get the following behavior at the SML prompt:
- cleanList [1,6,2,4,12,2,13,6,9];
val it = [1,6,2,4,12,13,9] : int list
(c) 20 points
Without using any built-in SML functions, or the while construct, write an SML function:
for : int * int * (int -> unit) -> unit that takes as input a triple (low,high,f) and applies the function f to every integer i such that low <= i
<= high. Once you have implemented the function, you should get the following behavior at the SML prompt:
3 of 5 2/18/2021, 6:58 AM
CSE 130, FALL 05: Programming Assignment #1 https://cseweb.ucsd.edu/classes/fa05/cse130/pa1/pa1.html
where pi stands for the constant 3.142, are functions over the variables x,y, which are guaranteed to produce a value in the range [-1,1] when x and y are in
that range. We can represent expressions of this grammar in SML using values of the following datatype:
datatype Expr =
VarX
| VarY
| Sine of Expr
| Cosine of Expr
| Average of Expr * Expr
| Times of Expr * Expr
First, write a function exprToString : Expr -> string to enable the printing of expressions. Once you have implemented the function, you should get
something like the following behavior at the SML prompt:
- exprToString (Times(Sine(VarX),Cosine(Average(VarX,VarY))));
val it = "sin(pi*x)*cos(pi*((x+y)/2))" : string
Next, write the function eval : Expr * real * real -> real that takes an triple (e,x,y) and evaluates the expression e at the point x,y . You should
use SML/NJ Math library, in particular, Math.sin,Math.cos, Math.pi to build your evaluator. Recall that Sine(VarX) corresponds to the expression
sin(pi*x). Once you have implemented the function, you should get the following behavior at the SML prompt:
- eval (Sine(Average(VarX,VarY)),0.5,~0.5);
val it = 0.0 : real
- eval (Sine(Average(VarX,VarY)),0.3,0.3);
val it = 0.809016994375 : real
- eval (sampleExpr,0.5,0.2);
val it = 0.118612572815 : real
to generate the grayscale image art_g_sample.jpg in your working directory. To receive full credit, this image must look like the leftmost grayscale image
4 of 5 2/18/2021, 6:58 AM
CSE 130, FALL 05: Programming Assignment #1 https://cseweb.ucsd.edu/classes/fa05/cse130/pa1/pa1.html
displayed above. Note that requires your implementations of for, eval to work correctly. A message Uncaught exception Chr is an indication that your
eval is returning a value outside the range [-1,1].
(b)(art.sml) 25 points
Next, you must fill in an implementation for the function build that generates random expressions. The function is of type build : int * (int*int ->
int) -> Expr . The function is called with the argument pair (depth,rand) .
The first element depth is a maximum nesting depth. A random expression of depth d built by randomly composing sub-expressions of depth d-1 , and the
only expressions of depth 0 are VarX or VarY .
The second element rand is a random number generator of type int * int -> int . Each call rand (i,j) returns a random integer between i and j
inclusive. Use this function to randomly select operators when composing subexpressions to build up larger expressions.
With this in place you can generate random art using the functions
doRandomGray : int * int * int -> unit
doRandomColor : int * int * int -> unit
Each function takes as a parameter a triple (depth,seed1,seed2) where depth is the depth of the expression to be generated and seed1,seed2 are two
seeds for the random number generator. The functions generate JPEG files called
art_g_<depth>_<seed1>_<seed2>.jpg,
art_c_<depth>_<seed1>_<seed2>.jpg .
The first is a gray scale image, built by mapping out a single randomly generated expression over the plane, and the second is a color image built using three
functions for the intensities of red, green and blue.
Play around with how you generate the expressions, using the tips below. Name your best three color files color1.jpg, color2.jpg, color3.jpg, and save
their parameters, i.e. the depth and the seeds in the bodies of c1,c2,c3. Name your best three gray files gray1.jpg, gray2.jpg, gray3.jpg , and save their
parameters in the bodies of g1,g2,g3.
Note:
Don't build the datatypes directly -- use the build functions provided in expr.sml. The purpose is to hide the actual implementation, i.e. the datatype, for
the expressions from the random art code, thus enabling modular code. We will see more of modules later.
Depths of 8-12 produce interesting pictures, but play around!
Make sure your expressions don't get "cut-off" early with VarX,VarY, as small expressions give simple pictures. In general, play around to bias the
generation towards more interesting operators.
(c)(art.sml) 20 points
Finally, add two new operators to the grammar, i.e. to the datatype, by introducing two new datatype constructors, and adding the corresponding cases to
exprToString, eval, build . The only requirements are that the operators must return values in the range [-1,1] if their arguments are in that range, and
that one of the operators take three arguments, i.e. one of the datatype constructors is of the form:
C of expr * expr * expr
You can include images generated with these new operators when choosing your best images for part (b).
The creators of the best five images, will get extra credit. Be creative!
5 of 5 2/18/2021, 6:58 AM