Homework 0: Starting Up!

Due: Friday, September 13 at 23:59
First Commit: Monday, September 9 at 23:59

In this assignment you will create programs which put to use some of the starting topics in the course. You’ll also be introduced to some useful new ways of thinking about Racket code. By the end of the assignment, you will have practice with:

Homework 1 will build on the basic skills you’ve developed in this assignment.

Your implementations of the following procedures should all be placed in a single Racket file named hw0.rkt. The corresponding tests for each procedures should be in a second Racket file named tests.rkt.

The start of each file should be

#lang racket
; Your name(s) here.

Preliminaries

Before you move on, please make sure you’ve read Racket Fundamentals. The rest of Homework 0 expects that you have:

To begin the assignment, click on the assignment link. Remember you likely need to claim your identifier to link your GitHub account with your enrollment in the class.

If you’re working with a partner, one partner should create a new team. The second partner should click the link and choose the appropriate team. It’s extremely helpful for the graders if you include your name and your partner’s name in the team name. Unfortunately, you cannot use the same team name for multiple assignments. You can append the homework number to your team name if you wish.

Please don’t choose the wrong team, there’s a maximum of two people and if you join the wrong one, you’ll prevent the correct person from joining.

If you choose to work alone, you still need to create a team name.

Once you have accepted the assignment and created/joined a team, you can clone the repository on your computer by following the instructions and you can begin working. Before you do, make sure to read the entire assignment and be sure to refer to Racket Fundamentals for the coding style guide.

Part 1: GitHub Classroom Basics

To begin the homework assignment, you are going to need to have:

  1. Git installed on your computer

  2. A GitHub Account

If you have taken classes which use Git, GitHub, and/or GitHub Classroom before, you can skip to Part B. If not, please execute the steps in Part A ASAP. Ask for help if you run into issues!

Part A: GitHub Access

Why Git/GitHub Classroom?

Git very powerful for software engineers to (a) have the ability to share code across and between teams and (b) have an automatically generated record of previous versions of your files. Git, as well as other version control software like subversion, supports both of these tasks. Git is the most common version control software and developing basic Git skills is a good use of your time now.

Installing Git & GitHub Accounts

For this class, you will need Git installed before you can begin HW1 – Git is how you will download and submit your assignments. To install Git, or check if your machine has it pre-installed, follow the instructions here: https://github.com/git-guides/install-git

If this is your third CS class and/or you have not used Git before, I highly suggest using Git via GitHub Desktop or the GitHub, as it provides a graphical interface for interacting with Git. The GitHub Command Line tool is also user friendly. There is also always the option to upload files via the online interface as a backup option. This is not preferred for many reasons, especially use caution if you are working with a partner!

GitHub is an online service which hosts Git repositories – we will be using GitHub Classroom in this class.

If you don’t already have a GitHub account, please make one. As a student, you can get additional GitHub benefits such as unlimited private repositories here, but you don’t need to for this course. I suggest using your Oberlin .edu email address and a username that contains part of your name - for instance, mine is “mollyfeldman”. Students use their GitHub accounts long after this course, so a professional identifier is a good recommendation for longevity! All of your repositories for this course will be private to you, your partner (if you have one), and course staff.

When you start an assignment in GitHub Classroom for the first time you’ll be asked to Join the Class and claim an identifier. The identifiers are Last/Family Name. Please make sure you only claim your own identifier and not someone else’s!

Part B: Accessing Starter Code

Now that you have GitHub setup and have practiced using it, you can start Homework 0. Each homework begins with a distinct assignment link - https://classroom.github.com/a/kt4CShCU is the link for Homework 0.

A reminder that the first time you join GitHub Classroom you’ll be asked to Join the Class and claim an identifier. The identifiers are Last/Family Name. Please make sure you only claim your own identifier and not someone else’s!

Part C: How to Submit your Homework with Git/GitHub Classroom

To submit your homework, you must commit and push to GitHub before the deadline.

Your repository should contain the following files:

It may also include a .gitignore file which tells Git to ignore files matching patterns in your working directory.

Any additional files you have added to your repository should be removed from the main branch. (You’re free to make other branches, if you desire, but make sure main contains the version of the code you want graded.)

Make sure you put your name (and your partner’s name if you’re working with one) as a comment at the top of each file.

Finally, prior to submitting all assignments make sure that you have properly completed your Honor Code attestation in HONORCODE.md.

