Cryptarithmetic puzzle - c++

I am trying to solve this cryptarithmetic puzzle TWO + TWO = FOUR and I used a raw brute force, but I can't figure out where I am making mistake. The idea here is that it tries all possible combinations of numbers from 0 to 10 and all numbers that are assigned to characters must be distinct. By definition
a cryptarithmetic puzzle is a mathematical game where the digits of
some numbers are represented by letters (or symbols). Each letter
represents a unique digit. The goal is to find the digits such that a
given mathematical equation is verified:
In this case:
TWO
+ TWO
------
= FOUR
This code goes through all possible combinations until it finds the solution that satisfies the problem. Constraint for it is given in else if statement.
First if statement simply checks if numbers are same, and if they are, it just skips that iteration.
My desired output is to see all correct solutions displayed.
int T, W, O, F, U, R;
for (T = 0; T < 10; T++)
{
for (W = 0; W < 10; W++)
{
for (O = 0; O < 10; O++)
{
for (F = 0; F < 10; F++)
{
for (U = 0; U < 10; U++)
{
for (R = 0; R < 10; R++)
{
if ((T == W) || (T == O) || (T == F) || (T == U) || (T == R) || (W == O) || (W == F) || (W == U) || (W == R) || (O == F) || (O == U) || (O == R) || (F == U) || (F == R) || (U == R))
{
continue;
}
else if (200 * T + 20 * W + 2 * O == F * 1000 + O * 100 + U * 10 + R * 0) {
cout << "T = " << T << endl
<< "W = " << W << endl
<< "O = " << O << endl
<< "F = " << F << endl
<< "U = " << U << endl
<< "R = " << R << endl << endl;
break;
}
}
}
}
}
}
}
I get bunch of results and interestingly enough, only the last result is fine, where it gives:
T = 7
W = 6
O = 5
F = 1
U = 3
R = 0

R * 0 should be R * 1 .
The answer you got that happened to be correct was the one where R = 0 (because when R is 0, R * 0 is the same as R * 1). I guess you also want to start F from 1 as typically cryptarithms don't allow leading zeros.

Related

Having trouble with a C++ program outputting to a file

