Friday, 5 August 2016

Chapter 4 // Exercise 16 - 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.16

In the drill you wrote a program that, given a series of numbers, found the max and min of that series. the number that appears the most times in a sequence is called the mode. Create a program that finds the mode of a set of positive integers.

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

int main()
{
vector<int> numbers;

cout << "Enter a set of numbers (press enter then ctrl+z when finished): \n";
int n;
while (cin >> n)
{
numbers.push_back(n);
}

sort(numbers);

int number = 0;
int mode = 0;
int highCount = 0;
int mostOccurring;
int count = 0;

for (int i = 0; i < numbers.size(); ++i)
{
cout << numbers[i] << " ";
}

for (int i = 0; i < numbers.size(); ++i)
{

if (i == 0) // get the ball rolling
{
number = numbers[i];
++count;
}

else 
{
if (number == numbers[i])
{
++count;
mode = numbers[i];
}
else
{
if (highCount == 0) 
{
highCount = count;
mostOccurring = mode;
}

if (count > highCount)
{
highCount = count;
mostOccurring = mode;
}
else
{
number = numbers[i];
count = 1;
}

}

}

}

cout << "\nThe mode is: " << mostOccurring;
cout << "\nAppearing " << highCount << " time(s)" << endl;


keep_window_open();

return 0;
}

This one took me a while but it was just a matter of getting the if statements to execute correctly. I mainly took inspiration from the exercise he mentions above and edited it.

Basically, it reads a set of integers into a vector. Sorts them, then on every loop checks if the current number was the same as the last. If it is, the count increases until it hits a different number. Then that number and count is stored, the comparing numbers are reset and it starts all over again. If it encounters a count higher than the one stored, the most occurring number and highest count is replaced by those. 

Wednesday, 3 August 2016

Chapter 4 // Exercise 11, 12, 13, 14, 15 - 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.11

Create a program to find all the prime numbers between 1 and 100. One way to do this is to write a function that will check if a number is a prime (i.e., see if the number can be divided by a prime smaller than itself) using a vector of primes in order (so that if the vector is called primes, primes[0]==2, primes[1]==3, primes[2]==5, etc). Then write a loop that goes from 1 to 100, checks each number to see if it is a prime, and stores each prime found in a vector. Write another loop that lists the primes you found. You might check your result by comparing your vector of prime number with primes. Consider 2 the first prime.

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

vector<int> user_primes; // vector to put found primes into
vector<int> primes{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,}; // to compare against

bool isItPrime(int n) 
{
for (int p = 0; p < user_primes.size(); ++p)
{
if (n % user_primes[p] == 0)
return false;
}
return true;

}

int main()
{
user_primes.push_back(2);

for (int i = 3; i <= 100; ++i)
{
if (isItPrime(i))
user_primes.push_back(i);
}

for (int i = 0; i < primes.size(); ++i)
{
cout << primes[i] << '\t' << user_primes[i] << '\n';
}

keep_window_open();

return 0;
}

I spent so many hours trying to solve this one, so many hours scouring the internet but they all solved it using methods that hadn't been taught yet. I then even found Bjarne himself answer this question using methods he had fucking taught yet (talk about not even reading your own book). The way the question is written it sounds like he is implicitly asking you to check all numbers from 1 to 100 are prime by dividing them by a smaller number from within another vector called primes containing primes numbers from 1 - 100. Talk about misleading. He actually wants you to just write a function that finds a prime and then returns that number into a vector. 

So basically I had to end up using a bool function which I still don't fully understand. In chapters 1 - 4 all he has said is that a bool is true or false. I also had to start at 3 otherwise it would never work (even though he says to start at 1 in the book, his own website solves this starting at 3. I was rage quitting for hours). So it checks to see if the number is divisible by any primes already pushed back (so obviously, primes smaller than itself).

For a better understanding of bool values, look here. This is the website I use when Bjarne makes no fucking sense. The author Alex, makes things much easier to understand. 

This was a terribly written exercise.

Chapter 4 Exercise // 4.12

Modify the program described in the previous exercise to take an input value max and then find all the prime numbers from 1 to max.

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

vector<int> user_primes; // vector to put found primes into
vector<int> primes{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,}; // to compare against

bool isItPrime(int n)
{
for (int p = 0; p < user_primes.size(); ++p)
{
if (n % user_primes[p] == 0)
return false; // n divided
}
return true; // n couldn't be divided

}

int main()
{
user_primes.push_back(2);

cout << "Please give a maximum number the computer should stop finding primes at:\n";
int max;
cin >> max;

for (int i = 3; i <= max; ++i)
{
if (isItPrime(i))
user_primes.push_back(i);
}

for (int i = 0; i < user_primes.size(); ++i)
{
cout << '\n' << user_primes[i];
}

cout << '\n';
keep_window_open();

return 0;
}



Chapter 4 Exercise // 4.13

Create a program to find all the prime numbers between 1 and 100. there is a classic method for doing this, called the "Sieve of Eratosthenes." Write your program using this method.

At this point in my programming knowledge, I honestly don't know how to do this using only methods he has shown us so far in the book. I've looked everywhere and I just don't understand whats going on. If someone could perhaps explain it to me in dunce terms that would be greatly appreciated but until I'm a more proficient programmer the answer to this one (and below) will have to wait.

EDIT 17/09/2019 - 3 years later I have now completed exercises 13 & 14. You can find the code for them at my git repository: https://github.com/l-paz91/principles-practice/tree/master/Chapter%204

I followed the pseudocode given on Wikipedia here: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithmic_complexity

This time is took me around 30 minutes to solve and I'm quite happy to see just how much my ability to read other code (pseudo or not) has progressed. It also is very possible to do this exercise using methods only shown up to chapter 4 but my problem solving skills were not as developed. I still have a long way to go but I've improved. 

Basically though, this method is quite a contrived way of doing it but I understand why he made us do it. I don't fully understand how it works, but the pseudocode is simple enough to follow to get it working.

Chapter 4 Exercise // 4.14

Modify the program described in the previous exercise to take an input value max and then find all the prime numbers from 1 to max.



Chapter 4 Exercise // 4.15

Write a program that takes an input value n and then finds the first n primes.


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

vector<int> user_primes; // vector to put found primes into
vector<int> primes{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,}; // to compare against

bool isItPrime(int n)
{
for (int p = 0; p < user_primes.size(); ++p)
{
if (n % user_primes[p] == 0)
return false; // n divided
}
return true; // n couldn't be divided

}

int main()
{
user_primes.push_back(2);

cout << "What number do you want to find primes from?: \n";
int countFrom;
cin >> countFrom;

double maxPrime = countFrom * 100;

for (int i = 3; i <= maxPrime; ++i)
{
if (isItPrime(i))
user_primes.push_back(i);
}

int countTo = countFrom*2;

for (int i = countFrom-1; i <= countTo-2; ++i) //this starts at n and continues n times
{
cout << '\n' << user_primes[i];
}

cout << '\n';
keep_window_open();

return 0;
}

I was a little confused on this one for a while as I thought he meant enter a number (n) and then find that many primes starting from the beginning. But then I realised that was exactly the same as 4.12, so he actually meant start at 'n' and then find the next 'n' numbers from 'n'. 

After some messing around it wasn't too hard, the function to find primes doesn't actually need to be tinkered all that much, you just need to make sure that it finds enough primes to print out.

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.