diff --git a/solutions/CMakeLists.txt b/solutions/CMakeLists.txt index 09cff2a..68396c4 100644 --- a/solutions/CMakeLists.txt +++ b/solutions/CMakeLists.txt @@ -1,3 +1,5 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(chapter-01) +add_subdirectory(chapter-02) +add_subdirectory(chapter-03) diff --git a/solutions/chapter-02/CMakeLists.txt b/solutions/chapter-02/CMakeLists.txt new file mode 100644 index 0000000..ca5acc6 --- /dev/null +++ b/solutions/chapter-02/CMakeLists.txt @@ -0,0 +1,12 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +# The next lines represent a list of all the executables in the folder (chapter) +# There is typically one executable per exercise. +# As you solve exercises, you need to add them here. +# The syntax is add_executable(executable_name source_file_name) + +add_executable(ch-02-ex-02-solution ch-02-ex-02-solution.cpp) +add_executable(ch-02-ex-03-solution ch-02-ex-03-solution.cpp) +add_executable(ch-02-ex-04-solution ch-02-ex-04-solution.cpp) +add_executable(ch-02-ex-05-solution ch-02-ex-05-solution.cpp) +add_executable(ch-02-ex-06-solution ch-02-ex-06-solution.cpp) \ No newline at end of file diff --git a/solutions/chapter-02/ch-02-ex-02-solution.cpp b/solutions/chapter-02/ch-02-ex-02-solution.cpp new file mode 100644 index 0000000..62a3f60 --- /dev/null +++ b/solutions/chapter-02/ch-02-ex-02-solution.cpp @@ -0,0 +1,70 @@ +/* + * chapter-02-exercise-02.cpp + * + * Using the "if" clause + * + * Created on: Aug 19, 2012 + * Author: Radu Popescu + */ + +#include + +int main(int argc, char *argv[]) { + double p, q, x, y; + int j; + + /* + * Read p + */ + std::cout << "Please input value of p (double): "; + std::cin >> p; + /* + * Read q + */ + std::cout << "Please input value of q (double): "; + std::cin >> q; + /* + * Read y + */ + std::cout << "Please input value of y (double): "; + std::cin >> y; + /* + * Read j + */ + std::cout << "Please input value of j (integer): "; + std::cin >> j; + + /* + * Set x to 5 if either p is greater than or equal to q, or the variable + * j is not equal to 10 + */ + if ((p >= q) || (j != 10)) { + x = 5; + } + + /* + * Set x to 5 if both y is greater than or equal to q, and the variable j + * is equal to 20. Otherwise set x to p + */ + if ((y >= q) && (j == 20)) { + x = 5; + } else { + x = p; + } + + /* + * Set x according to rule at ex 2.2.3 + */ + if (p > q) { + x = 0; + } else if (j == 10) { + x = 1; + } else { + x = 2; + } + + // Print out x + std::cout << "The value of x is: " << x << std::endl; + + return 0; +} diff --git a/solutions/chapter-02/ch-02-ex-03-solution.cpp b/solutions/chapter-02/ch-02-ex-03-solution.cpp new file mode 100644 index 0000000..9757792 --- /dev/null +++ b/solutions/chapter-02/ch-02-ex-03-solution.cpp @@ -0,0 +1,57 @@ +/* + * chapter-02-exercise-04.cpp + * + * Using the while loop + * + * Created on: Aug 19, 2012 + * Author: Radu Popescu + */ + +#include + +int main(int argc, char *argv[]) { + int number = 0, sum = 0; + + /* + * Point 1. Terminate reading numbers when -1 is input by the user + */ + while (number >= 0) { + sum += number; + std::cout << "Please input numbers. Terminate with -1 :"; + std::cin >> number; + } + std::cout << "The sum of the numbers is: " << sum << std::endl; + + /* + * Point 2. Terminate reading numbers when -1 is input by the user + * or when sum exceedes 100. + */ + do { + std::cout << "Please input numbers. Terminate with -1 :"; + std::cin >> number; + if (number != -1) + sum += number; + } while ((number >= 0) && (sum <= 100)); + std::cout << "The sum of the numbers is: " << sum << std::endl; + + /* + * Point 3. Reset sum by inputting -2 + */ + do { + std::cout << "Please input numbers. Terminate with -1. Reset with -2 :"; + std::cin >> number; + switch (number) { + case -1: + break; + case -2: + sum = 0; + break; + default: + sum += number; + break; + } + } while ((number >= 0) && (sum <= 100)); + std::cout << "The sum of the numbers is: " << sum << std::endl; + + return 0; +} diff --git a/solutions/chapter-02/ch-02-ex-04-solution.cpp b/solutions/chapter-02/ch-02-ex-04-solution.cpp new file mode 100644 index 0000000..0b0e09a --- /dev/null +++ b/solutions/chapter-02/ch-02-ex-04-solution.cpp @@ -0,0 +1,112 @@ +/* + * chapter-02-exercise-04.cpp + * + * Vector operations with loops + * + * Created on: Aug 19, 2012 + * Author: Radu Popescu + */ + +#include + +int main(int argc, char *argv[]) { + double u[3] = {1.0, 2.0, 3.0}; + double v[3] = {6.0, 5.0, 4.0}; + double A[3][3] = {{1.0, 5.0, 0.0}, {7.0, 1.0, 2.0}, {0.0, 0.0, 1.0}}; + double B[3][3] = {{-2.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {4.0, 1.0, 0.0}}; + double w[3]; + for (int i = 0; i < 3; ++i) { + w[i] = u[i] - 3.0 * v[i]; + } + + // x = u - v + double x[3] = {0.0, 0.0, 0.0}; + for (int i = 0; i < 3; ++i) { + x[i] = u[i] - v[i]; + } + + // y = Au + double y[3] = {0.0, 0.0, 0.0}; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + y[i] += A[i][j] * u[j]; + } + } + + // z = Au - v + double z[3] = {0.0, 0.0, 0.0}; + for (int i = 0; i < 3; ++i) { + z[i] -= v[i]; + for (int j = 0; j < 3; ++j) { + z[i] += A[i][j] * u[j]; + } + } + + // C = 4A - 3B + double C[3][3]; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + C[i][j] = 4 * A[i][j] - 3 * B[i][j]; + } + } + + // D = AB + double D[3][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + for (int k = 0; k < 3; ++k) { + D[i][j] += A[i][k] * B[k][j]; + } + } + } + + // Print w + std::cout << "w is: "; + for (int i = 0; i < 3; ++i) { + std::cout << w[i] << " "; + } + std::cout << std::endl; + + // Print x + std::cout << "x is: "; + for (int i = 0; i < 3; ++i) { + std::cout << x[i] << " "; + } + std::cout << std::endl; + + // Print y + std::cout << "y is: "; + for (int i = 0; i < 3; ++i) { + std::cout << y[i] << " "; + } + std::cout << std::endl; + + // Print z + std::cout << "z is: "; + for (int i = 0; i < 3; ++i) { + std::cout << z[i] << " "; + } + std::cout << std::endl; + + // Print C + std::cout << "C is:" << std::endl; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + std::cout << C[i][j] << " "; + } + std::cout << std::endl; + } + std::cout << std::endl; + + // Print D + std::cout << "D is:" << std::endl; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + std::cout << D[i][j] << " "; + } + std::cout << std::endl; + } + std::cout << std::endl; + + return 0; +} diff --git a/solutions/chapter-02/ch-02-ex-05-solution.cpp b/solutions/chapter-02/ch-02-ex-05-solution.cpp new file mode 100644 index 0000000..61495a8 --- /dev/null +++ b/solutions/chapter-02/ch-02-ex-05-solution.cpp @@ -0,0 +1,37 @@ +/* + * chapter-02-exercise-05.cpp + * + * Inverse for 2x2 matrix + * + * Created on: Aug 19, 2012 + * Author: Radu Popescu + */ + +#include +#include + +int main(int argc, char *argv[]) { + double A[2][2] = {{4, 10}, {1, 1}}; + + // Compute the determinant + double det = A[0][0] * A[1][1] - A[0][1] * A[1][0]; + assert(det != 0); + + // Compute the inverse + double Ainv[2][2]; + Ainv[0][0] = A[1][1] / det; + Ainv[0][1] = -A[0][1] / det; + Ainv[1][0] = -A[1][0] / det; + Ainv[1][1] = A[0][0] / det; + + // Print out inverse + std::cout << "The inverse of A is:" << std::endl; + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + std::cout << Ainv[i][j] << " "; + } + std::cout << std::endl; + } + + return 0; +} diff --git a/solutions/chapter-02/ch-02-ex-06-solution.cpp b/solutions/chapter-02/ch-02-ex-06-solution.cpp new file mode 100644 index 0000000..ed08f70 --- /dev/null +++ b/solutions/chapter-02/ch-02-ex-06-solution.cpp @@ -0,0 +1,38 @@ +/* + * chapter-02-exercise-05.cpp + * + * Newton-Raphson iteration for f(x) = exp(x) + x^3 + 5 = 0; x0 = 0; + * + * Created on: Aug 19, 2012 + * Author: Radu Popescu + */ + +#include +#include + +int main(int argc, char *argv[]) { + // Define a stopping precision + double epsilon = 1e-6; + int max_iter = 1000; + double x_prev = 0.0; + double x_next = 0.0; + + int num_iter = 0; + do { + x_prev = x_next; + x_next = x_prev - (exp(x_prev) + pow(x_prev, 3) + 5) / + (exp(x_prev) + 3 * pow(x_prev, 2)); + ++num_iter; + std::cout << "x[" << num_iter << "] = " << x_next << std::endl; + } while ((std::abs(x_next - x_prev) > epsilon) && (num_iter < max_iter)); + + if ((num_iter == max_iter) && (std::abs(x_next - x_prev) > epsilon)) { + std::cout << "Max number of iterations reached without convergence" + << std::endl; + } else { + std::cout << "The solution to exp(x) + x^3 + 5 = 0 is: " << x_next + << std::endl; + } + + return 0; +} diff --git a/solutions/chapter-03/CMakeLists.txt b/solutions/chapter-03/CMakeLists.txt new file mode 100644 index 0000000..1aa79f2 --- /dev/null +++ b/solutions/chapter-03/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +# The next lines represent a list of all the executables in the folder (chapter) +# There is typically one executable per exercise. +# As you solve exercises, you need to add them here. +# The syntax is add_executable(executable_name source_file_name) + +add_executable(ch-03-ex-01-solution ch-03-ex-01-solution.cpp) +add_executable(ch-03-ex-02-solution ch-03-ex-02-solution.cpp) +add_executable(ch-03-ex-03-solution ch-03-ex-03-solution.cpp) diff --git a/solutions/chapter-03/ch-03-ex-01-solution.cpp b/solutions/chapter-03/ch-03-ex-01-solution.cpp new file mode 100644 index 0000000..bf46c7b --- /dev/null +++ b/solutions/chapter-03/ch-03-ex-01-solution.cpp @@ -0,0 +1,47 @@ +/* + * chapter-03-exercise-01.cpp + * + * Print to file with a given precision + * + * Created on: Sep 2, 2012 + * Author: Radu Popescu + */ + +#include +#include + +int main(int argc, char *argv[]) { + double x[4] = {0.0, 1.0, 1.0, 0.0}; + double y[4] = {0.0, 0.0, 1.0, 1.0}; + + std::ofstream output_file("x_and_y.dat"); + // Check that file is properly openened. + if (!output_file.is_open()) { + std::cout << "Error opening output file." << std::endl; + return 1; + } + + // Output in scientific format with 10 significant figures + // and always showing sign + output_file.setf(std::ios::scientific); + output_file.setf(std::ios::showpos); + output_file.precision(10); + // Write x vector ending with a new line + for (int i = 0; i < 4; ++i) { + output_file << x[i] << " "; + } + output_file << "\n"; + // Flush after writing vector x + output_file.flush(); + // Do the same for y vector + for (int i = 0; i < 4; ++i) { + output_file << y[i] << " "; + } + output_file << "\n"; + // Flush after writing vector y + output_file.flush(); + // Close the file when finished + output_file.close(); + + return 0; +} diff --git a/solutions/chapter-03/ch-03-ex-02-solution.cpp b/solutions/chapter-03/ch-03-ex-02-solution.cpp new file mode 100644 index 0000000..bb9b5d2 --- /dev/null +++ b/solutions/chapter-03/ch-03-ex-02-solution.cpp @@ -0,0 +1,48 @@ +/* + * chapter-03-exercise-02.cpp + * + * Count number of rows in a file + * + * Created on: Sep 2, 2012 + * Author: Radu Popescu + */ + +#include +#include +#include + +int main(int argc, char *argv[]) { + std::ifstream read_file("x_and_y.dat"); + if (!read_file.is_open()) { + std::cout << "Error opening file." << std::endl; + return 1; + } + + int number_of_rows = 0; + + // This loop will read an empty line between the final EOL and the EOF + // characters + while (!read_file.eof()) { + double dummy1, dummy2, dummy3, dummy4; + read_file >> dummy1 >> dummy2 >> dummy3 >> dummy4; + number_of_rows++; + } + std::cout << "Number of rows = " << number_of_rows << " (false)" << std::endl; + + // We try again + number_of_rows = 0; + read_file.clear(); + read_file.seekg(std::ios::beg); + while (!read_file.eof()) { + std::string line; + getline(read_file, line); + if (line.compare("") != 0) { + number_of_rows++; + } + } + std::cout << "Number of rows = " << number_of_rows << " (true)" << std::endl; + + read_file.close(); + + return 0; +} diff --git a/solutions/chapter-03/ch-03-ex-03-solution.cpp b/solutions/chapter-03/ch-03-ex-03-solution.cpp new file mode 100644 index 0000000..56daaf8 --- /dev/null +++ b/solutions/chapter-03/ch-03-ex-03-solution.cpp @@ -0,0 +1,64 @@ +/* + * chapter-03-exercise-03.cpp + * + * Implements the backward Euler method to solve: + * dy / dx = -y, y_0 = 1, 0 <= x <= 1 + * + * The discretization for N grid points is: + * - step size: h = 1 / (N - 1) + * - grid points: x_n = n * h + * - solution: y_(n) - y_(n-1) / h = - y_n ; n = 1,2,...N-1 + * + * + * Created on: Sep 2, 2012 + * Author: Radu Popescu + */ + +#include +#include +#include + +int main(int argc, char *argv[]) { + // Read from the command line the number of grid points to use + int N; + std::cout << "Please input the number of grid points. N = "; + std::cin >> N; + assert(N > 1); + + // Calculate step size h + double h = 1.0 / (N - 1); + std::cout << "Computed step size. h = " << h << std::endl; + + // Start computing the grid points and the solution in these points + // At each step, we output the solution to disk + std::ofstream output_file("xy.dat"); + if (!output_file.is_open()) { + std::cout << "Error opening output file." << std::endl; + return 1; + } + output_file.setf(std::ios::scientific); + output_file.setf(std::ios::showpos); + output_file.precision(9); + + // x_(n-1) = x_0 = 0 + double x_prev = 0; + // x_(n) = x_1 = h; + double x_next = h; + // y_(n-1) = y_0 = 1; + double y_prev = 1; + double y_next; + + output_file << x_prev << " " << y_prev << std::endl; + + while (x_next <= 1.0) { + y_next = y_prev / (h + 1.0); + output_file << x_next << " " << y_next << std::endl; + y_prev = y_next; + x_prev = x_next; + x_next = x_prev + h; + } + + output_file.close(); + + return 0; +}