Skip to content

CS 31 (Fall '17)

Kevin Hsieh edited this page Feb 2, 2018 · 1 revision

Implementing a Vector Class for ints

Contributed by Alex Hunsader.

Implement a vector class (array that can grow in size) using dynamically allocated arrays. The class should have the following declaration:

class Vector {
    public:
        Vector();
        ~Vector();
        int getElementAt(int a); //returns element at index a
        void push_back(int a);   //adds item to back of vector
        int size();                          //returns size of the vector
    private:
    //you may add whatever private variables and functions
};

You may assume that the index, a, will always be less than the current size and greater than 0, i.e. if the current size is 2, v.getElementAt(2) will never be called.

Example

Vector v;
v.push_back(10);
v.push_back(12);

cout << "size: " << v.size() << endl;

for(int i = 0; i < v.size(); i++)
    cout << v.getElementAt(i) << endl;

outputs:

    size: 2
    10
    12

Solution

class Vector {
 public:
    Vector();
    ~Vector();
    int getElementAt(int a);
    void push_back(int a);
    int size();
 private:
    int current_position;
    int max_size;
    int * array;
};

Vector::Vector() {
    current_position = 0;
    max_size = 1;
    array = new int(max_size);
}

Vector::~Vector() {
    delete [] array;
}

int Vector::getElementAt(int a) {
    return array[a];
}

void Vector::push_back(int a) {
    if (current_position != max_size) {
        array[current_position] = a;
        current_position++;
        return;
    }
    // size not large enough --> expand array
    max_size *= 2;
    int * temp = new int(2 * max_size);
    for (int i = 0; i < max_size; i++)
        temp[i] = array[i];
    max_size *= 2;
    delete [] array;
    array = temp;
    array[current_position] = a;
    current_position++;
}

int Vector::size() {
    return current_position;
}

Compress String

Contributed by Christian Rodriguez.

You are given a string that is passed into a function called isCompressed. Compress the string by counting repeated characters. For example, given the string "aabbcc" output "a2b2c2". You may assume that the string consists of lowercase letters from a-z.

You might find it useful to use the to_string function which is included in the string library of C++. to_string converts an integer to a string. For example, to_string(4) outputs the string "4".

Example

"aaaab" outputs "a4b1"

"abcdef" outputs "a1b1c1d1e1f1"

Solution

#include <iostream>
#include <string>
using namespace std;

string isCompressed(string word) {
    int counter = 0;
    string temp = "";
    for (int i = 0; i < word.length(); i++) {
        counter++;
        if (i+1 >= word.length() || word[i] != word[i+1]) {
            temp += word[i] + to_string(counter);
            counter = 0;
        }
    }
    return temp;
}

Array pointer analysis

Contributed by Chenyu Xu.

Find the final arr array for the following code:

int main()
{
    int arr[4] = { 0, 1, 2, 3 };
    int* ptr = arr;

    *ptr = arr[1];               // 1
    *(ptr + 1) = arr[0] * 10;      // 2
    ptr += 2;
    ptr[0] = arr[1] * 10;        // 3
    ptr[1] = 1000;                 // 4
}

A. { 0, 0, 0, 0 }
B. { 0, 1, 10, 100 }
C. { 1, 10, 100, 1000}
D. { 10, 1000, 100, 1000}

Solution

The result arr is { 1, 10, 100, 1000}

  1. set arr[0] to 1
  2. set arr[1] to 10
  3. set arr[2] to 100
  4. set arr[3] to 1000

Palindrome

Contributed by Brandon Oestereicher.

Write a function that checks whether a string is a palindrome or not (return true if palindrome and false if not)

Solution

#include <string>
using namespace std;

bool isPalindrome(string s) {
  int ssize = s.size();
  for (int i = 0; i < ssize / 2; i++) {
    if (s[i] != s[ssize - i - 1]) {
      return false;
    }
  }
  return true;
}

Pass by value/reference/pointer

Contributed by Binyi Wu.

Read the following code:

#include <iostream>
#include <string>

using namespace std;

int f1(int i, int &j) {
    return i == (--j = -1);
}

void f2(int& i, int* j) {
    i = f1(*j++, i);
    j = &i;
}

void f3(int i, int* j, int& k) {
    i = ++k + (*j)++;
    f2(k, j);
    f2(k, &i);
    
    cout << "i: " << i;
    cout << " j: " << *j;
    cout << " k: "<< k;
}

int main(int argc, const char * argv[]) {
    int a = 1, b = 2, c = 3;
    
    f3(a, &b, c);
    
    cout << " a: " << a;
    cout << " b: " << b;
    cout << " c: " << c;
}

Which is the correct output of this program?

a. i: 0 j: 3 k: 0 a: 1 b: 3 c: 0
b. i: 6 j: 3 k: 4 a: 1 b: 3 c: 4
c. i: 6 j: 3 k: 4 a: 6 b: 3 c: 4
d. i: 0 j: 4 k: 0 a: 1 b: 4 c: 4
e. i: 6 j: 3 k: 0 a: 1 b: 3 c: 0

Solution

Answer: E.

Hint: Note the output f1 will be either 1 or 0.

Explanation:

  1. a is passed into f3 by value, so it's value will never be changed. i is passed into f2 by reference at the first time and as a pointer at the second time. So the change of value will be reflected in f3 after entering f2.

  2. b is passed into f3 as a pointer(by its address), so its value should be the same as j. Although there's a quite confusing *j++ term which is adding to the address instead of to the real value, we could ignore it since we know the output of f1 will either be 0 or be 1 after -1 is assigned to j as its value.

  3. c is passed into f3 as by reference, so its value should be the same as k. It is passed into both f2 and f1 by reference, so it's value will be updated in the two functions.


Reverse CString without Extra Variables

Contributed by Joey Ganley.

Write a function that takes a cstring and an integer length as input and outputs the reverse of that cstring. However, the only variable you are allowed to use is an iteration variable in a loop. Make sure not to create any additional variables to assist in this process.

Function Declaration

char* reverseCString(char* a, int length);

Solution

When reversing a string, you typically will use a temp variable to store letters as you replace them. This question does not allow you to create a variable to do that. So the trick to this question is realizing that all cstrings have a null byte, which you can use as an extra spot in the cstring to use as a temp variable.

char* reverseCString(char* a, int length) {
// STRATEGY
// cstring will have null byte at the end
// use the null byte spot to store chars

// store letter at index i in the null spot
// replace letter in index i with letter from the end of the string
// reinsert letter in index i into end of the string
for (int i = 0; i < length/2; i++) {
a[length] = a[i];
a[i] = a[length-1-i];
a[length-1-i] = a[length];
}

// reinsert the null byte
a[length] = '\0';

return a;
}

DistanceTraveled

Contributed by Jonathan Quach.

Suppose you were asked to find how far your friend has traveled given a char array and its size. We ask that you calculate the Euclidean distance that your friend has traveled (Recall that Euclidean distance is defined as √((x - a)² + (y - b)²)

Assuming an x-y coordinate plane and that your friend starts at the origin:

Any form of the letter N or U means that your friend has moved exactly one unit in the positive y-direction.

Any form of the letter E or R means that your friend has moved exactly one unit in the positive x-direction.

Any form of the letter S or D means that your friend has moved exactly one unit in the negative y-direction.

Any form of the letter W or L means that your friend has moved exactly one unit in the negative x-direction.

Sounds simple, but your friend is a little extra. Your friend is so extra that their char array may not just have the letters mentioned above but may also contain digits, punctuation marks, and other letters of the alphabet. Your code should be able to deal with processing such characters, even if chose characters do not contribute to the final calculation.

One more constraint: You MUST use both the sqrt() function and the pow() function in the cmath library AT LEAST ONCE in your code.

The sqrt() function takes only a double as an input and returns a double as an output

double x = sqrt(269); // x is 16.4012
double y = sqrt(3.14) // y is 1.772
double z = sqrt(-1) // z is nan (cannot take the square root of a negative number)

The pow() function takes two doubles as inputs and returns a double as an output. The first double passed in is the base, and the second double in is the exponent to raise the base by.

double a = pow(3,4); // a is 81
double b = pow(4,-2) // b is 0.0625
double c = pow(-5,3) // c is -125
double d = pow(-2,-5) //d is -0.03125

Assume that the following lines are already included at the top of your code:

#include <cmath>
#include <cctype>
#include <iostream>

Example

Input:   {'u','u','u','d','u','l','l','w','L'}, 9
Output: 5

Input: {'u','a','q','!','d','@'}, 6
Output: 0

Input: {'u','!','d','N','w','E','e','r','R','?','.','2'}, 12
Output: 3.16228

Solution

The trick here is to only process any of the 8 letters that convey that your friend has moved. I.e., ignore any other character. Since uppercase and lowercase letters are to be treated the same, your code must be able to reflect that (either by using the built-in functions tolower() or toupper() from the cctype library or writing your own code that exhibits similar results). NOTE: since there are many ways to either ignore a char or process a char, there are also many possible solutions to this problem.

#include<iostream>
#include <cctype>
#include <cmath>

double distanceTraveled(char arr[], int n) {    
    int x_pos = 0;
    int y_pos = 0;
    
    for (int i = 0; i < n; i++) {
        char move = tolower(arr[i]);
        
        if (move == 'n' || move == 'u')
            y_pos++;
        else if (move == 'e' || move == 'r')
            x_pos++;
        else if (move == 's' || move == 'd')
            y_pos--;
        else if (move == 'w' || move == 'l')
            x_pos--;
    }
    return sqrt(pow(x_pos, 2) + pow(y_pos, 2));
}

int main() {
char b[] = {'u','U','N','r','E','R','e'};
std::cout<<distanceTraveled(b, 7) << std::endl;
}

Writing Swap Functions

Contributed by Joseph Mo.

Examine the four swap functions below.

#include <iostream>
using namespace std;

void mystery1(int a[], int b[]) {
    int temp = a[0];
    a[0] = b[0];
    b[0] = temp;
}

void mystery2(int* a, int* b) {
    int* temp = a;
    a = b;
    b = temp;
}

void mystery3(int& a, int&b) {
    int temp = a;
    a = b;
    b = temp;
}

void mystery4(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

Which of the following does NOT output "2"?

(A)

int a[] = {1, 3, 5, 7, 9};
int b[] = {2, 4, 6, 8, 10};
mystery1(a, b);
cout << a[0] << endl;

(B)

int a = 1;
int b = 2;
mystery2(&a, &b);
cout << a << endl;

(C)

int a = 1;
int b = 2;
mystery3(a, b);
cout << a << endl;

(D)

int a = 1;
int b = 2;
mystery4(&a, &b);
cout << a << endl;

Solution

(B) does not output 2.


Find the Error

Contributed by Justin Li.

Consider the following function:

1    int sumOfDigits(int n) {
2        int sum = 0;
3        if (n < 0) {
4            n = -n;
5        }
6        while (n >= 0) {
7            sum += n % 10;
8            n /= 10;
9        }
10       return sum;
11   }

This function is supposed to return the sum of digits of n. Does it work as intended?

A) Yes - it's perfect.
B) No - there is an error on line 1
C) No - there is an error on line 3
D) No - there is an error on line 6
E) No - there is an error on line 7
F) No - there is an error on line 8

