Reading From File - Size of Magic Square

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!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  int main()
{
	//declare array to hold matrix
	int matrix[99][99];

	//call function to open file and load matrix array with matrix found in file
	int matrixSize = readSquare(matrix);

	//call function to output 
	printSquare(matrix, matrixSize);
	
	//call function to verify if square is a magic square
	checkMagic(matrix, matrixSize);

	cout << endl;
	system("Pause");
	return 0;
}
int readSquare(int matrix1[][99])
{
	//create object to read file
	ifstream input;

	//open file
	input.open("Prog2Input.txt");

	//create counter
	int rows = 0;

	//load matrix into array
	while (input >> matrix1[rows][0] >> matrix1[rows][1] >> 
matrix1[rows][2] >> matrix1[rows][3] >> matrix1[rows][4])
	{
		rows++;
	}

	//close file
	input.close();
	return rows;
}
void printSquare(int matrix2[][99], int matrixSize1)
{
	cout << "Matrix\n\n";
	cout << "Matrix Size = " << matrixSize1 << endl << endl;
	
	for (int j = 0; j < matrixSize1; j++)
	{
		cout << setw(7) << matrix2[j][0] << setw(7) 
<< matrix2[j][1] << setw(7) << matrix2[j][2] << setw(7) 
<< matrix2[j][3] << setw(7) << matrix2[j][4] << endl;
	}
}



An example of what would be in the text file would be:

8 1 6
3 5 7
4 9 2

17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

6 2 7
1 9 5
8 4 3
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.
Last edited on
@b4nanabread

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Read Square.cpp : main project file.

#include <iostream>
#include <fstream>
#include <string>

using namespace 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?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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();
b4nanabread wrote:
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.

Edit: Here is the example I promised
http://coliru.stacked-crooked.com/a/c46617138791426d
Last edited on
@b4nanabread

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?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
		}
		else
else
		{ // 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();
I was bored today so I decided to make an example showing multiple magic squares
http://coliru.stacked-crooked.com/a/5c7f23342d554a41
Thank you very much both of you. I have it now. I appreciate it!
Here is a version that will work for any sized squares.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <iostream>
#include <sstream>
#include <vector>

using namespace 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) return false;	// empty square
    if (matrix[0].size() != sz) return false; // 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) return false; // row is wrong size
	if (sum != vectorSum(matrix[i])) return false; // 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) return false;
    }

    // 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) return false;

    // It's magic!
    return true;
}

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');
    }
}

Topic archived. No new replies allowed.