Part 2: First Programs

  1. (13 points) hw0.rkt contains a definition for implementing len on a list in Racket. Think through the edge cases and typical use cases for len. Your goal is to add tests to tests.rkt which fully test all possible valid lists that could be passed to this implementation.

    Think really critically about the tests – specifically, think about tests structurally rather than with specific values.

    Look in tests.rkt for example tests and the length-tests test suite. For each procedure, we define a test suite (using define as normal)

    (test-suite name test...)
    

    where name is the name of the test suite and it’s followed by any number of tests.

    We can create a test which tests whether an expression returns #t or #f using test-true or test-false. We can use test-equal? to test outputs that are not Booleans.

    • (test-true test-name exp)

    • (test-false test-name exp)

    • (test-equal? test-name exp expected-output)

    At the bottom of tests.rkt, there’s a definition for an all-tests test suite which, when we’re finished will consist of all of the test suites for the procedures you’re writing. And finally (run-tests all-tests). After you’ve written the tests, click the Run button in DrRacket with tests.rkt open and you should see a message telling you all your tests have passed or that some have failed.

    1 success(es) 0 failure(s) 0 error(s) 1 test(s) run
    

    Add your new tests for len to the length-tests test suite.

  2. (15 points) Write a procedure arith which takes a number n as input and evaluates to a number according to the following requirements:

    • If n is greater than or equal to 10 and even, return n + 2
    • If n is greater than or equal to 10 and odd, return n
    • If n is less than 10 and even, return n * 5
    • If n is less than 10 and odd, return n + n

    I’d suggest that you use at least one cond for this implementation rather than only if statements.

    Add 5 tests to a new test suite arith-tests in tests.rkt to test your implementation.

    (define arith-tests
      (test-suite
      "arith"
      ...
      ))
    

    Try to think of all the possible edge cases (e.g., negative numbers).

    Add your new test suite to the all-tests test suite.

    (define all-tests
      (test-suite
      "All tests"
      length-tests
      arith-tests))
    

Click the Run button to make sure all your tests pass. After running the tests, you can run (test/gui all-tests) in the interpreter to get a graphical version of the output. Give this a try - I definitely find it helpful when there are numerous failing tests.

End of Part 2

Congratulations, you’ve now written Racket! Make sure that for each procedure you have implemented, you have created a test suite and added it to the all-tests test suite. Make sure your tests are (a) running and (b) passing. How can you check if your tests are running? Easy! For each test suite you wrote, pick one of your tests and change it so that the test itself is wrong. Then, when you run the tests, you should get a failure. Don’t forget to change your test back to the correct version!

If you haven’t already done so recently, now would be a great time to commit all of your code and push it to GitHub. Recall that you need to first add the files, commit them, and then push.

If you’re using command line git, the commands would be:

$ git add hw0.rkt tests.rkt HONORCODE.md
$ git commit
$ git push

When you push your code to GitHub, your test suite will be run. While the tests are running, if you go to the GitHub page for your repository: https://github.com/oberlin-cs275/YOUR_REPO, you’ll see a small yellow circle status icon in the header above your list of files.

Once the tests complete, the icon will change to a red ❌ if at least one test failed and a green ✓ if all tests pass.

You can click on the status icon to see more details.

Part 3: Racket Exploration

  1. (8 points) Some versions of Scheme have a primitive procedure atom? that returns #t if its argument is an atom and #f if it isn’t; this isn’t built into Racket. Since Racket has primitive procedures pair? and null? that returns #t if their argument is a cons pair (such as a nonempty list) or null, respectively, we can easily write atom?. Every expression is an atom, a pair, or null. Use this to define procedure atom? in hw0.rkt. Here is some test data:

    • (atom? 3) returns #t

    • (atom? #f) returns #t

    • (atom? '(1 2)) returns #f

    • (atom? null) returns #f

    • (atom? (cons 5 10)) returns #f

    Add at least 3 tests to a new atom?-tests test suite in tests.rkt.

  2. (8 points) Write a procedure all-atoms? that takes an argument and returns #t if the argument is either an empty list or a list where every element is an atom.

    Define a new test suite to test all-atoms? in tests.rkt.

    (define all-atoms?-tests
      (test-suite
       "all-atoms?"
       (test-true "Empty list"
                  (all-atoms? empty))))
    

    Add at least two more tests to this test suite. Try to think of all the possible edge cases (e.g., empty lists and lists containing a single element). Make sure to test cases that return #t and cases that return #f.

  3. (8 points) Write a procedure not-all-atoms? that returns #t if its argument is not a list of atoms. Of course, you could write this as

    (define (not-all-atoms? lst)
      (not (all-atoms? lst)))
    

    but don’t do that. Instead, write it directly using cond. You can assume that the input to this procedure is a list.

    Define a new test suite not-all-atoms?-tests with at least three tests. Make sure to add that test suite to all-tests. Make sure to test cases that return #t and cases that return #f.

  4. (8 points) Write the procedure all-ints? that returns #t if its argument is the empty list or if it’s a list where every element is an integer. You can use integer? to test if something is an integer. Write at least three tests. Make sure to test cases that return #t and cases that return #f.

Common Questions

Finishing up

Make sure you wrote tests of all of these, the test suite for each procedure is included in the all-tests test suite, and your tests pass.

Once you have finished (or better yet, frequently as you’re working), you need to push your code to GitHub since this is what we’ll use for grading. So double check that you’ve included your name and the name of your partner (if you’re working with a partner) in all files and git add/commit/push.

$ git add hw0.rkt tests.rkt HONORCODE.md
$ git commit
$ git push