Solution

The answer is D. The condition in the while loop should be n > 0. As written, n will always be greater than or equal to zero, resulting in an infinite loop.


Parition array

Contributed by William Lee.

Given an int array, move all negative values to the left, so that all negative values are to the left of all nonnegative values.

Note that the function takes in array and its length as parameters.

Example of possible outputs (many possible)

partition([1,2,3], 3) = [1,2,3] (or other orderings)

partition([-1,-2,-3,0,-1], 5) = [-1,-2,-3,-1,0] (or other orderings)

partition([1,2,3,-1],4) = [-1,2,3,1]

Note that ordering does not matter as long as negative values are on the left.

Solution

Keep track of the next index we can put a negative value in. Loop array, if see negative value swap it into the next index we keep track of.

#include <iostream>
using namespace std;

void partition(int arr[], int length) {
    int next = 0;
    for (int i = 0; i < length; i++) {
        if (arr[i] < 0) {
            // swap
            int tmp = arr[next];
            arr[next] = arr[i];
            arr[i] = tmp;
            next++;
        }
    }
}

Reverse A Number

Contributed by Vansh Gandhi.

Given a non-negative number, return the number that results by reversing the order of the digits

The function signature should look like int reverseNum(int *num);

Note: reverseNum takes an int pointer, not an int