I am a complete novice in programming and am currently taking an introductory level class at my local university, I am currently stuck on a question and the prof provides no help whatsoever.
I am taking 3 inputs from an input file molecules.txt (the first two are element names, the third is the number of the surrounding atoms) and printing them into an output file called geometricalshapes.txt
When I run my program nothing gets printed into the output file
Here is the code I have so far that does not work:
/******************************************************************************************************
* Problem Statement: This program will calculate the molecular geometry of atom A surrounded by b atoms of element B and output the results into a file geometricalshapes.txt
*
* Input: A list of element pairs from molecules.txt, and the number of B atoms surrounding atom A
*
* Output: The determined shape of the element pairs
*
* Main Algorithm: Determine the number of valence electrons 'v' for atom A
* Subtract the number of bonding domains 'b' from 'v' to determine the number of nonbonding electrons
* Determine the number of bonding domains 'n'
* Determine the shape of the molecule
* Ouput the geometrical shape of the molecule
*
* Major Variables: string A - Central Atom
* string B - Surrounding Atom
* string shape - Shape of Molecule
* int b - Number of B atoms
* int v - Number of Valence Electrons
* int e - Number of Nonbonding Elctrons
* int n - Number of Bonding Domains
*
*
* Assumptions: Only single bonds are present
*
* Limitations: Only coded for select elements from given tables
*
* *********************************************************************************************************************************************************************************/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// Declaring Variables
string A, B, shape;
int b, v, e, n;
ifstream inputData;
ofstream outputData;
inputData.open("molecules.txt");
if (!inputData)
{
cout << "Problem opening input file. Closing program..." << endl;
return 1;
}
outputData.open("geometricalshape.txt");
if (!outputData)
{
cout << "Problem opening output file. Closing program..." << endl;
return 2;
}
// Gathering data for central atom A
inputData >> A; // priming read
while (inputData) // EOF loop
{
// If-else statements to determine number of valence electrons 'v'
if (A == "Be")
{
v = 3;
}
else if (A == "C")
{
v = 4;
}
else if (A == "Si")
{
v = 4;
}
else if (A == "N")
{
v = 5;
}
else if (A == "P")
{
v = 5;
}
else if (A == "As")
{
v = 5;
}
else if (A == "O")
{
v = 6;
}
else if (A == "S")
{
v = 6;
}
else if (A == "Se")
{
v = 6;
}
else if (A == "F")
{
v = 7;
}
else if (A == "Cl")
{
v = 7;
}
else if (A == "Br")
{
v = 7;
}
else if (A == "I")
{
v = 7;
}
else if (A == "Xe")
{
v = 8;
}
// Input data for surroudning atom and number of atoms
inputData >> B >> b;
// Calculating number of nonbonding electrons
e = v - b;
// Calculating number of bonding doamains
n = e / 2;
// If else statements to determine shape
if (b == 2 && n == 0)
{
shape == "linear";
}
else if (b == 2 && n == 1)
{
shape == "bent";
}
else if (b == 2 && n == 2)
{
shape == "bent";
}
else if (b == 2 && n == 3)
{
shape == "linear";
}
else if (b == 3 && n == 0)
{
shape == "trigonal planar";
}
else if (b == 3 && n == 1)
{
shape == "trigonal pyramidal";
}
else if (b == 3 && n == 2)
{
shape == "T-shaped";
}
else if (b == 4 && n == 0)
{
shape == "tetrahedral";
}
else if (b == 4 && n == 1)
{
shape == "seesaw";
}
else if (b == 4 && n == 2)
{
shape == "square planar";
}
else if (b == 5 && n == 0)
{
shape == "trigonal bipyramidal";
}
else if (b == 5 && n == 1)
{
shape == "square pyramidal";
}
else if (b == 6 && n == 0)
{
shape == "octahedral";
}
else
{
shape == "unknown";
}
// Outputting line data into output document
outputData << "The geometrical shape of one atom " << A << " surrounded by " << b << " "
<< B << " atoms is " << shape << endl;
// Getting next input for A
inputData >> A;
}
return 0;
}
The first few lines on the input file look like:
O F 2
S F 4
Be F 3
C P 1
And I am supposed to get results that look like:
The geometrical shape of one O atom surrounded by 2 F atoms is bent.
The geometrical shape of one S atom surrounded by 4 F atoms is seesaw.
The geometrical shape of one Be atom surrounded by 3 F atoms is trigonal planar.
The geometrical shape of one C atom surrounded by 1 P atoms is unknown.
Any and all help is appreciated! Please try and keep explanations simple as I am still very new to programming!
Among the problems
incorrect file init testing.
untested extractions of B and b
unused test expressions shape == rather than assignments
Fixing all of the above:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// Declaring Variables
ifstream inputData("molecules.txt");
ofstream outputData("geometricalshape.txt");
if (!inputData.is_open())
{
cout << "Problem opening input file. Closing program..." << endl;
return 1;
}
if (!outputData.is_open())
{
cout << "Problem opening output file. Closing program..." << endl;
return 2;
}
string A, B, shape;
int b, v, e, n;
while (inputData >> A >> B >> b) // EOF loop
{
// If-else statements to determine number of valence electrons 'v'
if (A == "Be")
{
v = 3;
}
else if (A == "C")
{
v = 4;
}
else if (A == "Si")
{
v = 4;
}
else if (A == "N")
{
v = 5;
}
else if (A == "P")
{
v = 5;
}
else if (A == "As")
{
v = 5;
}
else if (A == "O")
{
v = 6;
}
else if (A == "S")
{
v = 6;
}
else if (A == "Se")
{
v = 6;
}
else if (A == "F")
{
v = 7;
}
else if (A == "Cl")
{
v = 7;
}
else if (A == "Br")
{
v = 7;
}
else if (A == "I")
{
v = 7;
}
else if (A == "Xe")
{
v = 8;
}
// Calculating number of nonbonding electrons
e = v - b;
// Calculating number of bonding doamains
n = e / 2;
// If else statements to determine shape
if (b == 2 && n == 0)
{
shape = "linear";
}
else if (b == 2 && n == 1)
{
shape = "bent";
}
else if (b == 2 && n == 2)
{
shape = "bent";
}
else if (b == 2 && n == 3)
{
shape = "linear";
}
else if (b == 3 && n == 0)
{
shape = "trigonal planar";
}
else if (b == 3 && n == 1)
{
shape = "trigonal pyramidal";
}
else if (b == 3 && n == 2)
{
shape = "T-shaped";
}
else if (b == 4 && n == 0)
{
shape = "tetrahedral";
}
else if (b == 4 && n == 1)
{
shape = "seesaw";
}
else if (b == 4 && n == 2)
{
shape = "square planar";
}
else if (b == 5 && n == 0)
{
shape = "trigonal bipyramidal";
}
else if (b == 5 && n == 1)
{
shape = "square pyramidal";
}
else if (b == 6 && n == 0)
{
shape = "octahedral";
}
else
{
shape = "unknown";
}
// Outputting line data into output document
outputData << "The geometrical shape of one atom " << A
<< " surrounded by " << b
<< " " << B
<< " atoms is " << shape
<< endl;
}
return 0;
}
Output (geometricalshape.txt)
The geometrical shape of one atom O surrounded by 2 F atoms is bent
The geometrical shape of one atom S surrounded by 4 F atoms is seesaw
The geometrical shape of one atom Be surrounded by 3 F atoms is trigonal planar
The geometrical shape of one atom C surrounded by 1 P atoms is unknown

