UNC-CH COMP 590-059

Final Exam

Individual work
Due: Sunday 5/4 (11:59pm)
Submitted as upload in Canvas

The exam is open book, open notes, open online info that is tutorial in nature (dont copy online code)... and as with the assignments, you may use chatGPT and other LLMs as tutors on language syntax and semantics... but do NOT ask for them to generate your solutions. Do your own coding. Please demonstrate what you have learned this semester.

There is no time limit on your work other than the final deadline for submission in Canvas.


Upload one zip file in canvas. That zip file will contain 2 directories:
  1. An Elixir directory, containing:
    • the Elixir source code file(s) for the problem One
    • a readme file with the text for the discussion questions in problem One
  2. A Go directory, containing:
    • the Go source code file(s) for the problem Two
    • a readme file with the text for the discussion questions in problem Two

One: Elixir OO

Write a program in Elixir that meets these specs:

Two: Go concurrency

Write a program in Go that meets these specs:


Class Assignments

Policy on AI tools:
You may use AI tools (e.g., ChatGPT, etc.) to assist your understanding of the concepts we study in this class, and to enhance your understanding of the mechamisms and methods in the PLs we use. These tools are excellent as tutorial resources, essentially being very rapid access to, and summarization of, materials findable on the internet with more traditional methods like Google search, Wikipedia, etc.

However, I want you to do your own coding. Form the solutions to your assignments yourself, not from AI tools and their solutions. Use your team members collectively to learn together, hopefully leaving you with a real understanding of the topics we are studying. You are honor-code bound to do your own (individually, and as a team) coding solutions.



Assignment 7: Go Processes: Sleeping Barber

Team work
Due: Monday 4/14 (11:59pm)

Team work... back to how we have been working.

Write a Go program to solve the Sleeping Barber problem. You already did this in Elixir, so you have a basic understanding of what you need to do. No need in the Go version to worry about hot-swapping code, but basically follow the other specs for the previous Elixir assignment (Assn. 5).



Assignment 6: Go basics

INDIVIDUAL work
Due: Thursday 3/20 (11:59pm)

Individual work... everyone will program this on your own.

This is an assignment to be done "in class" on Thursday. This assignment can easily be done in 75 mins and so I am making it due tonight (3/20) since you will have class time for it, and class attendance is required.

Write 2 Go programs, both of which compute N ^ P, N raised to the power P. Both will use goroutines (concurrent processes). Have the main function define the variable n and p as integers, and for simplicity, these parameters to the problem will be set as constants in the code rather than worrying for now about getting input from the kayboard. So set them to some initial value in the code for main (e.g., n = 127 and p = 12). Have function main call power(n,p). Then, the programs differ as follows:

Write a README file giving your reply to that last question about race conditions and your solutions, if any.

Create a zip file to upload to Canvas. The zip file will have 2 directory/file-folders, one for each of Prog One and Prog Two. In each directory will be the Go source file for the main package for that program.



Assignment 5: Elixir programming

Team work
Due: Friday 3/21 (11:59pm)

In this assignment we will write an Elixir program to solve the Sleeping Barber problem. Find this problem in an earlier class PPT.

I want to make some aspects of your solution the same for consistency. There are many ways to design a solution, so we will use this basic outline:

  -- Let's make each new customer a process.
  -- Let's make a process for the waiting room.  
  -- Let's add a receptionist process to the basic problem we defined earlier
       > have this receptionist greet each arriving customer
       > If there is room to wait, the receptionist sends the customer 
       > to the waiting room; if no room, the customer is turned away.
  -- Let's make the barber a process.  

This basic structure gives a lot of places that behavior can be parameterized or varied. The barber can cut hair in fixed time, long or short, or in random amounts of time. The barber can work a while and take a break for a while. The barber might get 2 chairs at some point, and handle 2 customer at once (like one has washed hair drying while another gets a cut). Customers can wait "forever" until served, or made to wait some amount of time and leave if not served. The wait room process can control how customers are handled... FIFO queue, priority some way, random, etc. All these different things can easily be written into the behavior of processes if we have the system architected that way.

I also want you to make parts of the program hot swappable. Do this for the main barber loop. In this way we can alter some of the barber characteristics without ending the execution of the program. Also make the spawning of a customer be a hot-swap... so that every time a customer is made we make the most recent version of the customer process code. The loop in a customer process can stay non-hot-swapped... when a customer is made, its behavior stays the same for its lifetime. But when a new customer is made we check for the latest version.

Feel free to make any other aspects of the program hot swappable as you see fit.