Example

Given 12345, return 54321

Given 0, return 0

Given 10, return 1

Given 100, return 1

Solution

In order to get the correct solution to this problem, you need to find a way to look at each problem individually. The way to do this is by using the mod and division operators. When you mod a number by 10, it will give you the digit in the one's place. Then, you can divide the number by 10 to get rid of that digit, and then repeat to get the digit that was originally in the ten's place, etc.

#include <iostream>
using namespace std;

int reverseNum(int *num) {
    int reversed = 0;
    for (int n = *num; n > 0; n = n/10) {
        reversed = reversed*10 + n%10;
    }
    return reversed;
}

int main() {
    int x = 1234;
    cout << reverseNum(&x) << endl;
    return 0;
}

Sum of Positive Numbers

Contributed by Hannah Kwon.

Given an array with positive and negative numbers, find the sum of the positive numbers. You may assume that the array will never be empty.

Example

Input: [-1]
Output: 0

Input: [1, -1, 2, 3]
Output: 6

Solution

#include <iostream>
using namespace std;

int findSum(int arr[], int len) {
    int sum = 0;
    for (int i = 0; i < len; i++) {
        if (arr[i] > 0) {
            sum+=arr[i];
        }
    }
    return sum;
}

int main(int argc, char* argv[]) {
    int arr[] = {1, 2, -1, 3, 5};
    cout << findSum(arr, 5) << endl;
}

What's in the string?

Haozhuo Huang.

Suppose you type in 24 when the program asks you to enter a number and you enter "Kobe" when the program asks your name. What would be s?

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "this is a string";
    int i;

    cout << "Enter a number: ";
    cin >> i;
    cout << "What's your name? ";
    getline(cin, s);
}

(A) "Kobe"
(B) "Kobe\n"
(C) "\nKobe"
(D) "\n"
(E) "
(F) "this is a string"

Solution

s should be (E) because when entering the number, it leaves the new line character and getline stops as long as it meets the new line character.


String Histogram

Contributed by Hengda Shi.

String Histogram is a program to generate a histogram of a input string or a cstring.

Requirement:

  • create a class called Histogram with the following functions:
// constructor
Histogram();
// parsing string
void acceptString(std::string data);
// parsing cstring
void acceptCString(char * data);
// reset data
void reset();
  • output the histogram data using cout (Hint: friend function).
  • The counting is not case-sensitive.
  • A sample main function is provided below.
#include <iostream>
using namespace std;

int main() {
    Histogram h;

    string s;
    cout << "Enter Data: ";
    getline(cin, s);

    h.acceptString(s);

    cout << h << endl;

    h.reset();

    char cstr[] = "HelloWorld";
        
        h.acceptCString(cstr);
        
        cout << h << endl;

    return 0;
}

Example

Enter Data: HelloWorld
D - 1 - *
E - 1 - *
H - 1 - *
L - 3 - ***
O - 2 - **
R - 1 - *
W - 1 - *

D - 1 - *
E - 1 - *
H - 1 - *
L - 3 - ***
O - 2 - **
R - 1 - *
W - 1 - *

Solution

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cctype>
#include <string>

using namespace std;

