Bitwise Operators
#include <stdio.h>
#define SIZE 20
/////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 1):
A company is looking to hire an employee based on answers to a questionnaire.
The questionnaire has 20 yes/no questions (labeled from question 0 to question
19) and an applicant’s set of responses is stored as a single integer such
that the ith bit is set to 1 if the response to question i is yes, and it’s
set to 0 if the response to question i is no. For example, if an applicant
answered yes to questions 0, 2, 3, 5, 8, and 10 and no to the other 14
questions, her responses would be stored as the single integer 1325, since
00000000010100101101 = 1325. For all questions, the company prefers yes
answers to no answers. However, since it’s unlikely that a candidate will
answer yes to all of the questions, they have developed a modified scoring
system for each candidate. The company has ranked each of the 20 questions in
order of preference from most important to least important. This ranking is an
array, preferences, that stores a permutation of the integers from 0 to 19,
inclusive. For example, if preferences[0] = 8, preferences[1] = 10 and
preferences[2] = 1, then the company cares most about the answer to question
8, second most about the answer to question 10 and third most about the answer
to question 1. A candidate's score is simply the maximum number of the most
important questions they answered yes without a single no. For example, the
sample candidate described above would have a score of 2, because she said yes
to questions 8 and 10, but no to question 1, which was third on the preference
list. Any candidate who said no to question 8 would be assigned a score of 0.
Complete the function below so it returns the score of the applicant whose
answers are stored in the formal parameter applicant. The formal parameter
preferences is an array of size 20 which stores the order of importance of the
questions as previously described. (Note: You must use bitwise operators to
earn full credit for this question. Assume SIZE has been defined as 20.)
*/
int score(int preferences[], int applicant) {
int i = 0;
// Loops through the indexes of preferences starting at 0
for (i = 0; i < SIZE; i++) {
// 1 << preferences[i] will shift 1 left by preferences[i], which represents
// the current question being checked. Use the bitwise & operator with
// applicant to determine whether the applicant answered "yes" to that
// question. If the result is greater than 0, the applicant answered yes and
// we continue to the next most important question. If the result is 0, the
// applicant answered no, so we stop and return how many important questions
// were answered yes in a row.
if (((1 << preferences[i]) & applicant) == 0)
break;
}
return i;
}
///////////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 2):
Imagine a dating website that asks each user 20 yes/no questions and stores
their answers in a single integer in between 0 and 2^(20) -1, with the answer to
the kth question stored in bit 2^(k-1) , with the bit 0 representing the answer
no and the bit 1 representing the answer yes for the corresponding question. (So
for example, if one person’s answers to questions 1, 3 and 4 were yes and the
rest of the answers were no, the integer 1101 = 13 would be used to represent
her 20 answers to the questions.) Consider the problem of finding the “best
match” for a client out of a list of prospective matches. We consider a match A
for the client to be better than match B if she shares more answers on
corresponding questions with A than B. Write a function that takes in an integer
representing the client’s answers, an array of integers storing the answers of
potential matches, and the length of that array, which returns the index into
the array storing the best match for that client. If there are multiple best
matches, you may return the index associated with any of them. A function has
been given that you may call in your code, if you find it useful.
*/
int count(int mask);
int bestMatch(int client, int *matches, int length) {
int bestIndex = 0;
int bestCount = -1;
for (int i = 0; i < length; i++) {
int numMatches = 20 - count(client ^ matches[i]);
if (numMatches > bestCount) {
bestCount = numMatches;
bestIndex = i;
}
}
return bestIndex;
}
int count(int mask) {
int res = 0, i;
for (i = 0; i < 32; i++)
if ((mask & (1 << i)) != 0)
res++;
return res;
}
///////////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 3):
There are a total of 25 cards, numbered 0 through 24. We can represent a set of
cards with a single integer by setting the i th bit to 1 if the set contains
card i, and setting the bit to 0 otherwise. For example, the set of cards {2, 6,
7} would be stored as the integer 196, since 196 = 2^7 + 2^6 + 2^2 . Two sets of
cards are disjoint, if and only if no card appears in both sets. Complete the
function below so that it returns 1 if the sets of cards represented by the
integers set1 and set2 are disjoint, and returns 0 if they are not disjoint.
(For example, disjoint(196, 49) should return 1 because 49 = 2^5 + 2^4 + 2^0 , and
there is no common value in the two sets {2, 6, 7} and {0, 4, 5}. On the other
hand, disjoint(196, 30) should return 0 because 30 = 2^4 + 2^3 + 2^2 + 2^1 , so that
card number 2 is included in both sets 196 and set 30.)
// Pre-condition: set1 and set2 are bitmasks in between 0 and
// (1<<25)-1.
// Post-condition: Returns 1 if the two bitmasks are disjoint,
// meaning that the sets they represent don't have
// any items in common, and returns 0 otherwise, if
// the two represented sets do have common items.
*/
int disjoint(int set1, int set2) { return ((set1 & set2) == 0); }
////////////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 3):
Imagine the task of painting a picket fence with 20 pickets. Let each picket be
numbered from 0 to 19, from left to right and initially each is painted white. A
pattern is 5 pickets long and can be placed with the pattern's left end aligned
with any picket in between number 0 and number 15, inclusive. (If you line the
pattern up with any of the pickets 16 through 19, the right end of the pattern
goes past the right end of the fence and this isn't allowed.) Below is a picture
of an example pattern, with the 3 of the 5 possible pickets painted:
If this pattern was lined up with picket number 4, then pickets 4, 5 and 7 would
get painted. Think of the process as a placing a stamp on a portion of the whole
fence. We can represent this pattern with the integer 11 (2^0 + 2^1 + 2^3
), the integer where bits 0, 1 and 3 are set to 1. The bit positions represent,
relative to the left end of the pattern, which positions have paint on them.
One way to paint a fence with a pattern is to line up the pattern with a few
different picket numbers and apply the pattern. For example, if we lined up this
pattern with the pickets at positions 1 and 4, then the pickets that would be
painted would be at positions 1, 2, 4, 5 and 7. (Notice that painting an
individual picket more than once leaves it still painted.) Complete the function
below so that it takes in an integer, pattern, in between 0 and 31, inclusive,
representing the pattern, an integer array, paintLoc, which stores the locations
to line up the pattern with for painting, and paintLen, representing the length
of the array paintLoc and returns a single integer storing the state of the
painted fence (for each picket number, k, that is painted, bit k in the returned
integer should be set to 1). Each of the values in paintLoc will be distinct
integers in between 0 and 15, inclusive.
*/
// This problem is difficult to understand at first, so here is a breakdown
// of what each variable represents:
//
// pattern: an integer representing a 5-bit mask. Each bit represents whether
// a picket relative to the left edge of the pattern is painted (1) or not (0).
//
// paintLoc[]: an array of integers indicating where the left edge of the
// pattern should be placed on the fence. For each value paintLoc[i], the
// pattern is shifted left by paintLoc[i] to line it up with the correct
// pickets.
//
// paintLen: the number of locations stored in the paintLoc array.
//
// Example:
// Suppose pattern = 00101 (binary) and paintLoc[] = {2, 6}.
// Start with fence = 00000000000000000000.
//
// First iteration (paintLoc[0] = 2):
// pattern << 2 = 00000000000000010100
// fence | value = 00000000000000010100
//
// Second iteration (paintLoc[1] = 6):
// pattern << 6 = 00000000000001010000
// fence | value = 00000000000001110100
//
// The final returned integer has bits 3, 5, 7, and 9 set to 1,
// meaning those pickets are painted.
int paintFence(int pattern, int paintLoc[], int paintLen) {
int fence = 0;
for (int i = 0; i < paintLen; i++) {
fence = fence | (pattern << paintLoc[i]);
}
return fence;
}
////////////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 4):
In the game of NIM, there are several piles with stones and two players
alternate taking 1 or more stones from a single pile, until there are no more
stones left. The person who takes the last stone wins. It turns out that if it's
someone's turn, if they play optimally, they can win as long as the bitwise XOR
of all of the number of stones in each pile is not equal to 0. Write a function
that takes in an array of values representing the number of stones in the piles
of NIM and the length of that array, and returns 1, if the current player can
win, and 0 otherwise, assuming both players play optimally.
*/
int canWinNIM(int piles[], int numPiles) {
int total = 0;
for (int i = 0; i < numPiles; i++) {
total = total ^ piles[i];
}
return (total != 0);
}
////////////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 5):
Two useful utility functions when dealing with integers in their binary
representation are (a) int lowestOneBit(int n) - returns the value of the lowest
bit set to 1 in the binary representation of n. (eg. lowestOneBit(12)returns 4,
lowestOneBit(80)returns 16.) (b) int highestOneBit(int n) - returns the value of
the highest bit set to 1 in the binary representation of n. (eg.
highestOneBit(12)returns 8, highestOneBit(80)returns 64.) Note: You may assume
that the input is less than 109 . The largest positive bit value in an integer
is equal to 230 > 109
.
The pre-condition for the first function is that n must be a positive integer.
The pre-condition for the second function is that n must be a positive integer
less than 109 . Write both of these functions in the space below. To earn full
credit, you must use bitwise operators when appropriate. (Namely, there are ways
to solve this question without using bitwise operators, but these solutions will
NOT receive full credit.)
*/
// Keep shifting 1 left until the first bit that is 1 is found
int lowestOneBit(int n) {
int rtn = 1;
while ((n & rtn) == 0) {
rtn = rtn << 1;
}
return rtn;
}
// Highest set bit is the greatest power of 2 less than or equal to the integer
int highestOneBit(int n) {
int rtn = 1;
while ((rtn << 1) <= n) {
rtn = rtn << 1;
}
return rtn;
}
////////////////////////////////////////////////////////////////////////////////////
/*
FOUNDATION EXAM QUESTION (Question 6):
In this problem we will consider buying a collection of 20 figurines, labeled 0
through 19, inclusive. The figurines come in packages. Each package has some
non-empty subset of figurines. We can represent the contents of a single package
using an integer in between 1 and (2^20) – 1, inclusive, where the bits that are
on represent which figurines are in the package. For example, the integer 22 =
2^4 + 2^2 + 2^1 , would represent a package with figurines 1, 2 and 4. Each
month, one package comes out. You greedily buy every package until you have all
20 figurines. Write a function that takes in an array of integers, packages, and
its length, n, where packages[i] stores an integer representing the contents of
the package on sale during month i, and returns the number of months you will
have to buy packages to complete the set. It is guaranteed that each figurine
belongs to at least one of the packages and that each value in the array
packages is in between 1 and (2^20) -1, inclusive. For full credit, you must use
bitwise operators.
*/
int monthsTillComplete(int packages[], int n) {
// It has said that the value of each package is between 1 and (2^20) -1
// where (2^20) -1 represents the value of bitmask with all 20 bits set
// This value can be written as (1<<20)-1 [1 shifted 20 bits left - 1]
int numAllCollected = (1 << 20) - 1;
// Now we can have some tracker to determine if all bits have been set to 1
// and continue updating every month
int tracker = 0;
int month = 0;
while (tracker != numAllCollected && month < n) {
tracker |= packages[month];
month++;
}
return month;
}
////////////////////////////////////////////////////////////////////////////////////
// Additional example question: Write a function that takes in an integer and prints the
// binary version of that integer from left to right as it would be read
// Takes in a decimal integer greater than 0 and prints each bit
void printEachBit(int num) {
if (num == 0)
return;
// shifts bits right one removing rightmost bit (Ex. 1101 becomes 110)
int newNum = num >> 1;
// Recursive call which shifts
printEachBit(newNum);
// This will return 1 if the rightmost bit is one, otherwise returns 0
int lastBit = num & 1;
// Prints on backtrack in order to print left to right
printf("%d", lastBit);
}
Academic Notice: The code shown here is provided solely as a learning reference. Copying and pasting is intentionally disabled to encourage independent practice. Students should implement solutions on their own to demonstrate understanding. This material is not intended for direct submission in assignments.
Additionally: This code was written by a former CS1 student and may not reflect your professor’s intended solution or instructional approach. For coursework, students are expected to follow examples, conventions, and requirements presented in class and in professor-assigned materials.