Some initial parameters/behaviors:

  -- The waiting room has 6 waiting chairs.  
  -- The barber has one cutting chair.
  -- Customers arrive at the shop at random times.
  -- The barber takes a random time to complete each haircut.
  -- The wait room is a FIFO queue
  -- customers who wait stay until they are served
  -- the simulation operates "forever" generating new customers

Write a README file giving your design rationale. What decisions did you make to get it running? Explain your overall design.



Assignment 4: Erlang processes program

Team work
Due: Friday 2/28 11:59pm

In this assignment we will write an Erlang program that spawns several processes to cooperatively solve the problem.

Write an Erlang program that will use the "send_recv" module we discusses in the video as a pattern or guide. You will write a chain of 3 "servers" which are processes that are in a chain communication pattern. Lets call for this discussion the servers serv1, serv2, and serv3. The head of the chain is serv1, which will be communicating with serv2; serv2 will communicate with serv3. The serv1 process will receieve messages (from the main function) and possibly send what it received on to serv2. The serv2 process will receieve messages from serv1 and possibly send what it received on to serv3; likewise, the serv3 process will receieve messages from serv2 but will not send any messages onward.

The basic specs are these:

-- all 3 server processes run potentially "forever" (except each will end when a halt message 
   is received)

-- each one will examine messages it receives looking for ones that
   it knows how to handle; on finding one, it will processes it as
   its job requires;  if a message does not match the pattern(s) 
   that it handles, the server process will pass that message down the chain.

-- serv1 will do much like the math servers from our example code.  It will intercept messages
   that are tuples of size 3 or size 2.  A size 3 tuple will have the first component the 
   atom 'add', 'sub', 'mult' or 'div', and the rest of the message will be 2 numbers.  
   Perform the indicated arithmetic operation with component 2 the left operand and component 
   3 the right operand.  In addition, a size 2 tuple will have the first component the atom 
   'neg' or 'sqrt' and the second component the numbers to apply the appropriate operation on.  
   For all messages, print an informative message indicating the operation, the operands, and 
   the result.  If the message does not match any of these patterns, then send the message 
   on to serv2. 

-- serv2 will intercept mesages that consist of lists, where the head element in the list
   is a number. if that number is an integer, then print out the sum of all elements in
   the list that are numbers.  If the head element of the list is a float, then compute and
   print the product of all the numbers in the list (integer or float).
   If the message does not match any of these patterns, then send the message on to serv3.

-- serv3 will get all the messages that the processes earlier in the chain
   dont want to handle.  If the message is a tuple of size 2, with the first component
   the atom 'error' then print "Error: " and the second component of the message tuple.
   For any other message keep a running count of the unprocessed messages.  Simply print 
   out "Not handled: " followed by the message; also bump up the unprocessed message count.  
   To do this you will need an accumulator that you pass to each successive recursive server 
   call.  This means the serv3 function you make into a process will use a helper recursive 
   function that takes one parameter (the accumulator) and starts with 0 as that parameter.

-- each server process is doing some printing.  Any output they make should have the first 
   part indetify the process doing the writing -- something like "(serv1) whatever the 
   output text is..."

-- in addition to the various different message patterns each server process will watch for,
   all 3 processes will also respond to a shut down message.  The message will be the single 
   atom 'halt' and the server behavior will be to forward the 'halt' message down the chain, 
   then print out that it is halting, and finally end its own execution (meaning do not recurse 
   for more message handling).  For the end of the chain, the serv3 process, which is counting 
   all messages not processed, print a note with the value of that counter before doing its 
   halt sequence.