class Histogram {
 public:
    Histogram() {
        my_DataSoFar = ";
        
        for (int i = 0; i < 27; i++) {
            my_FrequencyCount[i] = 0;
        }
    }
    // declare the overloading functions of operator <<
    friend std::ostream& operator << (std::ostream& outs, const Histogram& h) {
        // output each characters
        for (int i = 0; i < 27; i++) {
            // if i element of the frequency count does not equal to zero
            if (h.my_FrequencyCount[i] != 0) {
                // print out the character and frequency count
                outs << static_cast<char>(65 + i) << " - " << h.my_FrequencyCount[i] << " - ";
                // print out the stars
                for (int j = 0; j < h.my_FrequencyCount[i]; j++) {
                    outs << "*";
                }

                outs << endl;
            }
        }

    return outs;
    }
    // enumeration
    enum LETTER {A = 1, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z};

    void acceptString(std::string data) {
        char ch;
        int letter;
        // for loop to catch each characters in the string
        for (int i = 0; i < data.length(); i++) {
            // let ch equals to the character
            ch = data.at(i);
            // matching the character
            for (letter = A; letter <= Z; letter++) {
                // if the upper case letter of ch equals to the ascii value of letter
                // call the increment function
                if (toupper(ch) == (letter + 64)) {
                    incrementFrequency(static_cast<LETTER>(letter));
                }
            }
        }
    }
    
    void acceptCString(char * data) {
        // convert the char array to string
        string my_data(data);
        char ch;
        // for loop to catch each characters in the string
        for (int i = 0; i < my_data.length(); i++) {
            // let ch equals to the character
            ch = my_data.at(i);
            // match the character
            for (int j = A; j <= Z; j++) {
                // if the upper case letter of ch equals to the ascii value of letter
                // call the increment function
                if (toupper(ch) == (j + 64)) {
                    incrementFrequency(static_cast<LETTER>(j));
                }
            }
        }
    }

    void reset() {
        my_DataSoFar = " ";
        
        for (int i = 0; i < 27; i++) {
            my_FrequencyCount[i] = 0;
        }
    }

    void incrementFrequency(LETTER l) {
        for (int i = A; i <= Z; i++) {
                // if i equals to the parameter, then increment the i element
                if (i == l)
                    my_FrequencyCount[i - 1]++;
            }
    }

 private:
    std::string my_DataSoFar;

    int my_FrequencyCount[ 27 ];
};

int main() {
    Histogram h;

    string s;
    cout << "Enter Data: ";
    getline(cin, s);

    h.acceptString(s);

    cout << h << endl;

    h.reset();

    char cstr[] = "HelloWorld";
        
        h.acceptCString(cstr);
        
        cout << h << endl;

    return 0;
}

Find Longest "Good" Substring

Contributed by Honghua Zhang.

Implement the following function:

int longestGoodSubstr(string str);

which takes a string str as its only argument and it should return the length of the longest substring in str that is Good. A string is Good if it is a non-empty string such that all characters in it are the same. i.e. "aaaa" is Good while "abc" is not.

Example

Input: "abbbccccd"
Output: 4

Solution

int longestGoodSubstr(string str) {
    	int ans = 0;
    	int len = str.size();
    	for (int i = 0; i < len; i = j) {
        	int j = i;
        	while (j < len && str[j] == str[i])
            	j++;
        	ans = max(ans, j - i);
    	}
        return ans;
}

Various Variable Initialization

Contributed by Jason Less.

Multiple-choice problem consisting of four different variable initialization lines. The goal is to choose the choice that illegally initializes variable(s):

Which of the following is illegal?

(a) int **ip;  
(b) std::string k, int x;  
(c) int *pi = 5;  
(d) std::string* s, *sp, a = "hello";  

Solution

(b) is incorrect. Can't initialize two variables of different types in the same line.


Finding a Majority

Contributed by Arpit Jasapara.

A majority is defined as greater than 50%. You are given an array of numbers, and the length of the array. You have to find out if a majority exists or not. If a majority does not exist, return -1. Otherwise, return the majority number. You may assume that the array has nonzero length. Your function template looks like this:

// Find and return the majority number in an array
int findMajority(int* array, int len) {}

Example

Input: [1,1,1,1,2,3], 6
Output: 1

Input: [1,2,3,4], 4
Output: -1

Input: [1,2,3,2,2,4,2,1,1,2], 10
Output: -1

Input: [1,2,3,2,2,4,2,1,1,2,2], 11
Output: 2

Solution

The first solution is a trivial solution that runs in O(n^2) time. The second solution is a more advanced solution that runs in linear time.

int findMajority(int* array, int len) {
        for(int i = 0; i < len; i++) {
                int count = 0;
                for(int j = i; j < len; j++) {
                        if(array[i] == array[j]) count++;
                        if (count > len/2)
                                return array[i];
                }
        }
        return -1;
}

int findMajority(int* array, int len) {
        int curr = array[0], count = 1;
        for (int i = 1; i < len; i++){
                if (curr == array[i])
                        count++;
                else {
                        count--;
                        if (count == 0){
                                curr = array[i];
                                count = 1;
                        }
                }
        }
        count = 0;
        for (int i = 0; i < len; i++)
                if(curr == array[i])
                        count++;

        if (count > len/2)
                return curr;
        return -1;
}

strcmp implementation

Contributed by Arvind Ramachandran.

Suppose we wish to make our own implementation of the c-string comparision function strcmp(). Let's call our implementation mystrcmp(). Fill in the following blanks:

