Showing posts with label chapter 4 exercises. Show all posts
Showing posts with label chapter 4 exercises. Show all posts

Friday, 29 March 2024

Chapter 4 // Exercises 1-10 - The C++ Programming Language

 For this exercise I'm using Visual Studio Community 2022 and the header file std_lib_facilities:

The exercises can be found online and are not actually in the book:

Chapter 4 - A Tour of C++: Containers and Algorithms
Exercise 1
When first reading this chapter, keep a record of information that was new or surprising to you. Later, use that list to focus your further studies.

1. I didn't know that for_each() is classed as an algorithm. The more you know.

Exercise 2
List 5 standard library containers.

1. std::vector
2. std::array
3. std::map
4. std::deque
5. std::list

Exercise 3
List 5 standard library algorithms.

1. for_each()
2. find()
3. search()
4. copy()
5. remove()

Exercise 4
List 5 standard library headers.

1. #include <string>
2. #include <list>
3. #include <iostream>
4. #include <vector>
5. #include <random>

Exercise 5
Write a program that reads a name (a string) and an age (an int) from the standard input stream cin. Then output a message including the name and age to the standard output stream cout.


Exercise 6
Redo exercise 5, storing several (name, age) pairs in a class. Doing the reading and writing using your own >> and << operators.


Exercise 7
Initialise a vector<int> with the elements 5, 9, -1, 200 and 0. Print it. Sort it, and print it again.


Exercise 8
Repeat exercise 7 with a vector<string> initialised with "Kant", "Plato", "Aristotle", "Kierkegaard", and "Hume".


Exercise 9
Open a file for writing (as an ofstream) and write a few hundred integers to it.


Exercise 10
Open the file of integers from exercise 9 for reading (as an ifstream) and read it.













Monday, 1 August 2016

Chapter 4 // Exercise 10 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 4 Exercise // 4.10

Write a program that plays the game "Rock, Paper, Scissors." Use a switch-statement to solve this exercise. Also the machine should give random answers (i.e., select the next rock, paper or scissors randomly). Real randomness is to hard to provide just now, so just build a vector with a sequence of values to be used as the "the next value". If you build the vector into the program, it will always play the same game, so maybe you should let the user enter some values. Try variations to make it less easy for the user to guess which move the machine will make next.



#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;


int main()
{
//create comp moves
cout << "We're going to play Rock, Paper, Scissors.\n";
cout << "First the computer needs some moves. How many moves should the pc have?:\n";
int compMoves = 0;
cin >> compMoves;

vector<char> moves;

cout << "\nOk. Please enter 'r', 'p' or 's':\n";

for (int i = 0; i < compMoves; ++i)
{
char rps;
cin >> rps;
if (rps != 'p' && rps != 'r' && rps != 's')
{
cout << "Sorry, invalid input. Try again: \n";
cin >> rps;
}
moves.push_back(rps);
}

//play the game
char loop = 'y';

while(loop == 'y')

cout << "\nLets play! Enter 'r', 'p' or 's': \n";
char playerMove;
int plays = 0; 
int cm2 = compMoves;
char compMove = moves[cm2 - 1];
cin >> playerMove;

cout << "\nYour move: " << playerMove << " || Comp Move: " << compMove << endl;

switch (playerMove)
{

case 'r':
switch (compMove)
{
case 'r':
cout << "Tie!! r1\n";
break;
case 's':
cout << "You win!r2\n";
break;
case 'p':
cout << "I win!r3\n";
break;
}
break;

case 'p':
switch (compMove)
{
case 'p':
cout << "Tie!!p1\n";
break;
case 'r':
cout << "You win!p2\n";
break;
case 's':
cout << "I win!p3\n";
break;
}
break;

case 's':
switch (compMove)
{
case 's':
cout << "Tie!!s1\n";
break;
case 'p':
cout << "You win!s2\n";
break;
case 'r':
cout << "I win!s3\n";
}
break;

default:
cout << "Sorry, not recogised.\n";
break;
}

--cm2;
++plays;
//reset comp moves so it doesn't go out of vector range
if (plays > compMoves) { cm2 == compMoves; plays = 0; }

cout << "Would you like to play again? y /n: \n";
cin >> loop;

while (loop != 'y' && loop != 'n')
{
cout << "Sorry, not recognised. Try again. y / n: \n";
cin >> loop;
}

}

