Hello. I have written a program to read a 5*5 magic square and test whether or not it is one. I now need to covert my code to make it so it reads from a text file, pulling differently sized magic squares from it and checking the validity of each. I am having trouble with the conversion mainly in these ways:
1. Reading the file so that it differentiates between squares and terminates when there are no more squares
2. Reading the file to sense the square size and making a loop that will fit for a varying square size (reading and writing) (specifically in the area of columns... the columns are hard coded right now and I'm not sure how to make it so I don't have to hard code them)
I am going to place the functions that need edited below. Any help would be greatly appreciated. Thank you very much!
Have you tried counting the number of spaces on the first line of the file?
Another idea could be to read all the numbers into a flat 1D array one by one and count how many is read. Then, take the square root of the count to know the dimensions.
I did not do the first request, but here is the solving of the 2nd one. This one will except up to a 39x39 grid, if you put the numbers into the text file.
// Read Square.cpp : main project file.
#include <iostream>
#include <fstream>
#include <string>
usingnamespace std;
int readSquare(int matrix1[][40]);
void printSquare(int matrix1[][40], int matrixSize1);
void checkMagic(int matrix1[][40], int matrixSize1);
int main()
{
int matrix1[40][40];
//call function to open file and load matrix array with matrix found in file
int matrixSize = readSquare(matrix1);
//call function to output
if (matrixSize)
{
printSquare(matrix1, matrixSize);
//call function to verify if square is a magic square
checkMagic(matrix1, matrixSize);
}
else
cout << "Unable to continue." << endl << endl;
return 0;
}
int readSquare(int matrix1[][40])
{
int matrix[1600] = { 0 };
int test[1600] = { 0 };
//create object to read file
ifstream input;
//open file
input.open("Prog2Input.txt");
//create counter
int rows = 1, num, size = 1;
while (input >> num)
{
if (test[num] == 0)
{
matrix[rows] = num;
test[num] = num;
rows++;
if (size < num)
size = num;
}
else
cout << "Error in Magic Square data" << endl;
}
rows--;
num = 3;
while (num*num < size)
num++;
if (num*num != rows)
{
cout << "Error... Not enough numbers for a Magic square." << endl << endl;
return 0;
}
//load matrix into array
int z = 1;
for (int x = 1; x <= num; x++)
{
for (int y = 1; y <= num; y++)
{
matrix1[x][y] = matrix[z];
z++;
}
}
//close file
input.close();
return num;
}
void printSquare(int matrix1[][40], int matrixSize1)
{
cout << "Matrix\n\n";
cout << "Matrix Size = " << matrixSize1 << endl << endl;
// Print out the Magic Square
for (int x = 1; x <= matrixSize1; x++)
{
for (int y = 1; y <= matrixSize1; y++)
{
if (matrix1[x][y] < 10)
cout << " ";
cout << matrix1[x][y] << " ";
}
cout << endl;
}
}
void checkMagic(int matrix1[][40], int matrixSize1)
{
int Row_Total = 0, Total;
bool Square = true;
// Get value for top row
for (int x = 1; x <= matrixSize1; x++)
Row_Total += matrix1[1][x];
// Read each row and compare with top row value
for (int x = 1; x <= matrixSize1; x++)
{
Total = 0; // Reset variable for next row
for (int y = 1; y <= matrixSize1; y++)
{
Total += matrix1[x][y];
}
if (Total != Row_Total)
Square = false;
}
// Read each column and compare with top row value
for (int y = 1; y <= matrixSize1; y++)
{
Total = 0; // Reset variable for next column
for (int x = 1; x <= matrixSize1; x++)
{
Total += matrix1[x][y];
}
if (Total != Row_Total)
Square = false;
}
Total = 0; // Reset variable
// Read diagonal top left to bottom right
for (int x = 1; x <= matrixSize1; x++)
{
Total += matrix1[x][x];
}
if (Total != Row_Total)
Square = false;
// Read diagonal top right to bottom left
int y = 1;
Total = 0; // Reset variable
for (int x = matrixSize1; x >0 ; x--)
{
Total += matrix1[y][x];
y++;
}
if (Total != Row_Total)
Square = false;
if (Square)
cout << endl << "Yes, this is indeed a Magic Square.." << endl << endl;
else
cout << endl << "Sorry.. This is not a Magic Square.." << endl << endl;
}
@kevinkjt2000
I did try it, but somehow my array just loaded all the numbers, not just the numbers in the first column as I intended. As it stands now, it will load all the numbers in all of the squares into 5 columns. I like the square root idea. It would just be a matter of figuring out how to differentiate between squares at that point.
Basically - - how do I read/test for the extra white space included in the file?
@whitenite1
I'm sorry I am new to this. I don't quite understand what you have done/how you have done it. Specifically, why do you set size to the highest value contained within the matrix? And what is happening in lines 57-66 (15-24 below) and why?
how do I read/test for the extra white space included in the file?
Simple. Just ensure that the files are correct when you create them. Then the program does not have to worry. You could make a program that validates the data if you really wanted too, but you are complicating this exercise.
I'll try to answer your concerns, by commenting the code in question..
Well, yes lines 9 & 10, can be removed, along with lines 20 thru 24. And change line 17 to while (num*num < rows)
I was making sure they were all the same, but then, when the function checks if it's a Magic square, that would let you also know if there were errors.
I was just trying for all possible problems in the data.
Sorry if there was any confusion.
@whitenite1
I'm sorry I am new to this. I don't quite understand what you have done/how you have done it. Specifically, why do you set size to the highest value contained within the matrix? And what is happening in lines 57-66 (15-24 below) and why?
int rows = 1, num, size = 1;
while (input >> num)
{
if (test[num] == 0)
{
matrix[rows] = num;
test[num] = num;
rows++;// Check for how many numbers are read
if (size < num) // Find the highest number
size = num; // Assign variable to highest number
}
elseelse
{ // Should have been like this to return after the error is found
cout << "Error in Magic Square data" << endl; // If the same number is
// twice, show an error comment
return 0;
}
}
rows--;// Decrease by one
num = 3; // Start with a 3 to find the size of Magic Square
while (num*num < size) // If num squared not equal to variable size, increase num
num++;
// A 5x5 square should have 25 numbers. If, instead of a number 25, someone
// typed, let's say, a 26, then num squared would not equal size.
if (num*num != rows) // If not enough numbers in data, show error
{
cout << "Error... Not enough numbers for a Magic square." << endl << endl;
return 0;
}
//load matrix into array
int z = 1;
for (int x = 1; x <= num; x++)
{
for (int y = 1; y <= num; y++)
{
matrix1[x][y] = matrix[z];
z++;
}
}
//close file
input.close();
#include <iostream>
#include <sstream>
#include <vector>
usingnamespace std;
typedef vector<vector<int> > Matrix;
// Read the square and return its size or -1 on error
int
readSquare(istream &is, Matrix &matrix)
{
int num; // a number from the file
matrix.resize(1); // shrink to 1 empty vector
matrix[0].clear();
// read the first line and then parse it into the
// first row of the matrix
string line;
getline(is, line);
istringstream iss(line);
while (iss >> num) {
matrix[0].push_back(num);
}
// The number of items in the first line gives the size of the
// square. Read the rest of it.
int sz=matrix[0].size(); // the size of magic square
matrix.resize(sz);
for (int row = 1; row < sz; ++row) {
for (int col = 0; col < sz; ++col) {
is >> num;
matrix[row].push_back(num);
}
}
getline(is,line); // skip the newline at end of last line
// Finally, check if all is still well.
return (is.good() ? sz : -1);
}
void printSquare(ostream &os, const Matrix &matrix)
{
for (int row = 0; row < matrix.size(); ++row) {
for (int col = 0; col < matrix[row].size(); ++col) {
os << matrix[row][col] << ' ';
}
os << '\n';
}
}
// Add up the values in a vector. This is used by checkMagic below
int vectorSum(const vector<int> &vec)
{
int sum = 0;
for (int i=0; i<vec.size(); ++i) {
sum += vec[i];
}
return sum;
}
// Return true if this is a magic square
bool checkMagic(const Matrix &matrix)
{
bool result = false;
int sz = matrix.size();
if (sz == 0) returnfalse; // empty square
if (matrix[0].size() != sz) returnfalse; // 1st row wrong size
// Get the proposed sum
int sum = vectorSum(matrix[0]);
// Check the rows
for (int i=1; i<sz; ++i) {
if (matrix[i].size() != sz) returnfalse; // row is wrong size
if (sum != vectorSum(matrix[i])) returnfalse; // row is wrong sum
}
// check the columns
for (int col = 0; col < sz; ++col) {
int colSum = 0;
for (int row = 0; row <sz; ++row) {
colSum += matrix[row][col];
}
if (sum != colSum) returnfalse;
}
// check diagonals
int d1Sum=0, d2Sum=0;
for (int i=0; i<sz; ++i) {
d1Sum += matrix[i][i];
d2Sum += matrix[i][sz-i-1];
}
if (d1Sum != sum || d2Sum != sum) returnfalse;
// It's magic!
returntrue;
}
int main(int argc, char **argv)
{
Matrix matrix;
while (readSquare(cin, matrix) > 0) {
printSquare(cout, matrix);
cout << (checkMagic(matrix) ? "is" : "is not") << " magic\n\n";
// Skip the line separating the squares
cin.ignore(1000, '\n');
}
}