int mystrcmp(const char *str1, const char *str2) {
  int i = 0;
  while (str1[i] != '\0' ____ str2[i] != '\0') {
    if (____________)
       return -1;
    else if (str1[i] > str2[i])
       return 1;
    ++i;
  }

  if (str1[i] == '\0' ____ str2[i] == '\0')
      return ____;
  else if (str1[i] != '\0') return ____;
  return ____;
}

Solution

&&, str1[i] < str2[i], &&, 0, 1, -1


Length of Longest Subarray

Contributed by Nyan Tun.

Given an array of 0's and 1's, return the length of the longest contiguous subarray of 1's.

Example

in: a = [1, 0, 1]
out: 1
in: a = [0, 1, 0, 1, 1]
out: 2
in: a = [1, 0, 1, 1, 1, 1, 0, 1, 1, 0]
out: 4

Solution

You iterate through the array and keep the values of a counter of the # of 1's and a maximum. You increment the counter every iteration as long as the element's value is 1 and reset to 0 otherwise. If the max is greater than the counter, you set the max to the counter.

#include <iostream>

using namespace std;

int longest_subarray(int size, int *a) {
    int *subarr = a;
    int counter = 0;
    int max_val = 0;
    for (int i = 0; i < size; i++) {
        if (subarr[i] == 1) {
            counter++;
            if (counter > max_val) {
                max_val = counter;
            }
        } else {
            counter = 0;
        }
    }
    return max_val;
}

int main() {
    int a[10] = {1, 0, 1, 1, 1, 1, 0, 1, 1, 0};
    cout << longest_subarray(10, a) << endl;
    return 0;
}

Remove Specific Value in Vector

Contributed by Pochao Yang.

Given an array and a value, remove all instances of that value in-place and return the new length. Do not allocate extra space for another array. The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Solution

#include <iostream>
#include <vector>
using namespace std;

class Solution {
 public:
    int removeElement(vector<int>& nums, int val) {
        int index = 0;
        for (int i = 0; i < nums.size(); ++i) {
            if (nums[i] != val) {
                nums[index++] = nums[i];
            }
        }
        return index;
    }
};

Manipulating Variables Passed by Reference

Contributed by Nikhil Bhatia.

#include <iostream>
using namespace std;

void modify(int& a, int&b);
int main() {
  int a = 4, b = 9;
  modify(a, b);
  cout << " In main " << a << b;
  return 0;
}

void modify(int &a, int &b) {
  int temp = a;
  a = b;
  b = temp;
  cout << "In modify " << a << b;
}

What is the output of the program?

a) In modify 94 In main 94
b) In modify 94 In main 49
c) In modify 49 In main 94
d) None of the above

Solution

The answer is a. This is because we are passing a and b by reference instead of by value. Then in the modify function we are simply switching the two values, and since they were passed by reference they are being changed in memory, not just locally in the modify function. Thus the two print statements will be identical.


Follow the Pointer!

Contributed by Nate Sookwongse.

Given the following code below, what is the output of main function?

void f(int *ptr) {
    *ptr = *ptr + 5;
}

void g(int num) {
    num = num + 3;
}

void h(int *ptr) {
    *ptr = *ptr - 1;
}

int main() {
    int x = 0;
    int y = 10;
    int z = 4;

    int *p;

    p = &x;
    *p = 5;
    f(p);
    g(*p);
    h(p);
    
    p = &y;
    f(p);
    h(p);

    p = &z;
    h(p);
    g(z);
    h(p);

    y = x + z;
    
    x = *p + x;
    
    cout << x << endl;
    cout << y << endl;
    cout << z << endl;
}

Solution

11
11
2

String manipulation

Contributed by Muchen Liu.

What is the output of the following code?
A. cbeba debbac cba
B. abcde abcdea abc
C. cbeba deaabc bca
D. abcde abcdea bca

#include <iostream>
using namespace std;

string funny(string m, int n);
void foo(string& m, int a, int b);

int main() {  
    cout << funny("abcbe", 2) << endl;  
    cout << funny("abcdea", 3) << endl;  
    cout << funny("abc", 1) << endl;  
}

string funny(string m, int n) {
    if (n >= m.length())
         return m;
    int a = 0;
    int b = a + n;
    while (a < m.length() && b < m.length()) {
        foo(m, a, b);
        a++;
        b++;
    }
    return m;
}

void foo(string &m, int a, int b) {
    char temp = m[a];
    m[a] = m[b];
    m[b] = temp;
    return;
}

Solution

C. cbeba deaabc bca


Pointer Arithemtic

Contributed by Koji Kusumi.

#include <iostream>
using namespace std;
int main(void) {
    int arr[10] = {5, 3, 2, 7, 8, 23, 19, 0, 1, 9};
    int* a = (arr + 9) - (&arr[2 + arr[2]]) + &arr[arr[8]];
    cout << *a << '\n';
}

Examine the above code. What does it print out?

Solution

19

The summands can be interpreted as follows:

&arr[2 + arr[2]] -->  &arr[2 + 2] --> (arr+4)
&arr[arr[8]] --> &arr[1] --> (arr+1)
arr + 9 - arr - 4 + arr + 1 = arr + 6

a is equal to arr + 6, so *a is equal to arr[6]


Point those Pointers!

Contributed by Kyle Wong.

A challenger wants to challenge you to solve one of his hardest problems in his repretoire. As an avid arrow collector, he expects someone to be sharp enough to solve this problem. Read the following code:

#include <stdio.h>
#include <iostream>

using namespace std;

void challenger(int** doublePtr) {
    int x = 0;
    int* ptr = &x;
    doublePtr = &ptr;
}

