Homework 6
Last updated: Mon, 24 Mar 2025 11:50:55 -0400
Out: Tue Mar 11 2025, 11am EST
Due: Tue Mar 25 2025, 11am EST (after Spring Break)
Overview
In this assignment, you will continue to practice using the The Design Recipe to write programs that compute with lists.
This hw will be graded accordingly:
correctness (autograder) (10 pts)
design recipe (20 pts)
testing (16 pts)
style (8 pts)
README (2 pt)
Setup
Create a new repository for this assignment by going to the CS450 Spring 2025 GitHub Organization and clicking "New".
Note: The CS450 Spring 2025 GitHub Organization must be the owner of the repository. Do not create the repository in your own account.
On the "Create a new repository" screen:
Name the repository hw<X>-<LASTNAME>-<FIRSTNAME> where <X> is the current homework number.
For example, I would name my hw6 repository hw6-Chang-Stephen.
Mark the repository as Private.
Check "Add a README file".
Select the Racket template for the .gitignore.
Choose whatever you wish for the license.
When done click "Create repository".
Tasks
In this assignment, we will write several list-processing functions that may be helpful for the game we’ve been implementing.
For this assignment, you may use map, filter, foldr, foldl, or any other build in list function except for sort.
(Note that no solution to previous hws are needed to complete this assignment. In fact, since this assignment requires new data definitions, it is recommended that all students start from scratch, even those who completed previous ones. Trying to "adapt" a previous solution will likely be the more error-prone path, so do so at your own risk.)
Also, you will not need big-bang in this assignment. Though this assignment does not require using big-bang, here is an online demo that uses the functions from this assignment, in combination with the ones from previous assignments.
Reading
Read Chapters 14-16 of the Textbook (where reading means working through the examples and exercises interactively).
Review the The Design Recipe section of the course website for new elements of the design recipe that we have learned.
Pre-programming Notes
- All code must be written following the The Design Recipe. (Just submitting code is not sufficient.) In additional to the required receipe steps, some language features may only be used in the certain scenarios, as called for by The Design Recipe.
For example, set! and other "imperative" features are not allowed ever.
NEW: Each function is allowed one if expression, to "process" a piece of Boolean data, in addition to another kind of data, e.g., a WorldState. (Conditionals such as cond remain restricted to Data Definitions.)
Signatures should use define/contract and the predicates defined in the Data Design Recipe step. If a function is defined with define/contract and it’s clear which data definitions its contract refers to, then comment signatures no longer need to be submitted with code. NEW: The listof contract constructor may be useful to use with functions that process list inputs.
For Examples and Tests, do not use check-expect from the Beginning Student Language (even though the textbook says to). Instead, use check-equal? or other testing forms from rackunit.
Examples for a function definition should be right after the define. But Tests should be put into the test-suite in tests.rkt. Try to think about corner cases and code coverage. Each function should have at minimum one Example, and "sufficient" Tests.
Tests should go in a tests.rkt file, as described in lecture and the hw6 starter code, and the rest of the code should go in a file named hw6.rkt.
The submitted program must be only a series of defines (both constants and function definitions are allowed). It should not run any code (e.g., it should not start the big-bang loop automatically!). Not following this will result in GradeScope errors and/or timeouts.
You may look at lecture code to help you but DO NOT SUBMIT ANY OF THIS CODE (even if you change the variable names, etc). You won’t receive any credit. Instead, you should write code for this homework from scratch using The Design Recipe.
NEW: One-line helper functions—
if the name and description clearly describe what it does (the course staff is the final arbiter of this)— do not need to be submitted with Examples and Tests, if they are covered by other tests. NOTE: This does not change the Design Recipe. It is only changing submission requirements. As usual, however, we will not be able to debug code that does not follow the design recipe, so omit these steps at your own risk. struct instances, e.g., for WorldState data, must be comparable with equal? and check-equal?, which means that they should be declared with the #:transparent keyword.
Programming
- In this assignment:
a UNIT is 40 pixels,
the WIDTH of a row is 10 UNITs.
the HEIGHT of all possible rows is 20 UNITs
a J-block and its rotation point and ROTATION1 state use their definitions from previous assignments.
- a Data Definition named Block that represents a J-block. The design details are your choice, so long as you follow all the Data Design Recipe steps and define and provide the functions below.
a mk-Block function that takes a big-bang x and y coordinate representing a block rotation point, and a RotationState (the data definition from Homework 4), and returns a Block at the given coordinates in the specified RotationState
a Block? predicate that returns true when given a valid Block data value (if Block is compound data, then this should be a shallow check that does not check the fields),
- a Data Definition named 1Block that represents a \texttt{UNIT}\times\texttt{UNIT} square block. The design details are your choice, so long as you follow all the The Design Recipe steps, and define and provide the functions below.
mk-1Block : takes an x and y that is the block center, and a color that satisfies the 2htdp/image image-color? predicate, and returns a 1Block
1Block-x : takes a 1Block and returns its center x
1Block-y : takes a 1Block and returns its center y
1Block-color : takes a 1Block and returns its
Block->1Blocks : converts a Block into an equivalent Listof<1Block>
1Block-image : takes a 2htdp/image image-color? value and returns a 1Block image of that color.
1Blocks->scene : takes a Listof<1Block> and returns a (2htdp/image image?) of the blocks inserted into an empty-scene at their coordinates
1Blocks-top : takes a Listof<1Block> and returns the y coordinate of the top of the "highest" 1Block in the list
adjacent? : predicate that takes two 1Blocks and returns true if the first one is immediately on top of the second one, with one touching edge. Note: this function will need to use a Multi-argument Template that processes both Blocks simultaneously.
adjacent-to-1blocks? : predicate that takes a 1Block and a Listof<1Block>, and returns true if the first argument 1Block is adjacent? to any of the 1Blocks in the given list.
block-adjacent-to-1blocks? : predicate that takes a Block and a Listof<1Block>, and returns true if the Block is adjacent? to any of the 1Blocks in the given list. Hint: you might want to use the Block->1Blocks that you wrote.
sort-1Blocks : takes a Listof<1Block> and sorts the 1Blocks in descending order according to their y coordinates. This function should implement a functional quicksort as introduced in lecture and thus needs to follow the Generative Recursion Recipe.
shift-down : takes a Listof<1Block> and shifts each block "down" by UNIT pixels.
no-duplicates? : predicate that takes a Listof<1Block> and returns true if none of the list elements have the same x coordinates
same-row? : predicate that takes a Listof<1Block> and returns true if all the 1Blocks have the same y coordinate.
- full-row? : predicate that takes a Listof<1Block> and returns true if the given list constitutes a "full row", where the criteria for this is as follows:
must have length = WIDTH = 10
must all have the same y coordinates
cannot have any duplicate y coordinates x coordinates
You should probably use other predicates you’ve defined above in the implementation of this function. a function prune-rows that takes a Listof<1Block> and removes full rows (i.e., satisfies the full-row? predicate) by checking every WIDTH window of consecutive elements in the list. When the function finds a full row, it should remove it so that the output is a Listof<1Block> that has no full rows. Further, when a full row is removed, the 1Blocks "above" it (i.e., have smaller y coordinate) should "fall down" (you may find your shift-down function useful here).
To make writing this function easier, you may assume the input list is sorted in descending y coordinate order. Other functions you may find useful are the take and drop list functions.
Finally, this function will need to use Generative Recursion so make sure to follow the recipe steps.
Before Submitting
Testing (and Autograders)
Before submitting, note:
Do not submit until all code has been thoroughly tested (by you), which means writing a "sufficient" number of Test cases.
A GradeScope "Autograder" may or may not be released before the due date but either way, an Autograder is not a software development/testing tool, so do not use it as one. Code must be tested independent of any Autograder and questions about Autograders will be ignored (e.g., posts asking "why is the Autograder giving an error?" are not allowed)
If you do submit before the deadline and get an Autograder error, this is bonus information that indicates the submitted code is not complete and/or not correct. But it’s up to you to figure out what "correct" means and how to fix to the program.
Of course, the course staff is here and eager to help, but cannot do so without context information. The best way to supply this information is to INCLUDE EXAMPLES WITH ALL QUESTIONS, along with what the "expected" result should be! The posted examples should be the minimal amount of code needed to communicate the problem. This will receive the clearest possible answer.
The Autograder test suite is subject to change. This means that the visible grade seen during submission is not the final grade.
Style
All code should follow proper Racket Style.
Also, the repository itself must follow proper style. Specifically, it must have appropriate commit messages. See How to Write a Git Commit Message if you are unsure how to write a commit message.
Files
A submission must have the following files in the repository root:
hw6.rkt: Contains the hw solution code.
All defines should use the name specified in the exercise (ask if you are unsure) and should be provided.
The easiest (but not always the most readable) way to ensure all necessary definitions are provided is to (initially) put as the second line in the file:
This automatically provides all definitions in the file (the first line should be #lang racket).
tests.rkt: This file should require hw6.rkt and define tests for it.
Specifically, it should define a rackunit test-suite named TESTS which contains "sufficient" rackunit Test cases (e.g., check-equal?, etc.) for each defined function.
README.md: Contains the required README information, including the GitHub repo url.
Submitting
When you are done, submit your work to Gradescope hw6. You must use the "GitHub" Submission Method and select your hw<X>-<LASTNAME>-<FIRSTNAME> repository.
Note that this is the only acceptable way to submit homework in this course. (Do not manually upload files and do not email files to the course staff. Homework submitted via any unapproved methods will not be graded.)