Bits
Assignment: Bits
- Assign: Thursday 15 September
- Checkpoint: aim to complete at least 5 puzzles by the end of Monday 19 September
- Due: Thursday 22 September
- Policy: Pair graded synthesis assignment
- Partner search: Find a partner here.
-
Code:
cs240 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 cryptography, data compression, or encoding and decoding pictures, audio, video, and more. The puzzles will push you to think in new ways and 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 number representation.
- To become comfortable with basics of the C programming language.
- 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 240 code assignment. It is more challenging (and fun!) than the paper exercises that precede it. Here is some advice:
-
Complete 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. Alsogit push
your commits reasonably often. If things go wrong later you can always recover your work.
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 <= 9 hours.
- 75% of students spent <= 12 hours.
Setup
Complete Assignment Zero to learn 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
Each student is provided with a bits
repository hosted on the
CS 240 repository server. This repository contains starter
code and is where you will submit your work for the assignment.
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, adavis15 in adavis15@wellesley.edu.
It is strongly recommended that you 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 teammates to
work separately and then come together later to discuss. For the partner who did run the
above setup, that person can also get a cloned copy of the same repository. Simply
run cs240 start bits
. Make sure to enter the same
team that you did before to ensure you get the same hosted repository.
- Important: You may have created a bits repository in lab that was either a solo
repository or a repository with a different partner. This is okay. Simply give the old
repository a different name using the
mv
command. For instance,mv bits bits_lab
. Note this command assumes you are in the same directory as your bits repository. Then simply run the steps above using your new teammate. - 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 running them
along with your code in bits.c
. The most important ones are:
btest.c
,dlc
,driver.pl
: testing code and toolsMakefile
: recipes to compile 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.
-
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 should make the notion of data as bits
completely clear.
Individual Specifications
For each individual function:
- A function header comment in
bits.c
gives:- a specification of the function’s behavior
- the set of operators allowed (a specific subset of the operators
~ & | ^ + << >> !
) - the maximum number of operations allowed
- a rough difficulty rating, from low (1) to high (4)2
- A testing harness in
test.c
gives alternative documentation of expected behavior:- test cases (arguments and corresponding expected return values)
- an unrestricted reference implementation of the function
Tables below summarize the difficulty rating and description of each function.
[Independent] Tasks
Tasks marked [Independent] must be completed without assistance from others.
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 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 an executable file called btest.bin
.
Correctness: btest.bin
btest.bin
is a binary executable program that checks the functional
correctness of the code in bits.c
using other testing code from btest.c
.
Run tests of all puzzle functions with the command ./btest.bin
,
which runs the executable file btest.bin
that was generated last time
you compiled bits.c
.
$ ./btest.bin
Don’t forget to (re-)compile a fresh version of the btest.bin
executable each time you update bits.c
.
... edit and save bits.c ...
$ make
$ ./btest.bin
To test an individual puzzle function, e.g., bitXor
, pass the
function name to btest.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 test bitXor(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 (part of the output on our sample solution is shown):
$ ./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)
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
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
.
Submit: The course staff will collect your work directly from your hosted repository. To submit your work:
-
Test your source code files one last time. 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.
-
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"
-
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 this 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. ↩