void pointThosePointers(int** doublePtr) {
    int* mystery = *doublePtr;
    *mystery *= (*mystery) - 1;
    doublePtr = &mystery;
    challenger(doublePtr);
}

int main() {
    int x = 5;
    int* ptr = &x;
    int** ptr2 = &ptr;
    pointThosePointers(ptr2);
    cout << **ptr2 << endl;
}

Which of the following is the correct output for this code snippet?
A. 25
B. 0
C. -1
D. 20
E. Undefined behavior

Solution

D. 20

Explanation: Notice that the void challenger(int** doublePtr) code does nothing! Be careful and notice that the parameter is passed by value, not by reference. Thus, if you answered 0, look back at the code and see why.


Most Continuously Occurred Number

Contributed by Kevin Qian.

Write a function that, when given an array of positive numbers (assume the input is always correct, that is, not having negative numbers, of length >= 0), find the most continuously occurred number. For example, in array {1,1,2,2,2,2,1,1,1}, the number we want is 2 (since it continuously occurred 4 times, more than each of the other two sequences of only 1s). Return -1 if the number could not be found. If >= 2 different continuous number sequences have the same count, return the number in the last sequence.

Example

INPUT: {1,1,2,2,2,2,1,1,1}, 9  
OUTPUT: 2  

INPUT: {1,1,1,2,2,2,3,3,3,4}, 10  
OUTPUT: 3  

INPUT: {}, 0  
OUTPUT: -1  

Solution

int most_continuously_occurred_number(int arr[], int n) {
    if (n <= 0) {
        return -1;
    }
    int curr_int = arr[0];
    int curr_count = 1;
    int max_int = -1;
    int max_count = 0;
    
    for (int i = 1; i < n; i++) {
        if (arr[i] == curr_int) {
            curr_count++;
        } else {
            if (curr_count >= max_count) {
                max_int = curr_int;
                max_count = curr_count;
            }
            curr_int = arr[i];
            curr_count = 1;
        }
    }
    
    if (curr_count >= max_count) {
        max_int = curr_int;
        max_count = curr_count;
    }
    
    return max_int;
}

Operator Overload

Contributed by An Nguyen.

class Complex {
 public:
    double get_real() { 
        return real; 
    }
    double get_imaginary() {
        return imaginary; 
    }
    void set_real(double re) { 
        real = re; 
    }
    void set_imag(double im) {
        imaginary = im;
    }
  
 private:
    double real;
    double imaginary;
};

Overload operator '+' to return the sum of 2 complex numbers, use friend.

Solution

class Complex {
 public:
    double get_real() { 
        return real; 
    }
    double get_imaginary() {
        return imaginary; 
    }
    void set_real(double re) { 
        real = re; 
    }
    void set_imag(double im) {
        imaginary = im;
    }

    friend Complex operator+(Complex c1, Complex c2) { 
        Complex c;
        c.real = c1.real + c2.real;
        c.imaginary = c1.imaginary + c2.imaginary;
        return c; 
    }
  
 private:
    double real;
    double imaginary;
};

Greatest Common Divisor

Contributed by Analisse Reyes.

Use iteration to complete the function gcd so that it returns the greatest common divisor of a and b

Example

gcd(24, 12)
output: 12

gcd(21, 14)
output: 7

Solution

int gcd(int a, int b) {
    int gcd;
    for (int i = 1; i <= a && i <= b; i++) {
        if (a % i == 0 && b % i == 0) {
            gcd = i;
        }
    }
    return gcd;
}

Locate a sub-array within an array

Andrew Xue.

Implement a function called subarray(int* A, int* B).Determine if array A (size of a) is a sub-array of array B (size of b). If yes, return the index of the start of sub-array in B. Otherwise, return -1.

Example

A = [2, 1]
B = [3, 2, 1, 4]
return 1

A = [1, 2, 3]
B = [1]
return -1

A = [1, 2]
B = [3, 2, 1]
return -1

Solution

int subarray(int* A, int* B)
{
        if(b < a)
                return -1;
        
        for (int i = 0; i != b; i++)
        {
                if(B[i] == A[0])
                {
                        if(i + a > b)
                            return -1;
                        for (int j = 0; j != a; j++)
                        {
                                if(B[j+i] != A[j])
                                        break;
                                else if( j == a-1)
                                        return i;
                        }
                }
        }
        return -1;
}

Indexing with Pointers

Contributed by Lawrence Lee

What is the output of the program below?

#include <iostream>

int main() {
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int *p = a+1;

    for (int i = 0; *(p+i) < 10; i++, p++)
        std::cout << p[i];
}

a) 13579
b) 1357
c) 246810
d) 2468
e) undefined

Solution

d) 2468

In this problem we have two iterators in our loop, one an integer starting from zero and the other a pointer starting from the second element in the array (a[1]). Since "array" variables are essentially pointers, pointer p can also use the bracket operators to access elements in the array, so p[i] is just the element i positions ahead of what p points to.

By inspecting/tracing the code, we see that p[i] is equivalent to a[2*i+1]. So the loop prints every other element starting from the second element (or every even number), however we also need to check the condition for which the loop terminates. There is also the possibility that p[i] will be undefined (out of bounds) if our condition fails to terminate the loop before p[i] is out of bounds. The condition essentially checks if p[i] < 10, so our loop will end only if p[i] >= 10. Since only one element in the array meets this condition (10), then our code will only work if p[i]==10 at some point since this is the only element in our array that can contradict the condition, and thus end the loop without causing undefined behaviour.

