CIS 2400 (Fall 2024) Home Schedule Assignments Tools & Refs HW 01: Binary Puzzles

This assignment gives students hands on expereince with binary representation, boolean logic, and a little exposure to programming in C.

Collaboration

For assignments in CIS 2400, you will complete each of them on your own solo. However, you may discuss high-level ideas with other students, but any viewing, sharing, copying, or dictating of code is forbidden. If you are worried about whether something violates academic integrity, please post on Ed or contact the instructor.

Setup

If you haven’t already, you need to follow the Docker Setup. We recommend you try and figure this out ASAP.

Once you have the environment set up, you should boot it up, and download the appropriate tar file and compiler based on your machine. To download them, you should open the terminal and use the provided command:

curl -o binary_puzzles.tar https://www.seas.upenn.edu/~cis2400/current/projects/code/binary_puzzles_x86.tar

and this for the x86 compiler:

apt-get install -y gcc-multilib
curl -o binary_puzzles.tar https://www.seas.upenn.edu/~cis2400/current/projects/code/binary_puzzles_arm.tar

and this for the arm compiler:

apt-get install -y gcc

After downloading the tar file, you should be able to type in the command “ls” in the terminal, or use the file explorer to see the download tar file. Once you confirm that the file is downloaded, run the following command to decompress the files:

tar -xvf binary_puzzles.tar

You should now have a directory called binary_puzzles that contains the files necessary for this assignment.

Instructions

Once you have followed the setup instructions, there should be a folder called binary_puzzles that contains the file for this assignment. The only file you need to modify for this assignment is bits.c. The bits.c is a C programming file, and it contains the skeleton for 17 binary puzzles.

Each of these puzzles will be contained in a C function that you will have to complete. This means that you will have to write a little bit of C code, but if you have programmed in Java and are familiar with C binary operators, that should be enough (there is also a refresher on some of these operators here. These puzzles will each have their own restrictions on the operators you are allowed to use, some general restrictions are also outlined below.

Complete documentation on what kind of code is allowed and disallowed can be found at the beginning of the bits.c file. We will also give an overview of the restrictions on each type of puzzle below.

There are also provided ways to make sure your solutions behave correctly and follow the provided restrictions. You can read more on how to test in the Compiling and Testing section below.

You may find it useful to review the text editors and terminal as decribed in the docker setup and the previous homework. We also have the bash reference that may be useful.

It may also be helpful for you to write print statements for debugging purposes. We have information on how to print in C in the printf section below.

Binary Puzzles

For these puzzles, you will typically be given an int variable (which is a signed 2C type) and you will have to return the appropriate value for every possible integer input. For some of these puzzles, while the input is a 2C integer, you should think of the input as being a sequence of 32-bits and not so much as a number. Some puzzles may give you a char as a parameter. Remember that a char is an 8-bit integer type, that can represent an ascii character.

The code you write for each of these puzzles must follow certain rules, you can find these rules at the top of bits.c but here is an overview on them:

These restrictions are here so that you can get comfortable with the bit-wise operators and thinking with bits.

Below we have a table listing out the each of these puzzles, their somewhat subjective difficulty rating and a description of the problem. You will have to implement these puzzles in bits.c and each of the functions will have a comment before them further explaining the problem and restrictions.

Function Name Rating Description
negate 1 return -x
minusOne 1 return -1 using only positive integer constants & binary ops
multPower2 1 multiply an int by a power of 2 without the * operator
getAscii 1 get the ascii encoding of a given printable ascii character
digitToChar 1 get the ascii character that represents the given digit
charToLower 1 return the lowercase version of an uppercase letter
getByte 2 Extract byte n from word x
isEqual 2 return 1 if x == y, and 0 otherwise
shortArrayAt 2 given a pointer to the start of an array and an index, return &arr[i]
byteSwap 3 swaps the nth byte and the mth byte
conditional 3 same as x ? y : z
validIntArrayIndex 3 given a pointer to the start of an array of ints, and the array's length, returns 1 iff another pointer is a valid index into the array.
fitsBits 4 return 1 if x can be represented as an n-bit 2C integer
addOK 4 Determine if can compute x+y without overflow
charToLowerChecked 4 same as charToLower, but returns the same character passed in if it is not an uppercase letter.
absVal 4 returns the absolute value of x
isNonZero 4 Check whether x is nonzero without using !

Compiling and Testing

To test your code locally, you will first need to navigate in the terminal to where your bits.c file is. Once you are there, run the command make in the terminal. This command will compile your code and print any warnings/errors. We highly suggest you fix any errors and warnings except for the printf warning mentioned below. You will NEED to run this command again after each time you modify bits.c and want to test your code again.

Once you have run make there should be multiple programs you can now run to test your code:

printf

printf is a C function used for printing output when the program runs. This is comparable to System.out.println from Java. Since we haven’t covered C yet, here is some basics of using printf that should cover your printing needs for this assignment.

Assume we have an integer variable int a; defined somewhere in our code. If you wanted to print out the decimal value of a on a new line, you would write the line of code: printf("%d\n", a);.

We can make our print message have a little more context by modifying the string passed in to printf. An example of this would be: printf("The value of a is %d\n", a);.

If we want to print out the value of a in hexadecimal, we just need to replace the %d with %X. For example printf("%X\n", a);. Note that we cannot print a in binary just using a single call to printf. If you want the exact binary, we recommend you print the value in hexadecimal and convert hexadecimal to binary.

Operator Review

Since some of the C bit operators may be new to you, we are providing a table below that lists some of them alongside a description of them. For this table, assume that a and b are defined as ints.

Operator Usage Description
! !a The "bang" operator. If a is 0, !a evaluates to 1 if a is non-zero, !a evalutes to 0
~ ~a Performs a bit-wise "not" operation on a. Every bit that is a 1 in a becomes a 0 and vice-versa
& a & b Performs a bit-wise AND operation on the bits in a and b
^ a ^ b Performs a bit-wise XOR operation on the bits in a and b
| a | b Performs a bit-wise OR operation on the bits in a and b
+ a + b Performs addition on a and b
<< a << b Shifts the bits in a to the left b-times
>> a >> b Shifts the bits in a to the right b-times. If a is a signed type, then it is an arithmetic shift. If a is an unsigned type, it is a logical shift.

Advice and Misc Tips

int foo(int x) {
    int a = x;
    a *= 3; /* Statement that is not a declaration */
    int b = a; /* ERROR: Declaration not allowed here */
}

Instead, the above code should be written like:

int foo(int x) {
    int a = x;
    int b = a; 
    a *= 3;
}

Submission

Please submit your completed bits.c to Gradescope