UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ CS2613 Labs

Labs

Lab 1

Before the lab

Before every lab in this course, you will be given tasks to complete. These will generally be easy tasks like watching videos, but you need to complete them in order to keep up with the class.

Command Line Familiarity Check

  1. In an FCS linux lab (remote or locally) log in, and open a terminal.

  2. Make a directory

  3. Create a file in that directory using one of the available text editors

  4. Now clean up, removing the file and the directory.

If any of this was new to you, then please take the time to go through parts 1 to 5 of the Learning the Shell Tutorial.

Read the course syllabus.

The Course Syllabus is available on line. Please read it, and bring any questions you have about it to the first lab.

Background Reading

For every lab there will be some related reading. I'll point these out as we go through the lab, but I'll also collect them at the start of the lab in case you want to get a head start (or refer back to them later).


About the course

Time
10 minutes
Activity
Q&A, discuss course syllabus.
  1. What's similar to other CS courses you've taken?

  2. What's different?

  3. Key point, how are labs evaluated?

Getting started with racket

  1. Open a terminal.

  2. Make a directory called cs2613 that will keep all of your work (note that case and spaces matter in Linux and this is not the same as CS2613 or CS 2613. For the rest of this course we will assume it is directly under your home directory. The shortcut ~/cs2613 will refer to this directory in the lab texts and in the shell.

Hello Racket World

Time
20 Minutes
Activity
Group walkthrough
  • Open a terminal

  • Make a directory ~/cs2613/labs/L01 (if it does not already exist) and change there with cd

  • Save the following code to ~/cs2613/labs/L01/hello.rkt

#lang htdp/bsl
"hello world"
(* 6 7)

Command Line

  • run the program with

      $ racket hello.rkt
    
  • What is the difference between the first and second line of output?

  • compile the program

      $ raco make hello.rkt
    
  • run the program again

      $ racket hello.rkt
    
  • can you tell any difference? (hint, consider the "time" command).

DrRacket: A Racket Specific IDE

  • Start DrRacket from the activities menu

  • Referring to the DrRacket documentation as needed, open and run the hello.rkt program from the previous part.

  • What is the meaning of the first line of the file?

Setting up a git repo

Time
20 minutes
Activity
Individual work
Summary
This is where we create the git repository used for the rest of the term to hand things in.
  1. Change to ~/cs2613. This directory should have one subdirectory called labs, which has the results of our experiments with racket.

  2. Create the git repository

     $ git init -b main
    

    Git will reply with something like

     Initialized empty Git repository in /home1/ugrads/$username/cs2613/.git/
    

    You’ve now initialized the working directory — you may notice a new directory created, named ".git". You should mentally replace "$username" with whatever the login name is that you use to log into the FCS linux machines.

  3. Read the git-quickref page, and follow the initial configuration steps there.

    • note that the "--wait" option for gedit is important here.
  4. Next, tell Git to take a snapshot of the contents of all files under the labs, with git add:

    $ git add labs
    
Notes
Many revision control systems provide an add command that tells the system to start tracking changes to a new file. Git’s add command does something simpler and more powerful: git add is used both for new and newly modified files, and in both cases it takes a snapshot of the given files and stages that content in the index, ready for inclusion in the next commit.

This snapshot is now stored in a temporary staging area which Git calls the "index". You can permanently store the contents of the index in the repository with git commit:

   $ git commit

This will open and editor and prompt you for a commit message. Enter one and exit the editor. You’ve now stored the first version of your project in Git. See §5.2 of Pro Git for some hints about writing good commit messages. As mentioned in the class git policy, you will be marked on your commit messages, so you may as well get started with good habits.


Pushing to a central repo

Summary
Learn how to upload your work to a server
Time
20 minutes
Activity
Individual work
Notes
You absolutely have to understand this before continuing in the course, since all marks in the course will be based on work pushed to the coursegit repos.

Since we are using the FCS git repositories there is an existing repository for all students who registered early enough. If it turns out there is no repository for you, you may need to do the last step later.

  • First add the remote. This something like a nickname for the URL where the repo will be stored.

      $ git remote add origin https://$username@vcs.cs.unb.ca/git/cs2613-$username
    

    origin is the default name for a remote, but we could have used a different name here. Replace $username with your FCS Linux account name.

  • Now upload your local copy of the repo.

      $ git push --all origin
    

    you should see something like

              Counting objects: 388, done.
              Delta compression using up to 8 threads.
              Compressing objects: 100% (350/350), done.
              Writing objects: 100% (388/388), 71.63 KiB | 0 bytes/s, done.
              Total 388 (delta 223), reused 59 (delta 33)
              To https://$username@vcs.cs.unb.ca/git/cs2613-$username
                 e7e5311..f1ae959  main -> main
    

Git Tutorial Continued

Making Changes in git

Time
15 minutes
Activity
Individual work
Summary
Get some practice commiting your changes to git.

Change to the root of your git repository (~/cs2613). Start by finding the right files to edit with

$ git grep hello

git grep is a very useful (and fast!) tool to find occurrences of strings in your git repository. Notice in the output there are some Binary files created by racket; we will clean those up later.

Edit the non-binary (source code) file, and change the output message.

Use git add to stage your changes:

$ git add file1 

(replace file1 with the actual file you modified). You are now ready to commit. You can see what is about to be committed using git diff with the --cached option:

$ git diff --cached

or $ git diff --cached --stat

To undo the effect of a git add command, run git reset.

(Without --cached, git diff will show you any changes that you’ve made but not yet added to the index.) You can also get a brief summary of the situation with git status:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
#

The git-rubric requies to begin the commit message with a single short line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git.

If you need to make any further adjustments, do so now, and then add any newly modified content to the index. Finally, commit your changes with:

$ git commit

This will again prompt you for a message describing the change, and then record a new version of the project.

Alternatively, instead of running git add beforehand, you can use

$ git commit -a

which will automatically notice any modified (but not new) files, add them to the index, and commit, all in one step. Keep in mind that you will be marked on the logical structure of your git commits, so you are better off using git add to explicitely choose what changes to commit.

Cleaning up generated files

Time
15 minutes
Activity
Individual work
Summary
Get some practice commiting your changes to git.

A common phenomenon in software development is the existence of generated files. These files are created by some tool, typically based on some source files. In general it is a bad idea to track generated files in version control because they introduce spurious changes into history. We'll look at this more later, but for now let's try to clean up. We can often find what files are generated by re-running the build process. In our case

$ cd ~/cs2613/labs/L01
$ raco make hello.rkt

To find out what changed, run

$ git diff --stat

All going well, you will two modified files. You can delete them using git rm. As with with other changes, you can preview your changes with git diff and git status.

When you are satisfied with the changes, run git commit.

Before next lab

Lab 2

Before the lab

Background


Viewing project history

Time
15 minutes
Activity
Small group discussion, presenting work to the group, peer feedback
Summary
Reinforce idea of commit message quality
  1. At any point you can view the history of your changes using

     $ git log
    

    Use this command to verify that all the changes you expected to be pushed to the server really were.

    If you also want to see complete diffs at each step, use

     $ git log -p
    

    Often the overview of the changes is useful to get a feel for each step

     $ git log --stat --summary
    
  2. In most projects, you have to share commit messages to (at least) the same people who view your source code. Share your "best commit" message with one or more of your neighbours.

  3. Find something positive to say about the other commit messages you are reading.

  4. Find a constructive improvement with one of the other messages. Don't be mean, people have varying levels of experience with this.

Racket

Racket Expressions.

Time
20 minutes
Activity
Small groups
#lang htdp/bsl
(define y 18)
(define (t1 x)
  (or (= x 0) (< 0 (/ y x))))
(define (t2 x)
  (or (< 0 (/ y x)) (= x 0)))
(define (t3 x)
  (and (= x 0) (< 0 (/ y x))))
(define (t4 x)
  (or (< 0 (/ y x)) (not (= x 0))))

Racket functions

Time
20 minutes
Activity
Individual work
(check-expect (middle-of-three 1 2 3) 2)
(check-expect (middle-of-three 2 1 3) 2)
(check-expect (middle-of-three 1 3 2) 2)

The DrRacket stepper

Time
25 minutes
Activity
Individual work

Test Coverage

Time
25 minutes
Activity
Individual work

Unit testing is an important part of programming, and has inspired something called test driven development.

Before Next Lab

Assignments

Reading

Lab 3

Before the lab

Assignments

Reading


Q&A

Time
5 Minutes
Activity
Group discussion

Setup


Semantics

Time
25 minutes
Activity
Small Groups
Summary
new evaluation rules for and and or

As you read in FICS unit 3, we can understand evaluation ("running") of Racket programs as a sequence of "reductions" or "substitutions". These rules are similar to the reduction steps in the DrRacket stepper.

The stepper uses the following rules for and and or (notice that these rules enforce short circuit evaluation)

(and true exp2 ...) => (and exp2 ...)
(and false exp2 ...) => false
(or true exp2 ...) => true
(or false exp2 ...) => (or exp2 ...)
(and) => true
(or) => false

Following Exercise 7, write a new set of rules that requires at least two arguments for and and or. The rules are for human consumption; you can write them as comments in DrRacket. You can write "exp1 exp2 ..." to mean at least 2 expressions.

Discuss your answers with a your group, and try a couple evaluation small examples by hand using your rules.

Simulating Natural Numbers I

Time
25 minutes
Activity
Individual work
Summary
Learn about structures and recursion.

Write the times function from Exercise 11 in FICS. You can (and should) use the following code from the linked discussion

#lang htdp/bsl
(define-struct Z ())
(define-struct S (pred))
(define (pred nat)
  (cond
    [(Z? nat) (error "can't apply pred to Z")]
    [(S? nat) (S-pred nat)]))

(define (plus nat1 nat2)
  (cond
    [(Z? nat1) nat2]
    [(S? nat1) (make-S (plus (S-pred nat1) nat2))]))

Here is the template for structural recursion on (simulated) natural numbers. See the linked text (or the plus function just above) for how to add a second "carried-along" parameter.

(define (my-nat-fn nat)
  (cond
    [(Z? nat) ...]
    [(S? nat) ... (my-nat-fn (S-pred nat)) ...]))

Here are some tests to get you started. As always, try to have as complete test coverage as possible. Depending on how you choose the language in DrRacket, the line (define-struct S (pred)) may show partial coverage; you can ignore this for this lab.

;; 0 * 0 = 0
(check-expect (times (make-Z) (make-Z)) (make-Z))
;; 0 * 1 = 0
(check-expect (times (make-Z) (make-S (make-Z))) (make-Z))
;; 2 * 1 = 2
(check-expect (times (make-S (make-S (make-Z)))
                       (make-S (make-Z)))
              (make-S (make-S (make-Z))))

You may find it helpful to refer back to your solution from L02.

Simulating Natural Numbers II

Time
30 minutes
Activity
Individual work
Summary
Learn about structures and recursion.

Write the compare function from Exercise 11 in FICS. Your function compare should use the struct definitions Z and S, and pass the following tests

;; 0 = 0
(check-expect (compare (make-Z) (make-Z)) 'equal)
;; 0 < 1
(check-expect (compare (make-Z) (make-S (make-Z))) 'less)
;; 1 > 0
(check-expect (compare (make-S (make-Z)) (make-Z)) 'greater)
;; 2 > 1
(check-expect (compare (make-S (make-S (make-Z)))
                       (make-S (make-Z))) 'greater)

Before Next Lab

Reading

On your own

Time
20 min
Activity
Independent research

See if you can come up with answers to the following questions for next time.

  • The programming languages we will study this term are mainly dynamically typed. This means that not only the value but also the type of variables can change at runtime. Why does this make testing even more important?

  • What kind of software problems is testing not well suited to find?

  • Why might mutable state (e.g. instance variables in Java) make writing unit tests harder?

Lab 4

Before the lab

Reading

On your own

Time
20 min
Activity
Independent research

See if you can come up with answers to the following questions for next time.

  • The programming languages we will study this term are mainly dynamically typed. This means that not only the value but also the type of variables can change at runtime. Why does this make testing even more important?

  • What kind of software problems is testing not well suited to find?

  • Why might mutable state (e.g. instance variables in Java) make writing unit tests harder?


Questions from last time

Time
10 Minutes
Activity
Group discussion

Setup

Structural recursion, on numbers

Time
20 minutes
Activity
Individual work
Summary
Learn about structural recursion.

Use structural (note that structural here is only indirectly related to Racket structs) recursion on natural numbers (not the simulated ones from above, but regular Racket numbers like 1, 42, and 1337) to define a function (sum-factors n max-factor) that sums all factors of n (including 1) no larger than max-factor

Recall the template for structural recursion on natural numbers:

(define (my-nat-fn n)
  (cond
    [(zero? n) ...]
    [(positive? n) ... (my-nat-fn (sub1 n)) ...]))

Try to use only one recursive call to sum-factors like in the template. Keep in mind that the n in the template might be a different parameter of your function. You can use the builtin function remainder to test for divisibility.

The following tests should pass

;; 1+2+3 = 6
(check-expect (sum-factors 6 5) 6)
;; 1+2+4+7+14 = 28
(check-expect (sum-factors 28 27) 28)

Substitute in a list

Time
25 minutes
Activity
Individual work
Summary
Learn about lists and recursion.

Complete FICS Exercise 13.

Note the template for structural recursion.

(define (my-list-fn lst)
  (cond
    [(empty? lst) ...]
    [(cons? lst) ... (first lst) ...
                 ... (my-list-fn (rest lst)) ...]))

Here is a test case based on the linked test

(check-expect
 (substitute 3 "three" (list "four" 3 4 "three" 3))
 (list "four" "three" 4 "three" "three"))

Uniquifying lists

Time
25 minutes
Activity
Individual work
Summary
Learn about lists and recursion.

Complete FICS Exercise 15. Although probably not intended by the original question, use the built-in BSL function member? to simplify your solution. Otherwise use only the constructs specified in Exercise 14, and structural recursion. Here is one test case derived from the linked text.

(check-expect
 (unique-right
  (list 1 4 2 1 5 4))
 (list 2 1 5 4))

Add an element to all lists

Time
25 minutes
Activity
Individual work
Summary
Learn about lists and recursion.

Recall the template for structural recursion on lists

(define (my-list-fn lst)
  (cond
    [(empty? lst) ...]
    [(cons? lst) ... (first lst) ...
                 ... (my-list-fn (rest lst)) ...])

Use this template to write a function cons-all that adds a given element to the front of each given sublist. This is related to FICS Exercises 23-25 (but you only need to write cons-all, not do those exercises).

The following test case illustrates the use of cons-all. You will need to use the language #lang htdp/bsl+ or "Beginning Student with List Abbreviations" or replace the use of ' in the following.

(check-expect (cons-all 3 '((2 4) () (5)))
              '((3 2 4) (3) (3 5)))

Before Next Lab

Lab 5
Lab 6
No lab: Truth and Reconciliation Day
Lab 7 / Racket Quiz
Lab 8
No lab: Thanksgiving Day
Lab 09
Lab 10
Lab 11
Lab 12
Lab 13 / JS Quiz
Lab 14
Lab 15
No lab: Reading Week
No lab: Reading Week
Lab 16
Lab 17
Lab 18 / Python Quiz
Lab 19
Lab 20
Lab 21
Lab 22
Lab 23