Disease Outbreak Simulation using SIR model

I have a homework where I have to write a C++ program to simulate a disease outbreak using SIR model (Susceptible, Infectious, Recover). The requirement is to use a 2D-array with 7x7 size where user will choose an X and Y coordinate to initialize an infectious person. A Susceptible person (S) will become infected (I) if there is an infected person in adjacent. Then an infected person will recover (R) if there is a Recover person in adjacent. The program will end if all people are recovered.
Example output:
Day 0 Day 1 Day 2
s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s i i i i i s
s s s s s s s s s i i i s s s i r r r i s
s s s i s s s s s i r i s s s i r r r i s
s s s s s s s s s i i i s s s i r r r i s
s s s s s s s s s s s s s s s i i i i i s
s s s s s s s s s s s s s s s s s s s s s
So far, I can only check the state in position (1,1), (1,7), (7,1), (7,7). If the next three position next to it have an infected person, it will update the state to nextDayState.
Here is my code so far for two functions, SpreadingDisease and RecoverState.
void recoverState(char currentDayState[SIZE][SIZE], char nextDayState[SIZE][SIZE], int sizeOfArray)//It will take in the currentState of Day 0. I also copy the elements in currentState to nextDayState so that it could work.
{
for (int i = 1; i < sizeOfArray + 1; ++i)
{
for (int j = 1; j <= sizeOfArray + 1; ++j)
{
if (currentDayState[i][j] == 'i')//If found any Infected, update it to Recover on the nextDayState array.
{
nextDayState[i][j] == 'r';
}
}
}
for (int i = 1; i < sizeOfArray + 1; ++i)
{
for (int j = 1; j <= sizeOfArray + 1; ++j)
{
currentDayState[i][j] = nextDayState[i][j];
//After all people are recover, update the currentState and output it to terminal.
}
}
}
void spreadDisease(const char currentDayState[SIZE][SIZE], char nextDayState[SIZE][SIZE], int sizeOfArray, int day = 1)
{
for (int i = 1; i < sizeOfArray + 1; ++i)
{
for (int j = 1; j <= sizeOfArray + 1; ++j)
{
if (currentDayState[i][j] == 's')
{
if (i == 1 && j == 1)
{
if (currentDayState[1][2] == 'i' || currentDayState[2][1] == 'i' || currentDayState[2][2] == 'i')
{
nextDayState[1][1] = 'i';
}
}
if (i == 1 && j == 7)
{
if (currentDayState[1][6] == 'i' || currentDayState[2][6] == 'i' || currentDayState[2][7] == 'i')
{
nextDayState[1][7] = 'i';
}
}
if (i == 7 && j == 1)
{
if (currentDayState[6][1] == 'i' || currentDayState[6][2] == 'i' || currentDayState[7][2] == 'i')
{
nextDayState[7][1] = 'i';
}
}
if (i == 7 && j == 7)
{
if (currentDayState[6][6] == 'i' || currentDayState[7][6] == 'i' || currentDayState[6][7] == 'i')
{
nextDayState[7][7] = 'i';
}
}
}
}
}
}
I figure out that If I can somehow get the X and Y coordinate from the user, then I can use that coordinate to update the state of the next day. Unfortunately, I don't know how to assign the X and Y coordinate into the function to start with it.
P/S: Thank you for all of your answers. I very appreciate your kindness. However, I should have mentioned the requirement of my assignment before. Since I only study till the User-Defined Functions part, I am not allowed to use anything else beyond that. So I am limited to use 2D-array, If-else, Looping only to solve this problem. Map and Vector is far beyond my knowledge right now xD.
This assignment remembered me to my days at the University (and that's quite long ago).
It seems like a variant of Conway's Game of Life which I got as assignment when I was first year's student. Hence, I couldn't resist...
Some notes before:
Two dimensional arrays are a bit inconvenient in C++. Either you have to use constant size or resizing them is not possible without using some kind of new[] (or g++'s VAL extension which is not standard conform). The better alternative is usually std::vector. Instead of nesting std::vectors, the two dimensions can be "faked" by appropriate operator overloads. For my luck, I had a minimal working version at hand from another recent answer of mine to Multi-threading benchmarking issues.
Concerning the simulation step i, I came to the following logic:
If patient X is
's': check all neighbours around her/him whether somebody is infected ('i'). If so, infect patient X.
'i' (infected in day before): let her/him recover ('r').
'r' (recovered): do nothing with him i.e. keep her/him recovered ('r').
Please, note that the tests of the different current cases can be done in one iteration of all rows/all columns of the board – no necessity to do this in separate functions.
The most interesting case is 's'. For patient X at [i][j], all neighbours have to be checked. These are the patients at [i + iP][j + jP] with iP in [-1, 1] and jP in [-1, 1]. Iterating over these 9 values will check the patient X itself when iP == 0 and jP == 0. This special case could be checked but I ignored it (as by the above logic) a patient cannot infect itself. This saves an extra check for iP and jP in the most inner loop which is IMHO welcome.
At closer glance, you will realize that [i + iP][j + jP] might result in invalid coordinates if i == 0 or i == number of rows - 1 or j == 0 or j == number of columns - 1. This would require a lot of additional tests to grant valid indices but I use another trick: I make the board respectively larger to provide a border around. I don't use it for writing but this provides me safe read-accesses. All I have to grant is that reading from these border cells will not tamper my simulation logic. I initialize the whole board including border cells with 's'. As border cells are never written (except in initialization) they are never infected what matches my concept.
So, this is my simulation step:
void doSimStep(const Board &board, Board &board1)
{
assert(board.getNumRows() == board1.getNumRows());
assert(board.getNumCols() == board1.getNumCols());
for (size_t i = 1, nRows = board.getNumRows() - 1; i < nRows; ++i) {
for (size_t j = 1, nCols = board.getNumCols() - 1; j < nCols; ++j) {
const char person = board[i][j];
char person1 = person;
switch (person) {
case 's': { // search for infection in neighbourhood
bool infect = false;
for (int iP = -1; !infect && iP <= 1; ++iP) {
for (int jP = -1; !infect && jP <= 1; ++jP) {
infect = board[i + iP][j + jP] == 'i';
}
}
person1 = infect ? 'i' : 's';
} break;
case 'i': // infected -> recover
// fall through
case 'r': // recovered: stable state
person1 = 'r';
break;
default: assert(false); // Wrong cell contents!
}
board1[i][j] = person1;
}
}
}
I don't get why user10522145 believes this cannot be done without recursion. (Btw., I believe the opposite: every recursion can be turned into an iteration which may accumulate or stack intermediate results.) I actually don't know where the recursion would be necessary considering that the OP already planned separate boards for current and new state (which simplifies things much).
Output of a simulation with a 9×9 board:
Init.:
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
Day 0:
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s i s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
Day 1:
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
s s s i i i s s s
s s s i r i s s s
s s s i i i s s s
s s s s s s s s s
s s s s s s s s s
s s s s s s s s s
Day 2:
s s s s s s s s s
s s s s s s s s s
s s i i i i i s s
s s i r r r i s s
s s i r r r i s s
s s i r r r i s s
s s i i i i i s s
s s s s s s s s s
s s s s s s s s s
Day 3:
s s s s s s s s s
s i i i i i i i s
s i r r r r r i s
s i r r r r r i s
s i r r r r r i s
s i r r r r r i s
s i r r r r r i s
s i i i i i i i s
s s s s s s s s s
Day 4:
i i i i i i i i i
i r r r r r r r i
i r r r r r r r i
i r r r r r r r i
i r r r r r r r i
i r r r r r r r i
i r r r r r r r i
i r r r r r r r i
i i i i i i i i i
Day 5:
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
r r r r r r r r r
No further progress detected on day 6.
Done.
Live Demo on coliru
And finally (spoiler alert) the complete source code:
#include <cassert>
#include <iomanip>
#include <iostream>
#include <vector>
template <typename VALUE>
class MatrixT; // forward declaration
template <typename VALUE>
void swap(MatrixT<VALUE>&, MatrixT<VALUE>&); // proto
template <typename VALUE>
class MatrixT {
friend void swap<VALUE>(MatrixT<VALUE>&, MatrixT<VALUE>&);
public:
typedef VALUE Value;
private:
size_t _nRows, _nCols;
std::vector<Value> _values;
public:
MatrixT(size_t nRows, size_t nCols, Value value = (Value)0):
_nRows(nRows), _nCols(nCols), _values(_nRows * _nCols, value)
{ }
~MatrixT() = default;
MatrixT(const MatrixT&) = default;
MatrixT& operator=(const MatrixT&) = default;
size_t getNumCols() const { return _nCols; }
size_t getNumRows() const { return _nRows; }
const std::vector<Value>& get() const { return _values; }
Value* operator[](size_t i) { return &_values[0] + i * _nCols; }
const Value* operator[](size_t i) const { return &_values[0] + i * _nCols; }
};
template <typename VALUE>
void swap(MatrixT<VALUE> &mat1, MatrixT<VALUE> &mat2)
{
std::swap(mat1._nRows, mat2._nRows);
std::swap(mat1._nCols, mat2._nCols);
std::swap(mat1._values, mat2._values);
}
typedef MatrixT<char> Board;
bool operator==(const Board &board1, const Board &board2)
{
return board1.getNumRows() == board2.getNumRows()
&& board1.getNumCols() == board2.getNumCols()
&& board1.get() == board2.get();
}
std::ostream& operator<<(std::ostream &out, const Board &board)
{
for (size_t i = 1, nRows = board.getNumRows() - 1; i < nRows; ++i) {
for (size_t j = 1, nCols = board.getNumCols() - 1; j < nCols; ++j) {
out << ' ' << board[i][j];
}
out << '\n';
}
return out;
}
void doSimStep(const Board &board, Board &board1)
{
assert(board.getNumRows() == board1.getNumRows());
assert(board.getNumCols() == board1.getNumCols());
for (size_t i = 1, nRows = board.getNumRows() - 1; i < nRows; ++i) {
for (size_t j = 1, nCols = board.getNumCols() - 1; j < nCols; ++j) {
const char person = board[i][j];
char person1 = person;
switch (person) {
case 's': { // search for infection in neighbourhood
bool infect = false;
for (int iP = -1; !infect && iP <= 1; ++iP) {
for (int jP = -1; !infect && jP <= 1; ++jP) {
infect = board[i + iP][j + jP] == 'i';
}
}
person1 = infect ? 'i' : 's';
} break;
case 'i': // infected -> recover
// fall through
case 'r': // recovered: stable state
person1 = 'r';
break;
default: assert(false); // Wrong cell contents!
}
board1[i][j] = person1;
}
}
}
int main()
{
size_t nRows = 9, nCols = 9;
#if 0 // disabled for demo
std::cout << "N Rows: "; std::cin >> nRows;
std::cout << "N Cols: "; std::cin >> nCols;
/// #todo check nRows, nCols for sufficient values
#endif // 0
// init board
std::cout << "Init.:\n";
Board board(nRows + 2, nCols + 2);
std::fill(board[0], board[nRows + 2], 's');
std::cout << board << '\n';
// infect somebody
size_t i = nRows / 2 + 1, j = nCols / 2 + 1;
#if 0 // disabled for demo
std::cout << "Patient 0:\n";
std::cout << "row: "; std::cin >> i;
std::cout << "col: "; std::cin >> j;
/// #todo check i, j for matching the boundaries
#endif // 0
board[i][j] = 'i';
// simulation loop
for (unsigned day = 0;;) {
std::cout << "Day " << day << ":\n";
std::cout << board << '\n';
// simulate next day
++day;
Board board1(board);
doSimStep(board, board1);
if (board == board1) {
std::cout << "No further progress detected on day "
<< day << ".\n";
break; // exit sim. loop
}
// store data of new day
swap(board, board1);
}
// done
std::cout << "Done.\n";
return 0;
}
You are using C++, so use the standard library to the maximum...
The magically optimized disease simulation function:
/*
*-----------------------
* Key:
* ----------------------
* 0 - Susceptible person
* 1 - Infected person
* 2 - Recovered person
*
* #param init_infect_x Person to infect at x position...
* #param init_infect_y Person to infect at y position...
* #param map_size_x Width of the map...
* #param map_size_y Height of the map...
*/
std::vector<std::vector<std::vector<int>>> disease_simulator(size_t const init_infect_x = 0u,
size_t const init_infect_y = 0u,
size_t const map_size_x = 7u, size_t const map_size_y = 7u)
{
if (map_size_x == 0u || map_size_y == 0u || init_infect_x + 1 > map_size_x || init_infect_x + 1 < 0 || init_infect_y
+ 1 > map_size_y || init_infect_y + 1 < 0) // Well, we can't create a map which is empty...
return std::vector<std::vector<std::vector<int>>>();
std::vector<std::vector<std::vector<int>>> map_list;
std::vector<std::pair<int, int>> spread_pos;
std::vector<std::vector<int>> map(map_size_y, std::vector<int>(map_size_x, 0));
map[init_infect_y][init_infect_x] = 1;
map_list.emplace_back(map);
while (std::adjacent_find(map.begin(), map.end(), std::not_equal_to<>()) != map.end())
{
for (auto i = 0; i < signed(map.size()); i++)
for (auto j = 0; j < signed(map[i].size()); j++)
if (map[i][j] == 1)
{
map[i][j] = 2;
spread_pos.emplace_back(std::make_pair(j, i));
}
for (auto const pos : spread_pos)
{
if (pos.second - 1 >= 0 && map[pos.second - 1][pos.first] == 0) // Up...
map[pos.second - 1][pos.first] = 1;
if (pos.first - 1 >= 0 && map[pos.second][pos.first - 1] == 0) // Left...
map[pos.second][pos.first - 1] = 1;
if (pos.second - 1 >= 0 && pos.first - 1 >= 0 && map[pos.second - 1][pos.first - 1] == 0) // Up left...
map[pos.second - 1][pos.first - 1] = 1;
if (pos.second - 1 >= 0 && pos.first + 2 <= signed(map_size_x) && map[pos.second - 1][pos.first + 1] == 0)
// Up right...
map[pos.second - 1][pos.first + 1] = 1;
if (pos.second + 2 <= signed(map_size_y) && map[pos.second + 1][pos.first] == 0) // Down...
map[pos.second + 1][pos.first] = 1;
if (pos.first + 2 <= signed(map_size_x) && map[pos.second][pos.first + 1] == 0) // Right...
map[pos.second][pos.first + 1] = 1;
if (pos.second + 2 <= signed(map_size_y) && pos.first + 2 <= signed(map_size_x) && map[pos.second + 1][pos.
first + 1] == 0) // Down right...
map[pos.second + 1][pos.first + 1] = 1;
if (pos.second + 2 <= signed(map_size_y) && pos.first - 1 >= 0 && map[pos.second + 1][pos.first - 1] == 0)
// Down left...
map[pos.second + 1][pos.first - 1] = 1;
}
map_list.emplace_back(map);
spread_pos.clear();
}
return map_list;
}
What this function does is that it gives you the map of each day simultaneously, now you can just iterate over them one by one...
Note: Also, don't forget to #include <algorithm> at the beginning for std::adjacent_find()...
Example:
int main()
{
auto days_map = disease_simulator();
for (auto i = 0u; i < days_map.size(); i++)
{
std::cout << "Day " << i << ":" << std::endl;
for (auto elem2 : days_map[i])
{
for (auto elem3 : elem2)
switch (elem3)
{
case 0:
std::cout << "s ";
break;
case 1:
std::cout << "i ";
break;
case 2:
std::cout << "r ";
break;
default:
std::cout << ' ';
break;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
std::cout << "All people have recovered!" << std::endl;
return 0;
}
Edit: Live on coliru (Using 9x9 arrays with center as the infect point)
Well, see if it gives your desired output...
Kind regards,
Ruks.
I guess iteration might not work in this case ill suggest you use recursion with the array boundary values as the condition to stop recursion.
Hope it made sense

Renaming filenames in two directories IF certain characters between them match - vector subscript out of range

My first job as an intern was to write a program to compare certain characters in the filenames of two different directories, and if they match, rename them. I wrote a custom code to match the characters. The initial few files get renamed in both directories, but it breaks after a point, giving a vector subscript out of range error.
I have an idea of how to fix such a vector range error from all the other posts, but nothing seemed to work. Any input would be appreciated!
PS: I am not a coder and this is my third official program. I understand the code is a bit messy.
Here is the code:
#include<dirent.h>
#include<vector>
#include<sstream>
int main()
{
cout << "Comparer - Renamer v.0.1.beta\n\n";
string dr1, dr2;
int x, y;
DIR *d1;
struct dirent *dir1;
vector<string> a;
a.reserve(25000);
int i = 0;
cout << "Enter the first directory (format : log_2017...) : ";
cin >> dr1;
d1 = opendir(dr1.c_str());
if (d1){
while ((dir1 = readdir(d1)) != NULL){
i++;
a.push_back(dir1->d_name);
}
closedir(d1);
}
x = a.size();
cout << "\nEnter the second directory (format : 2017.12...) : ";
cin >> dr2;
DIR *d2;
struct dirent *dir2;
vector<string> b;
b.reserve(25000);
int j = 0;
d2 = opendir(dr2.c_str());
if (d2){
while ((dir2 = readdir(d2)) != NULL){
j++;
b.push_back(dir2->d_name);
}
closedir(d2);
}
y = b.size();
ostringstream osa, nsa, osb, nsb;
string oldname_a, newname_a, oldname_b, newname_b;
int u, v, w;
for (int l = 2; l < x; l++){
for (int k = l; k < y; k++){
int c = a[l][20] * 10 + a[l][21];
int d = b[k][14] * 10 + b[k][15];
int e = a[l][17] * 10 + a[l][18];
int f = b[k][11] * 10 + b[k][12];
if (a[l][4] == b[k][0] && a[l][5] == b[k][1] && a[l][6] == b[k][2] && a[l][7] == b[k][3] && a[l][9] == b[k][5] && a[l][10] == b[k][6] && a[l][12] == b[k][8] && a[l][13] == b[k][9]){
u = 0;
}
else{
u = 1;
}
if ((e - f) == 0 && abs(c - d) < 12){
v = 0;
}
else{
v = 1;
}
if ((e - f) == 1 && ((c == 58) || (c == 59) || (c == 0) || (c == 1) || (c == 2))){
w = 0;
}
else{
w = 1;
}
if (u == 0 && (v == 0 || w == 0)){
osa.str(string());
osa << dr1 << "\\" << a[l];
nsa.str(string());
nsa << dr1 << "\\" << l - 1 << ". " << a[l];
oldname_a = osa.str();
newname_a = nsa.str();
osb.str(string());
osb << dr2 << "\\" << b[k];
nsb.str(string());
nsb << dr2 << "\\" << l - 1 << ". " << b[k];
oldname_b = osb.str();
newname_b = nsb.str();
rename(oldname_a.c_str(), newname_a.c_str())
rename(oldname_b.c_str(), newname_b.c_str())
break;
}
}
}
return 0;
}
Presently the code is set such that it shows me how the comparison between the filenames is made.
It turns out I was not debugging properly, and the problem was in this part of the code:
int c = a[l][20] * 10 + a[l][21];
int d = b[k][14] * 10 + b[k][15];
int e = a[l][17] * 10 + a[l][18];
int f = b[k][11] * 10 + b[k][12];
I did not know that I couldn't assign an integer from a string/char directly to an int. I converted the char to int (which would give me the ASCII value of the char) and then subtracted it by 48 to convert it to decimal (I do not know if there is an easier way to do this, but this seemed to have worked for me!) The modified part looks like this:
c = ((int)a[l][20] - 48) * 10 + ((int)a[l][21] - 48);
d = ((int)b[k][14] - 48) * 10 + ((int)b[k][15] - 48);
e = ((int)a[l][17] - 48) * 10 + ((int)a[l][18] - 48):
f = ((int)b[k][11] - 48) * 10 + ((int)b[k][12] - 48);
There was also a small manual error in the conditions, which I also rectified.

Trying to check for 3 of a kind with arrays (Yahtzee) C++

I am trying to check for if the kept dice rolls (which can be up to 5) are 3 of a kind or not, so I'm trying to compare the dice roll values to each other.
The first value of R is showing as 0 of course, but the second value of R after the code is run is showing as 8191 every time, and I'm not entirely sure why.
I've also tried using
r++ instead of r += r+1, but of course that didn't change anything.
int r = 0;
cout << "first value of R is " << r << endl;
for(int t = 0; t < 5; t++) {
for(int w = 0; w < 5; w++) {
if(keptDice[t] == keptDice[w] ) {
r += r + 1;
}
}
}
cout << "Value of R is " << r << endl;
The point is that in the second for loop yo have tor start from t (int w = t;...) otherwise you would compare each dice with itself which will be naturally equal. Plus use r++ instead of r += r + 1 which is definitely wrong but I think that is just a misspelling.
int r = 0;
cout << "first value of R is " << r << endl;
for(int t = 0; t < 5; t++) {
for(int w = t; w < 5; w++) {
if(keptDice[t] == keptDice[w] ) {
r++;
}
}
}
cout << "Value of R is " << r << endl;
r += r + 1
is the same as writing
r = r + r + 1
r is doubling every time. Interestingly, it's always 1 less than 2^n
r = 0 + 0 + 1 (1)
r = 1 + 1 + 1 (3)
r = 3 + 3 + 1 (7)
r = 7 + 7 + 1 (15)
r = 15 + 15 + 1 (31)
r = 31 + 31 + 1 (63)
r = 63 + 63 + 1 (127)
r = 127 + 127 + 1 (255)
r = 255 + 255 + 1 (511)
r = 511 + 511 + 1 (1023)
r = 1023 + 1023 + 1 (2047)
r = 2047 + 2047 + 1 (4095)
r = 4095 + 4095 + 1 (8191)
Your program is counting 13 matches. For yahtzee, you probably want an array that counts matches, otherwise you're doubling up on each die. For example, if you had
1 2 3 4 1
It would count the first 1 matching the last die AND the last die matching the first (2 matches).
What would be more sensible is to count how many 1's you have, how many 2s you have, and store in an array
int diceCount[6];
for(int num = 1; num <= 6; num++) {
for(int w = 0; w < 5; w++) {
int count = 0;
if(keptDice[w] == num ) {
count++;
}
diceCount[num-1] = count;
}
This way when it's done, if you had two 1's, then diceCount[0] will be 2
Based on your approach, but generalized to N-of-a-kind:
int N = 3; // N in [1;5]
bool isNOfAKind = false;
for(int t = 0; t < 6-N; t++) { // skip searches with less elements than N
int r = 0; // r must be reset for each count
for(int w = t+1; w < 5; w++) { // avoid comparing to self
if(keptDice[t] == keptDice[w]) {
r++;
}
}
// found a solution already? then bail out.
if(r == N) {
isNOfAKind = true;
break;
}
}
cout << N << " of a kind? " << isNOfAKind << endl;

How to convert a 2D line equation in General Form to a Slope-intercept Form, in C++

I have the equation of a 2D line in the General Form a x + b y + c = 0 and I need to convert it to the proper Slope-intercept Form; with proper I mean I can choose between y = m x + q and x = m y + q.
My idea is to check if the line appears "more" horizontal or vertical and consequently choose one of the two Slope-intercept Form.
This is a sample code:
#include <iostream>
#include <cmath>
void abc2mq( double a, double b, double c, double& m, double& q, bool& x2y )
{
if ( fabs(b) >= fabs(a) ) {
x2y = true;
m = -a/b;
q = -c/b;
} else {
x2y = false;
m = -b/a;
q = -c/a;
}
}
void test(double a, double b, double c)
{
double m,q;
bool x2y;
abc2mq( a, b, c, m, q, x2y );
std::cout << a << " x + " << b << " y + " << c << " = 0\t";
if ( x2y ) {
std::cout << "y = " << m << " x + " << q << "\n";
} else {
std::cout << "x = " << m << " y + " << q << "\n";
}
}
int main(int argc, char* argv[])
{
test(0,0,0);
test(0,0,1);
test(0,1,0);
test(0,1,1);
test(1,0,0);
test(1,0,1);
test(1,1,0);
test(1,1,1);
return 0;
}
And this is the output
0 x + 0 y + 0 = 0 y = -1.#IND x + -1.#IND
0 x + 0 y + 1 = 0 y = -1.#IND x + -1.#INF
0 x + 1 y + 0 = 0 y = -0 x + -0
0 x + 1 y + 1 = 0 y = -0 x + -1
1 x + 0 y + 0 = 0 x = -0 y + -0
1 x + 0 y + 1 = 0 x = -0 y + -1
1 x + 1 y + 0 = 0 y = -1 x + -0
1 x + 1 y + 1 = 0 y = -1 x + -1
Any different or better idea? In particular, how can I handle the first two "degenerate" lines?
If you are looking for a good way to draw these lines, I would recommend using Bresenham's algorithm instead of sampling the result of the slope-intercept form of your line equation.
Apologies if this is not what you are trying to do.
You're almost done, just handle the degenerate case.
Add the check for a and b to be non-zero.
if(fabs(a) > DBL_EPSILON && fabs(b) > DBL_EPSILON)
{
... non-degenerate line handling
} else
{
// both a and b are machine zeros
degenerate_line = true;
}
Then add the parameter 'degenerate_line':
void abc2mq( double a, double b, double c, double& m, double& q, bool& x2y, bool& degenerate_line)
{
if(fabs(a) > DBL_EPSILON && fabs(b) > DBL_EPSILON)
{
if ( fabs(b) >= fabs(a) ) {
x2y = true;
m = -a/b;
q = -c/b;
} else {
x2y = false;
m = -b/a;
q = -c/a;
}
degenerate_line = false;
} else
{
degenerate_line = true;
}
}
And then check for the line to be empty set:
void test(double a, double b, double c)
{
double m,q;
bool x2y, degenerate;
abc2mq( a, b, c, m, q, x2y, degenerate );
std::cout << a << " x + " << b << " y + " << c << " = 0\t";
if(!degenerate)
{
if ( x2y ) {
std::cout << "y = " << m << " x + " << q << std::endl;
} else {
std::cout << "x = " << m << " y + " << q << std::endl;
}
} else
{
if(fabs(c) > DBL_EPSILON)
{
std::cout << "empty set" << std::endl
} else
{
std::cout << "entire plane" << std::endl
}
}
}
If all you need is to draw the line, just use Thorsten's advice - use the rasterization algorithm instead.
The equations corresponding to the two degenerated cases do not represent lines but the full plane (ℝ2) and the empty set (∅) respectively. The right thing to do is probably to discard them or to throw an error.
For the non degenerate cases, you are already handling them properly.