CS 245 - Programming Languages

Homework 4

Rust Programs

In this lab you will write four small programs in Rust. Each of your programs should be it its own cargo workspace.

Each program should be accompanied by a set of tests sufficient to demonstrate that your program works. The testing need not be formal tests in the Software Engineering sense, just runs of your program to demonstrate that it works. If your program requires command line input, the test could be documented in the readme in a form like: "execute 'cargo run -- 5'. This shows ....".

Except for program 3, you may assume that someone else is checking for valid input. So the tests need only demonstrate that your program works on "good" input.

Part 1

Lucas Sequences

Lucas sequences are a generalization of the Fibonacci sequence. The only difference is that Lucas sequences follow the sequence 1, L, (1+L), (1+L)+L, ... whereas Fibonacci numbers following the sequence, 1, 1, 2, 3, ... In other words, the Fibonacci sequence is a Lucas sequence with L=1. When L=2 the sequence is: 1,2,3,5,8,13. When L=3 the sequence is: 1,3,4,7,11,... Write a program that does the following.
  1. Computes (and print) the largest Lucas number that can be computed in Rust without the program Panicking (or otherwise dieing) when the program is compiled in debug mode for each of L= 1..10
  2. In addition to printing the largest number print the count of that number (for instance in the Fibonacci sequence, the count of 13 is 7)
  3. Computes (and print) the ratio of the largest to the next largest Lucas number for each of L= 1..10
Question
  1. Explain how you avoid panic (or death) in your program? Can this technique be applied to any mathematical function or did you take advantage of some aspect of the Lucas sequence?

Part 2

Write a Struct to hold the following information about students For that struct, write the following methods:
  1. check_num -- this should be a function of your devising that returns a number that is a function of the first name and last name. The function need not be complex or have any kind of non-collision guarantees.
  2. check_id -- return true if id is equal to the value produced by check_num, false otherwise.
  3. Debug -- this should be your own implementation that overrides Debug in the fmt module. It should print the first name, last name , id number and the value returned by check_id
Given all that, write a main function that reads student information from a file, puts the student information into structs and puts those structs into a vector (slice). You may create the student information file in any format that is convenient for your reader. The student information file must have information on at least 5 students. At least one of the five students should have an invalid id and at least one should have a valid id. As a final step, print the contents of the vector thereby showing the result of all of your work.

    

Perfect, and near perfect, numbers

In math a perfect number is one in which sum of its factors (excluding itself) is equal to itself. So 6 is a perfect number because its factors (1,2,3) sum to 6. For more details, there is an excellent article on Wikipedia about perfect numbers. In addition to simply finding perfect numbers, this program should find the numbers within 5 of being perfect. It should print out the numbers it found in a format similar to this:
-5 [9]
-4 [14, 44, 110, 152, 884, 2144, 8384]
-3 []
-2 [10, 136]
-1 [8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]
perfect [6, 28, 496, 8128]
1 []
2 [20, 104, 464, 650, 1952]
3 [18]
4 [12, 70, 88, 1888, 4030, 5830]
5 []
    
The above listing shows all perfect, and near perfect numbers in the range 6..=10000.

Requirements:

Stack Depth

The default stack size in Rust is 2M (in Go stack size is 1G). Write a program that determines how many recursive calls you can do before running out of stack space. Modify your program as needed to answer the following questions:
  1. Suppose your initial recursive function had a single parameter of type u32. How is the max stack depth affected by changing that single parameter to u64 or u128. Explain.
  2. Again, suppose your initial recursive function had a single parameter of type u32. Now add a new parameter of type i128 to the parameter set. How does this affect stack depth? Explain. Is your answer consistent with your previous answer? Explain.
  3. Again, suppose your initial recursive function had a single parameter of type u32. Now add a new parameter of type [i32; 100] to the parameter set. How does this affect max recursive stack depth? Explain. Is your answer consistent with your previous answers? Explain.
  4. Again, suppose your initial recursive function had a single parameter of type u32. Now add a new parameter of type Vec<i128> to the parameter set. The vector should contain at least 1000 random numbers. How does this affect max recursive stack depth? Explain. Is your answer consistent with your previous answers? Explain.
Each of the questions above asks you to make a change to a recursive function. Probably the best things to do would be to make a program that looks kind of like:
    fn main() {
        let args: Vec = env::args().collect();
        let version:u32 = args[1].trim().parse().unwrap();
        match version {
        1=>rec_v1(0),
        2=>rec_v2(....),
        3=>rec_v3(....),
        4=>rec_v4(....),
        }
    }
    fn rec_v1(param:i32) {
        // body here
    }
    fn rec_v2(....){ .... }
    fn rec_v3(....){ .... }
    fn rec_v4(....){ .... }
That is, write several versions of the recursive function with differing parameter sets. Then select the one to use via a command line parameter in the sample above "...." should be a valid set of parameters or valid code.

What to hand in

Before you submit your work, run "cargo clean" in each of the directories you created with cargo. Doing so will get rid of a bunch of stuff (intermediate compilation files, etc) and save a lot of space. Not cleaning before submitting will result in up to a 2 point penalty per uncleaned directory.

How to Submit

Put everything you want to submit in a directory containing nothing else. For instance you might name the directory a4

  1. Go to the directory containing a4
  2. Enter /home/gtowell/bin/submit -c 245 -p 4 -d a4
If this worked you will get a message with the word "success" and a listing of all the files you submitted.