Bits
Assignment: Bits
- Assign: Thursday 1 February
- Checkpoint: aim to complete at least 4 puzzles by the end of Wednesday 7 February
- Due: Monday 12 February
- Policy: Pair graded synthesis assignment
- Partner search: Find a partner here.
-
Code:
cs240 start bits
(if this doesn't work, usecs240.s24 start bits
) - Submit:
git commit
andgit push
your completed code. - Reference:
Contents
- Assignment: Bits
- Overview
- Setup
- Tasks
- Preparatory Exercises
- Puzzle Specifications
- Compiling and Testing
- Submission
- Grading
Overview1
This assignment requires you to solve a series of programming puzzles using only bitwise operations. Some puzzles may seem far removed from your previous programming experience, but bit manipulations like these are crucial for efficiency in essential applications such as compilers, cryptography, data compression, or encoding and decoding pictures, audio, video, and more. The puzzles will push you to think in new ways and help you internalize how computers deal with bit representations. Mind-twisters, enlightenment, and fun await!
Goals
- To understand the representation and manipulation of data as bits.
- To communicate how low-level bitwise operations relate to high-level data operations through representation.
- To master unsigned and two’s complement (signed) number representation.
- To practice using command-line tools for programming.
- To have at least one mind-blowing realization about two’s complement.
Advice
This is your first major CS 240 code assignment. It is more challenging (and fun!) than the paper exercises that precede it. Here is some advice:
-
Make you understand Assignment Zero before starting. Knowing your way around the tools will pay off now, all semester, and beyond.
-
Start early. This assignment takes considerably longer than the earlier paper exercises. Allow time to work, get stuck, sleep on it, and come back repeatedly. Any recent CS 240 alum will confirm that we are serious about starting early!
-
Prepare and plan before you code. Complete the preparatory exercises. Try some pencil-and-paper or whiteboard hacking to design your solution before you start typing C.
-
Commit and push often. Each time you get a new function working (or even just closer to working),
git add
andgit commit
your work, with a descriptive message (e.g., saying which exercise now works).
Alsogit push
your commits reasonably often. If things go wrong later, this will help you recover earlier, working versions.
Time Reports
In a past semester, according to self-reported times for a similar version of this assignment:
- 25% of students spent <= 7 hours.
- 50% of students spent <= 15 hours.
- 75% of students spent <= 20 hours.
Setup
Complete Assignment Zero to review the standard CS 240 tools before starting this assignment.
CS 240 code assignments require a CS 240 GNU/Linux computing environment.
CS 240 code assignments are designed, tested, and graded in the CS 240 GNU/Linux computing environment, since low-level system details matter in this course. We guarantee support (help with provided tools) and consistency (our grading and your testing use the same environment) only for work in a CS 240 GNU/Linux computing environment.
Get the Code
This assignment can be completed either alone or with a partner. Please see the specific directions below for each possibility.
Working Alone
To start, run cs240 start bits --solo
to
create your hosted repository and clone it to your CS account.
- As you make changes, record them with
git add
andgit commit
and submit them (or make backups) withgit push
. - The assignment manifest at the top of every assignment gives steps necessary to obtain starter code.
- The Solo Workflow summary or the full Git and CodeTub tutorial describe this process in more detail.
Working with a Partner
To start, one team member should run cs240 start bits
to create your hosted repository and clone it to your CS account. You will
be prompted to enter your teammate’s user ID. The user ID comes from the first part
of your email address. For instance, av111 in av111@wellesley.edu.
You should work together on the same computer using just one cloned repository.
This ensures that partners are brainstorming, testing, communicating,
and solving these puzzles together. However, sometimes it is helpful for each teammate
to have a copy of the code, so that you can switch which computer you are both
working on. The second teammate can later
run cs240 start bits
to get another clone of the
repository within their CS Linux account. Make sure to then enter the same
team that you did before to ensure you get the same hosted repository.
- The Team Workflow summary or the full Git and CodeTub tutorial describe this process in more detail.
Code Overview
Your repository initially contains many files. The only file that you need to inspect or edit is:
bits.c
: file where you will implement bit puzzle solutions.
The other files support for testing. You do not need to inspect them,
though you are free to do so. You will be compiling or executing them
along with your code in bits.c
. The most important ones are:
btest.c
, ‘extest.c,
dlc,
driver.pl`: testing code and tools.Makefile
: recipes to compile and execute testing code with themake
command.
Tasks
Your task is to solve the given bit puzzles and explain your
solutions. The bits.c
file contains rules, specifications, and
function templates for the programming puzzles. For each puzzle, you
must:
- Implement the function according to the specification and coding rules that are specified in the function header comments for that function.
-
Explain in one or more comments how and why your solution works.
Translating the operations into English or re-explaining the high-level specification do not suffice. You must demonstrate that you understand the link between the high-level behavior and its low-level implementation. How/why do the effects of the individual operations combine to implement the specification?
Grading considers correctness and compliance of your implementations as well as effectiveness of your explanations.
The remainder of this document describes:
- Preparatory exercises to help you review and start the assignment.
- Specifications and rules for the puzzle functions you must implement.
- Documentation of how to compile and test your implementation.
- Grading criteria.
Preparatory Exercises
CS 240 code assignments include preparatory exercises. Preparatory exercises are required, but not graded (unless otherwise noted).
Preparation is your ticket for assistance.
- You must complete the preparatory exercises (and show evidence) before asking questions about code or debugging on the main assignment.
- You may ask questions on preparatory exercises at any time.
A. Get the code (and know your tools).
Complete the setup steps above to refresh your memory of the course software tools and acquire assignment code.
B. Read the instructions.
As you read this document and the coding rules given in bits.c
,
complete these exercises to familiarize yourself with the coding
restrictions, the compilation process, and puzzle functions.
- What command should you run to compile your code?
- What command should you run to test both correctness and compliance of your solutions?
- Where are loops allowed?
- How many arguments does the
thirdBits
function take? What operators are allowed inthirdBits
?
C. Practice bitwise thinking.
-
Review the
zero.c
functions from Assignment Zero. - Complete and review the class Exercises from Data as Bits.
-
Before trying the Two’s Complement Functions, complete and review the Exercises from Integer Representation.
- Recommended: Try some practice problems from CSAPP: 2.8, 2.9, 2.14, 2.16
Puzzle Specifications
General Restrictions
All puzzle function implementations must obey the restrictive
coding rules at the top of bits.c
. Read the rules
carefully before starting – they are essential. The rules restrict
you to performing only bit-level operations on data. The purpose of
these restrictions is to force you to think about the data as bits.
Due to the restrictions, your solutions may not be the simplest or
most efficient way to accomplish the function’s goal, but the process
of working out the solution will deepen your understanding of data
as bits.
Individual Specifications
For each individual function:
- A function header comment in
bits.c
gives:- A specification of the function’s behavior.
- Some examples of the input/output behavior of the function.
These examples are coded as test cases in
extest.c
. - The set of operators allowed (a specific subset of the operators
~ & | ^ + << >> !
). - The maximum number of operations for a full score.
- An estimated difficulty rating, from low (1) to high (4)2.
- A testing harness in
tests.c
gives alternative documentation of expected behavior in terms of a reference implementation of the function
Tables below summarize the difficulty rating and description of each function.
Honor policy and [Independent] Tasks
Look over the graded synthesis assignment policy to make sure you understand how much you can discuss with other teams and the limitations on the use of external resources.
Raw Bitwise Functions
These functions do checks and manipulations on 32-bit int
values treated as bit vectors (i.e., they do not interpret the values as numbers).
Rating | Function | Short Description |
---|---|---|
1 | bitAnd | x & y using only ~ and | |
1 [Independent] | bitXor | x ^ y using only ~ and & |
1 | thirdBits | Return the int value where every third bit (including the LSB) is 1 |
2 | getByte | Extract byte n from word x |
3 | logicalShift | Logical shift x to the right by n |
4 [Independent] | bang | Compute !x without using ! |
3 | conditional | x ? y : z |
Two’s Complement Functions
These functions do checks and manipulations of 32-bit signed 2’s-complement int
values.
Rating | Function | Short Description |
---|---|---|
2 | fitsBits | Return 1 if x can be represented as an n-bit, two's complement integer |
2 [Independent] | sign | Return 1 if positive, 0 if zero, and -1 if negative |
3 | addOK | Determine if x+y can be computed without overflow |
4 [Provided Sample] | isPower2 | Return 1 if x is a power of 2, and 0 otherwise |
Compiling and Testing
There are 4 key steps for checking your work:
- Use
make
to compile your code and generate thebtest.bin
executable. - Use
btest.bin
to check your solution’s functional correctness. - Use
dlc
to check your solution’s compliance with the coding rules. - Use
driver.pl
to autograde your solution.
The dlc
and driver.pl
tools enforce strict coding rules and will
raise error messages if you have use prohibited or unsupported
code. See Common Issues if you are confused by error
messages in these steps.
Compiling: make
To build (compile) your solutions and provided testing code, type the command make
.
$ make
The make
command looks for a file called Makefile
that gives a recipe for how to compile a given executable so that you can avoid retyping long compilation commands each time you need to compile a new version. In this case, the Makefile
we provide (take a look!) uses gcc
to compile your code with testing code and produces executable files named extest.bin
and btest.bin
.
Correctness: extest.bin
and btest.bin
-
extest.bin
is a binary executable program that checks the functional correctness of the code inbits.c
on the example test cases in the function headers inbits.c
.The command
./extest.bin
will run the example test cases for on all puzzle functions.$ ./extest.bin
Don’t forget to (re-)compile a fresh version of the
btest.bin
executable each time you updatebits.c
.... edit and save bits.c ... $ make $ ./extest.bin
To simplify the recompilation process, you can instead use
make extest
as an abbreviation for the above sequence of commands. -
btest.bin
is a binary executable program that checks the functional correctness of the code inbits.c
using other testing code frombtest.c
.-
Run tests of all puzzle functions with the command
./btest.bin
, which runs the executable filebtest.bin
that was generated last time you compiledbits.c
.$ ./btest.bin
Don’t forget to (re-)compile a fresh version of the
btest.bin
executable each time you updatebits.c
.... edit and save bits.c ... $ make $ ./btest.bin
To simplify the recompilation process, you can instead use
make btest
as an abbreviation for the above sequence of commands. -
To test an individual puzzle function, e.g.,
bitXor
, pass the function name tobtest.bin
with its-f
flag:$ ./btest.bin -f bitXor
-
Optionally, test an individual function with specific arguments using the flags
-1
,-2
, and-3
to pass the 1st, 2nd, and 3rd arguments. For example, to testbitXor(7, 0xf)
, run:$ ./btest.bin -f bitXor -1 7 -2 0xf
-
Coding Rules: dlc
dlc
is a modified C compiler that can check your solution against
the coding rules.
$ ./dlc bits.c
A lack of output means your solution follows the coding rules. Error messages will appear if your solution violates the coding rules.
The -e
switch supports counting operations in a function.
$ ./dlc -e bits.c
Summary: driver.pl
The driver.pl
tool will automatically grade your solutions on correctness and performance using the dlc
and btest.bin
tools.
Points are awarded only for working solutions. The difficulty rating determines the number of correctness points available for each puzzle. Each puzzle may receive up to 2 performance points, based on the number of operations used.
Run the autograder like this (the output on our sample solution is shown below):
$ ./driver.pl
[ ... status messages omitted here ... ]
Correctness Results Perf Results
Points Rating Errors Points Ops Puzzle
1 1 0 2 4 bitAnd
1 1 0 2 7 bitXor
1 1 0 2 4 thirdBits
2 2 0 2 7 fitsBits
2 2 0 2 4 sign
2 2 0 2 3 getByte
3 3 0 2 6 logicalShift
3 3 0 2 9 addOK
4 4 0 2 6 bang
3 3 0 2 7 conditional
4 4 0 2 11 isPower2
Score = 48/48 [26/26 Corr + 22/22 Perf] (68 total operators)
If your solutions are correct, the Errors
column should show all 0’s and you score should be 48/48.
Running make driver
does this same thing as ./driver.pl
.
Common Issues
You must use a CS 240 GNU/Linux computing environment for CS 240 code assignments.
The dlc
checker enforces a stricter and older form of C declarations
than gcc
enforces. This section describes how to avoid common
issues with dlc
for the Bits assignment only. Do not
adopt these as style conventions in later assignments.
Benign Warning in std-predef.h
You may receive one warning from dlc
that you can safely ignore:
/usr/include/stdc-predef.h:1: Warning: Non-includable file <command-line> included from includable file /usr/include/stdc-predef.h.
Pay attention to other warnings and errors.
Declare Variables at the Start of the Function
In particular, in a block (what you enclose in
curly braces) all your variable declarations must appear before any
statement that is not a declaration. For example, dlc
will complain about the following code:
int foo(int x) {
int a = x;
a *= 3; /* Statement that is not a declaration */
int b = a; /* ERROR: Declaration not allowed here */
return b+2;
}
Instead, you must declare all your variables first, like this:
int foo(int x) {
int a = x;
int b;
a *= 3;
b = a;
return b+2
}
This restriction is specific to older standards for the C language,
such as that used by the dlc
checker. In future assignments, it
will best practice and good style to declare variables at the
innermost scope that is reasonable.
Avoid Binary Notation
Remember that unprefixed integer literals in C use decimal
notation. The expression 10110010
in a C program means “the int
value ten million, one-hundred ten thousand, and ten.”
The dlc
checker does not accept the 0b
prefix for numbers in
binary notation (e.g., 0b11110000
). Do not use it.
Instead, make good use of hexadecimal in this assignment: 0xF0
. Or,
for small numbers, decimal notation may work just fine.
The ishow.bin
tool lets you display integer representations and
conversions. It takes hex or decimal input.
$ ./ishow.bin 0x27
Hex = 0x00000027, Signed = 39, Unsigned = 39
There is also a corresponding fshow.bin
tool for floating point numbers.
Floating point representations are optional material in CS 240,
but feel free to play around with that tool as well if you are curious.
Avoid #include
Do not include the stdio.h
header file in your
bits.c
file, as it confuses dlc and results in some non-intuitive
error messages. You will still be able to use printf in your bits.c
file for debugging without including the stdio.h
header, although gcc
will print a warning that you can
ignore.
Submission
Before submitting, disable any diagnostic printing in bits.c
.
You will use the standard code assignment submission process for your
answers in bits.c
.
Submit: The course staff will collect your work directly from your hosted repository. To submit your work:
-
Test your
bits.c
source code file one last time using./driver.pl
(or, equivalently,make driver
). Make sure that, at a minimum, submitted source code is free of syntax errors and any other static errors (such as static type errors or name/scope errors). In other words: the code does not need to complete the correct computation when invoked, but it must be a valid program. We will not grade files that do not pass this bar. -
Use
git status
to see which files need to be added and committed. In this assignment, you should have changed onlybits.c
:[gdome@tempest bits] git status On branch main Your branch is up to date with 'origin/main'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: bits.c no changes added to commit (use "git add" and/or "git commit -a")
-
Make sure you have committed your latest changes. (Replace
FILES
with the files you changed andMESSAGE
with your commit message.)$ git add FILES $ git commit -m "MESSAGE"
In this assignment:
[gdome@tempest bits] git add bits.c [gdome@tempest bits] git commit -m "finished all bits functions" [main aa41bff] finished all bits functions 1 file changed, 3 insertions(+), 1 deletion(-)
-
Run the command
cs240 sign
to sign your work and respond to any assignment survey questions.$ cs240 sign
-
Push your signature and your latest local commits to the hosted repository.
$ git push
Confirm: All local changes have been submitted if the output of
git status
shows both:
Your branch is up to date with 'origin/main'
, meaning all local commits have been pushednothing to commit
, meaning all local changes have been committed
Resubmit: If you realize you need to change something later, just repeat the above process.
Grading
Your grade will be derived as follows:
- Correctness and performance (72 points = 1.5 × autograder score):
- Grading considers correctness and performance of all puzzle solutions.
- Tests may include new inputs that
btest.bin
does not check by default. - Solutions must comply with the coding rules as checked by
dlc
. - No credit is awarded unless the
./driver.pl
autograder can compile and run your code.
- Succinct comments explaining why each puzzle solution works (28 points):
- Grading may consider explanations for a random subset of puzzles.
- Good comments describing incomplete or non-working solutions may receive credit in this part.
Correct solutions that match or beat the operator count of the instructor’s solutions may result in prizes!
-
This document is an alternative description for the CSAPP Data Lab, which is available on the CSAPP website. ↩
-
Different people have different opinions about which puzzles are more difficult. ↩