CSCI 2330
Introduction to Systems

Bowdoin College
Spring 2016
Instructor: Sean Barker

Project 1 - A Bit Puzzling

This project should be completed individually.

This project is designed to make you more familiar with the bit-level representations of data used by computers. At the same time, you will become well-acquainted with the bitwise manipulations available in many languages (like C). You will do this by solving a series of (fun, enlightening, and challenging!) programming puzzles in C.

Start by reading through the entire project description, particularly the advice section!

Project Overview

In this project, you will modify a single C source file, puzzles.c, which is included in the starter files. This file contains the skeleton for a set of 15 programming puzzles. Each puzzle is a function which should compute a simple operation (e.g., returning whether a given number is positive or negative). Your task is to complete each function using a highly restricted subset of the full C language. In particular:

Exception: For floating-point puzzles, you do not need to adhere to the restrictions on branching, looping, constants, or operators, and you may use both int and unsigned types (but no floating-point types). Other restrictions still apply (e.g., no function calls).

In order to solve the puzzles while following the rules above, you will need to have a clear understanding of data representations and be clever about using bitwise operators!

Puzzle Information

Puzzles may make use of either raw bitwise values (i.e., bits not interpreted as numbers), integers, or floating-point numbers. Integers use a 2's complement representation and floating point numbers use the standard IEEE floating point representation discussed in class.

Each puzzle is assigned a difficulty rating from 1 to 4 reflecting the relative complexity of that puzzle (1 = least complex). Puzzles with the lowest rating may be straightforward given a bit of thought. Harder puzzles are almost certainly not, and will require a non-trivial amount of thought, experimentation, and possibly pen-and-paper exploration!

In addition to your code implementing each puzzle, you must provide explanations (via comments embedded in puzzles.c) of how and why each of your solutions works. Your comments must go beyond a simple translation of the bitwise operations you used. Rather, your comments must clearly demonstrate that you understand why (as opposed to simply how) your solution works.

In some cases, your comments may end up exceeding the length of your code (though this is not strictly a requirement). Do not neglect your explanations, as they will factor significantly into your project grade.

Complete reference implementations of the puzzles are provided in tests.c that make use of the entire C language. Refer to these if you have any question about how a given function is supposed to behave. Of course, given that these implementations do not have any restrictions, they are not likely to be especially helpful when writing your functions.


Checking your puzzle solutions can be tricky. Luckily, you will have a couple of useful tools at your disposal.

ishow: Integer Representations

The ishow utility accepts an integer input (either in decimal or hex format) and outputs its signed, unsigned, and raw-bit (in hex) equivalents. For example:

$ ./ishow 20
Hex = 0x00000014, Signed = 20,  Unsigned = 20
$ ./ishow 0xffffffff
Hex = 0xffffffff, Signed = -1,  Unsigned = 4294967295

fshow: Floating-Point Representations

The fshow utility accepts either an integer or hex value representing an arbitrary bit pattern, or a float-point number, and outputs the corresponding floating point value and representation components. For example:

$ ./fshow 5.25

Floating point value 5.25
Bit Representation 0x40a80000, sign = 0, exponent = 0x81, fraction = 0x280000
Normalized.  +1.3125000000 X 2^(2)
$ ./fshow 100

Floating point value 1.401298464e-43
Bit Representation 0x00000064, sign = 0, exponent = 0x00, fraction = 0x000064
Denormalized.  +0.0000119209 X 2^(-126)

blc: Compliance

The blc (bit lab compiler) utility is a modified C compiler that will check your solutions for compliance with the coding rules specified. To check the compliance (but not correctness) of your solutions, run blc on your puzzles.c file as follows:

$ ./blc puzzles.c

If your program is fully compliant, no output will be produced (otherwise, an error message will be printed). You can also count the number of operations in each function by passing the -e switch:

$ ./blc -e puzzles.c

btest: Correctness

To check the correctness (but not compliance) of your solutions, use the btest utility. To use btest, you must compile it using the included Makefile by typing make, which will compile it using your current puzzles.c file. This means that your must rebuild btest each time you modify puzzles.c. You should not modify the included Makefile.

Once compiled, simply run the utility directly to check the correctness of all your solutions:

$ ./btest

You can also use the -f flag to tell btest to test only a single named function, like this (assuming a function named foo):

$ ./btest -f foo

While btest normally checks your solutions against many possible inputs, you can also check specific inputs using the flags -1, -2, and -3. For example, to test the correctness of foo(5, 0xF), you could run the following:

$ ./btest -f foo -1 5 -2 0xF Autoscoring

The utility (a Perl script, if you are curious) will both run btest to check your solutions as well as count the number of operations used. To use it, simply execute it directly:

$ ./

The script will output an autogenerated score for each puzzle out of 1-4 possible correctness points (based on the difficulty rating of the puzzle) and 2 possible performance points (based on the number of operations used). The total score shown does not correspond directly to your project score (in particular, a full performance score is not necessary for full credit) but will give you a sense of where improvement is possible.

Debugging Tips and General Advice


To get started, download the starter files on the class server using the standard utility wget (web-get), then decompress the archive using tar:

$ wget
$ tar xzvf p1-bits.tar.gz

These commands will download the starter files and decompress them, creating a directory in your current working directory called p1-bits. You should move this directory into your SVN directory and name it proj1 (alongside your existing proj0 directory). You can then add and commit your proj1 directory to SVN in the usual way.

As you work, commit your changes to SVN frequently. This will both save your work and allow me to see your progress. You will be required to show progress at an intermediate checkpoint via your SVN commits!

As with project 0, your final committed puzzles.c at the project due date will constitute your project submission.


You will be evaluated on the contents of your puzzles.c file, which must contain both your puzzle solutions and your solution explanations. Do not store any work that you would like to be considered outside this file!

Your project will be evaluated as follows:

Partial credit is possible for solutions that are not complete, provided some understanding of the problem is apparent (note that good documentation will be doubly important here).