The main function (let's call it "start/0") will repeatedly as the user to type a message as input, and will send the message to serv1 at the head on the chain. If the user types the atom 'all_done' then the main start function will end execution.

Feel free to embellish the program as you wish. Have fun with it.

This is team work. The team produces a common solution, and one group member submits the entire solution on behalf of all the group members. Put an erlang comment in your module source files naming all the group members (or naming the solo person doing the work if you are a team of 1). Also create a README text file with the team member names in it, as well as anything else you wish to comment about the assignment solution.
Put your source files and README into one zip file, and in Canvas, submit this single zip file.





Assignment 3: Basic Erlang Programming

Team work You may work in teams of 1, 2, or 3

Prepare a single zipfile that contains your source code AND a readme file containing the names of all team members.
ONE team member (doesnt matter who) will upload the zip file in Canvas on behalf of the entire team

Due: Friday. 2/14 11:59 pm in Canvas

In this assignment we will get Erlang running on your computers, and then write two simple Erlang programs. The goal is to get familiar with Erlang syntax and with the Erlang functional programming style.

Follow the instructions (see the reading lists) to get Erlang installed on your laptop or other computer. Try the examples we have looked at in class, and get used to making source modules (with the .erl file type). Make sure you move around in the file system using the unix-ish "cd", "pwd", and "ls" commands; make sure you can compile the modules; make sure you can run the functions defined and exported by those modules.

Here is a short new Erlang lesson: getting input from the keyboard. This is a small function that will get a number from the keyboard, and you may use this as you wish in the programs you write:

    get_numData() ->
        {ok, Num} = io:read("Enter a number: "),
        io:format("The number you entered is: ~w~n", [Num]).
This works using pattern matching, where the number typed by the user is bound to "Num" on the left side of the expression using io:read.

Once this all works, write these two Erlang programs:


  1. Write an Erlang program that will take one number as input (you will get the number from the user typing it at the keyboard) and then do this computation:
        a) if the input is not an integer, print "not an integer"
    
        b) if the input integer is negative (smaller than 0), compute
           the absolute value of that integer raised to the 7th power... 
           and print that.
    
        c) if the input integer is 0, simply output the 0
    
        d) is the input integer is greater than 0 then decide if it is 
           a multiple of 7 or not; if it is a multiple of 7, print out 
           the 5th root of the integer; if its not a multiple of 7, then 
           print out the factorial of that integer.
    
    It ends after doing the correct thing with the input number. You may find math:pow(X,Y) useful... it returns a float, and it computed X raised to the Y power. Factorial is a function we defined in class (in a PPT).


  2. Use the program just written as a "loop" body, and repeat the get-input-then-compute cycle repeatedly. End this repetition when the user gives a 0 as input. Note that you should do the "looping" here with tail recursion.

Since this is group work, the group produces a common solution and one group member submits the entire solution on behalf of all the group members. Put an erlang comment in your module source files naming all the group members, or naming the solo person doing the work. Something like this directive at the top of each module source file:

    -team("bob smith, jane doe, kim kinney").
 or
    % team: bob smith, jane doe, kim kinney
Identify the coder(s) even if you are a solo "team".

Make two modules... named "p1" and "p2" . Put your module source files into one zip file, include a README file for any comments you might want to note (as well as put your group member names in that README file), and in Canvas, submit this single zip file.





Assignment 2: Java Threads

Team work You may work in teams of 1, 2, or 3

Prepare a single zipfile that contains your source code AND a readme file containing the names of all team members.
ONE team member (doesnt matter who) will upload the zip file in Canvas on behalf of the entire team

Due: Sunday. 2/02 11:59 pm in Canvas

Using Java, and threads in Java, program a solution to the Dining Philosophers problem, a classic problem in concurrent computation. Use judicious output to show what is going on in your simulation as it executes. Make sure your solution avoids deadlocks, starvations, and race conditions.

In your readme file for the zipfile, explain your design rationale. What features and structures are you using to represent the philosophers? To represent the table, the forks, the spaghetti? To represent eating phase of a philosophers "life"... the thinking phase?

What does your algorithm do to help prevent deadlocks and starvation? Are deadlocks and/or starvations still possible (and just improbable)?




Assignment 1: OO Pillars, Models and Issues

Individual work (not teams)

Prepare a single document (PDF, or Word) that contains your answers to these discussion questions.
Then submit it in Canvas for Assignment 1 as a single PDF file.

Due: Friday. 1/24 11:59 pm in Canvas
  1. Java vs. JavaScript OO Models:
    Part A:
     -- Explain the Java Object model.  What are the main components in 
        the language for creating and managing objects. 
     -- Explain the JavaScript Object model (the older model, before
        classes were added to EcmaScript).  What are the main components in 
        the language for creating and managing objects. 
    Compare and contrast these two models.  What can we do in Java that we
    cant with JavaScript objects, and vice versa?
    
    Part B:
    for each of the 4 classical OO "pillars" show how each one is accomplished 
    or provided or enhanced in Java, and then in JavaScript.
    

  2. Research OO concepts in general. What are the failings and shortcomings of OO "stuff"?

    Discuss the objections that have been raised to using OO principles in programming. What are limitations of OO, what are areas where problems exist hindering the creation of clear, concise, well-organized, correct software systems... in essence what areas need some improvement?

    What we are after here is to have a list of issues so that -- as language designers -- we have guidance for developing new mechanisms to manage or alleviate these shortcomings.

    Note I want a discussion here, not simply a list of issues/phrases. For the objections and issues you find, explain each or give examples supporting the claims made about it.