cout << "Thanks for playing!\n";
keep_window_open();

return 0;
}

This one did my freaking nut in. I spent bloody hours on it and when it finally worked it was just so simple I wanted to bash my head in with the book. My main problem was I constantly kept going out of the vector range and my original while loop got stuck in an infinite loop. Once you've figured it out though, it is actually quite easy, it just sounds hard.

EDIT 18/03/2018

So exercise 11 of chapter 7 has us revisit 2 exercises of your choice from chapter 4 or 5, This was one of the ones I chose. First off I noticed that everything is done in main(). If there's one thing I've learnt over the chapters it's that a function should only have 1 purpose.

#include "stdafx.h"
#include "std_lib_facilities.h"
#include <Windows.h>
#include <time.h>

vector<char> rps = { 'r', 'p', 's'}; //assign a vector with rock, paper and scissors

//---------------------------------CLASS PC Moves//
class PCMoves
{
public:
void setMoves();
char playMove();

vector<char> moveset;
int compMoves;
};

//set the computer moves using number set in getMoves() and rand()
void PCMoves::setMoves()
{
char move;
int min = 0;
int max = 2;
int randNum;

//for each move, get a random move from the rockpaperscissors vector and push it into moveset
//pc is given 100 different options to choose from
for (int i = 0; i < 100; ++i)
{
randNum = rand() % (max - min + 1) + min; //get a random number between 0 and vector size
move = rps[randNum];   //move found at randNum number is assigned to move
PCMoves::moveset.push_back(move);       //that move is then pushed into moveset
}

return;
}

//returns a move from the pc's moveset
char PCMoves::playMove()
{
int min = 0;
int max = 99; //due to vectors starting at 0, we gave it 100 options
int randNum = rand() % (max - min + 1) + min;

return PCMoves::moveset[randNum];       //return a random move in the given moveset
}

PCMoves pcMoves;
//-------------------------------------END PC Moves//

//----------------------------------CLASS Play Game//
class PlayGame
{
public:
char getPlayerMove();
void checkMoves();
void playGame();
char playAgain();

char playerMove;
char yesNo;
};

//get a move from the player
char PlayGame::getPlayerMove()
{
cout << "\nEnter 'r', 'p' or 's':\n>";
cin >> PlayGame::playerMove;

while (PlayGame::playerMove != 'r' && PlayGame::playerMove != 'p' && PlayGame::playerMove != 's')
{
cout << "Sorry, that's not a correct move. Try again.\n>";
cin >> PlayGame::playerMove;
}

return PlayGame::playerMove;
}

//compare player to computer move to see who won
void PlayGame::checkMoves()
{
char playerMove = PlayGame::getPlayerMove(); //get a move from the player
char compMove = pcMoves.playMove(); //get a move from the pc

cout << "\nYour move: " << playerMove << " || Comp Move: " << compMove << endl;

//see who won
switch (PlayGame::playerMove)
{

case 'r':
switch (compMove)
{
case 'r':
cout << "Tie!!\n";
break;
case 's':
cout << "You win!\n";
break;
case 'p':
cout << "I win!\n";
break;
}
break;

case 'p':
switch (compMove)
{
case 'p':
cout << "Tie!!\n";
break;
case 'r':
cout << "You win!\n";
break;
case 's':
cout << "I win!\n";
break;
}
break;

case 's':
switch (compMove)
{
case 's':
cout << "Tie!!\n";
break;
case 'p':
cout << "You win!\n";
break;
case 'r':
cout << "I win!\n";
}
break;

default:
cout << "Sorry, not recogised.\n";
break;
}

return;
}