Since the loop goes to every even number, p[i] will eventually equal 10, at which point the loop will terminate and this value of p[i] will not be printed. So the program prints every even number in the array except 10.


Flipping the contents of an array.

Contributed by Marko Sevo.

Write a function that takes as parameters an array and its length n, and that flips the order of the elements in the array and returns n.

Example

Given the following array of strings: { "gary", "donald", "mike", "rob", "tim", "bob" } The resulting array should look like this: { "bob", "tim", "rob", "mike", "donald", "gary" }

Solution

#include <string>
using namespace std;

int flip(string a[], int n) {
    if (n < 0) {
        return -1;
    }
    
    for (int i = 0; i < (n/2); i++) {
        string tempStringGettingSwitched = a[i];
        a[i] = a[n-1-i];
        a[n-1-i] = tempStringGettingSwitched;
    }
    
    return n;
}

Function problem

Contributed by Melissa Peng.

What does the following code output?

#include <iostream>
using namespace std;

int main() {
  int n = 310;
  funcOne(n);
  std::cout << “n = “ << n << endl;
  return 0;
}

void funcOne(int n) {
  n = 240;
}

Solution

n = 310


Switch Statement Selection

Contributed by Spenser Wong.

Consider the following code.

#include <iostream>
using namespace std;

int main() {
  for (int i = 0; i < 7; i++) {
    switch (i) {
    case 0:
      cout << "D ";
    case 2:
    case 3:
      cout << "E ";
      break;
    case 4 :
      cout << "F ";
    case 5:
      cout << "C ";
      break;
    case 6:
      cout << "B ";
    default:
      cout << "A ";
    }
  }
}

Out of the selections below, which selection provides the proper output of the program?
A. D A E E F C B
B. D E A A E E F C C B A
C. D A E F C B
D. D E A A E E F C C B
E. D A E E F C B A

Solution

The correct answer is B. D E A A E E F C C B A . This is because some cases lack break statements, and one case has multiple case labels.


String Reversal

Sriharshini Duggirala.

Write a function that reverses a string. You may only use up to 5 variables. The function should have the following structure:

string reverse(string s){
     // YOUR CODE HERE 
}

Example

abc -> cba abcd -> dcba a -> a

Solution

#include <string>
using namespace std;

string reverse(string s) {
  int end = s.length()-1;
  char temp;
  for (int start = 0; start < end; start++) {
    temp = s[start];
    s[start] = s[end];
    s[end] = temp;
    temp--;
  }
  return s;
}

for loops and while loops

Contributed by Sydney.

Write 2 functions, FORLOOP_SUM and WHILELOOP_SUM to which will return the sum of all the numbers in list x. The length of list x is “size”.

Solution

int FORLOOP_SUM(int x[], int size) {
  int sum = 0; 
  for (int i = 0; i < size; i ++) {
      sum = sum + x[i];
  } 
  return << sum; 
} 

int WHILELOOP_SUM(int x[], int size) {
  int sum = 0; 
  int i = 0; 
  while (i < size) {
      sum = sum + x[i];
      i++;
  } 
  return sum; 
} 

Divison VS MOD

Contributed by Sydney.

What is the output of this program?

int main() {
  int x1 = 20; 
  int y1 = 3; 
  cout << x1 % y1 << endl; 

  int x2 = 20; 
  int y2 = 3; 
  cout << x2 / y2 << endl; 
}

Solution

2
6

Creating a Simple Vector (mathematical) Class

Dennis van Ee.

Write a simple Vector class that represents a 3D vector. The vector class should have 3 public member variables of type double called x, y, and z. The vector class should have a default constructor that constructs everything to 0. There should also be a constructor that takes in x, y, and z coordinates, in that order, and assigns them. The vector class should also allow for the following operations (function overloading):

If v0, v1, and v2 are Vectors and s is a double:

v0 = v1 * s
v0 = s * v1
v0 = v1 + v2
v0 = v1 - v2
s = v1[0]
s = v1[1]
s = v1[2]

Note, the last one is useful in some cases when dealing with vectors. The index should only work between 0 and 2, inclusive. Don't have to check for errors.

Also note, all operations occur component-wise.

Solution

#include <iostream>

class Vector {
 public:
    Vector() : x(0), y(0), z(0) {}
    Vector(double _x, double _y, double _z) : x(_x), y(_y), z(_z) {}

    Vector operator+(const Vector& o) {
        return Vector(x + o.x, y + o.y, z + o.z);
    }

    Vector operator-(const Vector& o) {
        return Vector(x - o.x, y - o.y, z - o.z);
    }

    Vector operator*(double s) {
        return Vector(x * s, y * s, z * s);
    }

    double& operator[](int i) {
        // Do you understand why this could work but isn't defined behaviour?
        // return (double*)(this)[i];
        switch (i) {
            case 0: return x;
            case 1: return y;
            case 2: return z;
        }
    }

 public:
    double x, y, z;
};

Vector operator*(double s, Vector v) {
    return v * s;  // why can we do this?
}

Detail Orientation

Contributed by Edward Hu.

Intended for CS31 Midterm 1. What is the output of the following code?

Solution

The answer is choice A.

#include <iostream>
using namespace std;