//ask users if they want to play again
char PlayGame::playAgain()
{
cout << "\nWould you like to play again? y /n: \n>";
cin >> PlayGame::yesNo;

while (yesNo != 'y' && yesNo != 'n')
{
cout << "Sorry, not recognised. Try again. y / n: \n>";
cin >> yesNo;
}

return yesNo;
}

void PlayGame::playGame()
{
cout << "We're going to play Rock, Paper, Scissors.\n";

//create compMoves
pcMoves.setMoves();
//continue to play until numOfMoves runs out or users wants to quit
while (PlayGame::yesNo != 'n')
{
//get moves from each player and compare the moves to see who won
PlayGame::checkMoves();

//ask users if they want to continue playing
PlayGame::yesNo = PlayGame::playAgain();
}

cout << "\nThanks for playing!\n";
Sleep(2000); //pause program for 2 seconds before closing

return;
}

PlayGame game;
//-----------------------------------------END Play Game//

//start program
int main()
{
//set seed for rand() based on pc's current time
srand(time(NULL));

//play game
game.playGame();

return 0;
}

The code is a lot bigger however, everything is done from within 2 classes and has appropriate error checking. I also changed the program so that instead of giving the pc a number of moves to create a 'random looking' sequence, it now pushes back 100 choices into a vector from another vector containing r, p or s. This provides almost real randomness to the pc's choices instead of choosing what it might select.

Most functions now only have 1 purpose; to either set or get values, check values or play the game. I wrote this code pretty much off the top of my head in about 40 minutes which is kind of shocking because I remember how long it took me to do this originally and how frustrated I got. It's crazy to think that practice and studying really do pay off. It also showed me some logic errors from the first time round and made me think "why did I do it that way?" But it's all a part of the learning process.

Saturday, 30 July 2016

Chapter 4 Exercise // 8 & 9 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 4 Exercise // 4.8 

There is an old story that the emperor wanted tot hank the inventor of the game of chess and asked the inventor to name his reward. The inventor asked for one grain of rice for the first square, 2 for the second, 4 for the third, and so on, doubling for each of the 64 squares. That may sound modest, but there wasn't that much rice in the empire! Write a program to calculate how many squares are required to give the inventor at least 1000 grains of rice, at least 1,000,000 grains, ad at least 1,000,000,000 grains. You'll need a loop, of course, and probably and int to keep track of which square you are at, an int to keep the number of grains on the current square and an int to keep track of the grains on all the previous squares. We suggest that you write out the value of all your variables for each iteration of the loop so that you can see what's going on.


#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;


int main()
{
int currentSquare = 1;
int allGrains = 1;

for (int grainsCS = 1; grainsCS < 1000000000; ++currentSquare)
{
cout << "You are on square number: " << currentSquare << endl;
cout << "The number of grains on this square is: " << grainsCS << endl;
cout << "The total number of grains so far is: " << allGrains << '\n' << endl;

grainsCS = grainsCS * 2;
allGrains += grainsCS;
}

keep_window_open();

return 0;
}

To get at least 1000 you need 10 squares.
To get at least 1,000,000 you need 20 squares.
Te get at least 1,000,000,000 you need 30 squares.

When I first read this exercise I honestly thought I wouldn't be able to solve it. But after having done all the previous exercises and becoming for more comfortable with for and while loops, this took me around an hour to solve. 


Chapter 4 Exercise // 4.9

Try to calculate the number of rice grains that the inventor asked for in exercise 8 above. You'll find that the number is so large that it won't fit in an int or a double. Observe what happens when the number gets too large to represent exactly as an int and as a double. What is the largest number of squares for which you can calculate the exact number of grains (using an int)? What is the largest number of squares for which you can calculate the approximate number of grains (using a double)?


#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;


int main()
{
int currentSquare = 1;
double allGrains = 1;

for (double grainsCS = 1; currentSquare <= 64; ++currentSquare)
{
cout << "You are on square number: " << currentSquare << endl;
cout << "The number of grains on this square is: " << grainsCS << endl;
cout << "The total number of grains so far is: " << allGrains << '\n' << endl;

grainsCS = grainsCS * 2;
allGrains += grainsCS;
}

keep_window_open();

return 0;
}

You can get up to square 32 on an int.
You can get to square 20 on a double before it starts showing it in notation form.



Thursday, 28 July 2016

Chapter 4 Exercise // 7 - Principles & Practice Using C++

In all these exercises I am using Visual Studio Community 2015 and the header file "std_lib_facilities.h" which can be found here:


http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


My version is spelt differently so adjust the code accordingly if copying and pasting.


Chapter 4 Exercise // 4.7

Modify the "mini calculator" from exercise 5 to accept (just) single-digit numbers written as either digits or spelled out.

#include "stdafx.h"
#include "std_lib_facilities_new_version.h"
using namespace std;

vector<string> values1{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
vector<string> values2{ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

char op; //the operation

//this function gets our digits
int get_digit()
{
int d_1 = 10; //this will test for bad input

cout << "Please enter a single digit 0 - 9 in numeric form or written (lower case): \n";
string digit;
cin >> digit;

//this checks for bad input on digit and loops till it's correct
while (d_1 != 0 && d_1 != 1 && d_1 != 2 && d_1 != 3 && d_1 != 4 && d_1 != 5 && d_1 != 6 && d_1 != 7 && d_1 != 8 && d_1 != 9)
{
for (int i = 0; i < values1.size(); ++i)
{
//this is for numeric input
if (digit == values1[i])
{
d_1 = i;
return i;
}

//this is for written input
else if (digit == values2[i])
{
d_1 = i;
return i;
}
}

if (d_1 != 0 && d_1 != 1 && d_1 != 2 && d_1 != 3 && d_1 != 4 && d_1 != 5 && d_1 != 6 && d_1 != 7 && d_1 != 8 && d_1 != 9)
{
cout << "Sorry, incorrect input. Please try again: \n";
cin >> digit;
}
}

d_1 = 10; //reset back to ten for future use
}

//this function gets the operation
char get_op()
{
cout << "Please enter an operation from, +, -, *, /: \n";
cin >> op;

while (op != '+' && op != '-' && op != '*' && op != '/')
{
cout << "Sorry, that operation is not recognised. Please try again: \n";
cin >> op;
}

return op;
}

int main()
{
char loop = 'y';

cout << "This program is a calculator for single digits.\n";

while (loop == 'y')


d1 = get_digit(); //first number
op = get_op(); //this will get the operation
d2 = get_digit(); //second number

double add = d1 + d2;
double minus = d1 - d2;
double mult = d1*d2;
double div = d1 / d2;

switch (op)
{
case '+':
cout << "The sum of " << d1 << " and " << d2 << " is: " << add << endl;
break;
case '-':
cout << d1 << " minus " << d2 << " is: " << minus << endl;
break;
case '*':
cout << d1 << " multiplied by " << d2 << " is: " << mult << endl;
break;
case '/':
cout << d1 << " divided by " << d2 << " is: " << div << endl;
break;
}

cout << "\nWould you like to use the calculator again? y / n\n";
cin >> loop;

while (loop != 'y' && loop != 'n')
{
cout << "Sorry, not recognised. Try again. y / n: \n";
cin >> loop;
}
}

keep_window_open();

return 0;
}

This one took me a few hours. I originally started off with it all in main, using if-statements for bad input and converting the input into an actual number. There was also code to get a second digit and it worked but it ran into quite a few lines of code and looked quite ugly. So I sat there and pondered on how I could make it more streamline. 

By turning the process of getting a digit into a function outside main, I could then just call that whenever necessary and by turning the process of getting the number into a while loop, the function also checks itself for bad input so you don't have to do it in main.

I then turned getting the op into a function, just to take it out of main and make it more readable. The last bit was then just a copy and paste job from the exercise mentioned.

The hardest part of all of this was getting it to check itself for bad input, the upside of that is I now understand while loops a hell of a lot more and I'm starting to feel much more comfortable using them.