int main() {
  int n = 5;
  n = n % n + 5;
  if (n == 10)
        cout << "A" << endl;
  else if (n == 5)
  cout << "B";
  else 
  cout << "C" << endl;
  cout << "D";
  n = n + 2;
  if (n = 4)
  cout << "E" << endl;
  else
  cout << "F";
  cout << n;
  n == 5;
  switch (n) {
  case 1:
    cout << "G" << endl;
    n = n + 4;
  case 5:
    cout << "H" << endl;
  case 4:
    cout << "I";
  case 8:
    cout << "J";
    break;
  default:
    cout << "K";
  }
  n = n + 3;
  if (n == 3 || 1)
  cout << "L" << endl;
  else if (n == 4 || 5)
  cout << "M" << endl;
  else
  n == 3;
  cout << "N";
  if (n == 6 || 0)
  cout << "O";
  else
  n = n + 1;
  if (n == 8 || 0)
  cout << "P" << endl;
  cout << "Q" << endl;
  cout << n;
}

Loop Tracing:

Submission by Derek Xu

Consider the following program, which prints text to the terminal:

#include <iosteam>
#include <string.h>
using namespace std;

int main() {
        string prof = "David A. Smallberg";
        for (int i = 0; i < 10; ++i) {
                for (int j = i; j < 10; ++j) {
                        if ((i+j)%2 == 0)
                                cout << prof << " was here." << endl;
                        cout << "Go Bruins!";
                }
                if (i%3)
                        cout << "\n" << endl;
                if (i%10 == 0)
                        cout << "Be Careful!" << endl;
        }
}

How many lines are printed?
(a) 30
(b) 44
(c) 40
(d) 38
(e) 36

Solution

(b) 44

Explanation

    "... was here" is printed only when i is odd and j is odd
                                or when i and j are both even

    Draw out the times that i and j are run:
    i\j 0 1 2 3 4 5 6 7 8 9
    0   X   X   X   X   X
    1     X   X   X   X   X
    2       X   X   X   X 
    3         X   X   X   X
    4           X   X   X
    5             X   X   X
    6               X   X
    7                 X   X
    8                   X
    9                     X

    We can see this happens: 10 + 8 + 6 + 4 + 2 = 30 times

    0%10 == 0, therefore "Be Careful!" is printed 1 time
    
    To find total # of lines, we count the total number of endl's and \n's                there are 30 endl's from the "... was here." prints.
    there are 6 endl's and 6 '\n's from when i != 0,3,6,9
    there are 1 endl from the "Be Careful!" prints.        
    therefore, in total there are 44 lines.

Understanding Pass By Reference

Contributed by Destin Raymundo.

What is the output of following C++ code snippet?

#include <iostream>

using namespace std;

int foo(int& i) {
    int j = i;
    int count = 0;
    for (i = 0; i < 10; i += 2) {
        j--;
        count++;
    }
    return count;
}

int main() {
    int i = 1;
    int j = foo(i);
    cout << "i: " << i << endl;
    cout << "j: " << j << endl;
    return 0;
}

Choose one answer

A)

i: 10
j: 10

B)

i: 10
j: 5

C)

i: 1
j: 10

D)

i: 1
j: 5

Solution

The answer is B. The variable i is passed into foo() by reference. So anywhere i is mutated within foo(), it will also change i within main().

The variable j, from foo() takes on the value of i but it does not reference the i from main() because it is given a copy of i's data. So, j actually has no direct effect on any variable in main().

The variable count simply counts how many times the for loop in foo() iterates. The for loop terminates once i >= 10. i takes on the following values during the execution of the for loop: 2,4,6,8,10. It takes five iterations, so count is 5, and since it is returned and assigned to the j in main(), j is 5


Issues with Memory in Classes

Contributed by Deven Patel.

The following code snippet shows an example of how to use a dynamically allocated member variable in cases where you class may or may not contain another object. In this case, the child can or cannot have a toy, based on if he is given one or not.

#include<string>

using namespace std;

struct toy {
    string m_toyName;
};

class child {
 public:
        child(int weight, string name) {
            m_weight = weight;
            m_name = name;
            m_toy = nullptr;
        }
        void giveToy(string name) {
            m_toy = new(toy);
            m_toy->m_toyName = name;
        }
        bool hasToy() {
            return (m_toy != nullptr);
        }
        ~child() {
            delete m_toy;
        }
 private:
        int m_weight;
        string m_name;
        toy* m_toy;
};

Of the following options, which would throw an error or cause a memory leak while or after your program runs, given the child class above:
a) Giving a child more than one toy
b) Calling hasToy before you gave a child a toy
c) Creating a new child and setting him equal to an already existing child who doesn't have a toy.
d) Creating a new child and setting him equal to an already existing child who does have a toy.

Solution

a and d will cause issues given the current class.

a will cause a memory leak becuase when we give the child another toy, his first toy is still active, and we lose a pointer to that toy. That means that that toy stays allocated throughout the whole program and is never feed with a delete.

b is okay because the toy was initialized to the nullptr in the constructor, and the boolean statement will just evaluate as it should.

c is okay since the private variables will just be copied exactly by their values.

d is not okay becuase the private variables will be copied exactly by value, which means that both m_toys will point to the same spot once the child is copied, and when one child is destructed, the spot for the toy in memory is released. If say hasToy is run on the other child after that memory is released, an exepction will be thrown.

Clone this wiki locally