마방진(magic square)은 모든 행, 열, 대각선의 합이 서로 같은 정사각형 행렬입니다. 이번 글에서는 3×3 행렬에서 대각선 요소가 비어 있을 때, 나머지 여섯 개의 요소만으로 대각선 값을 계산해 완전한 마방진을 만드는 방법을 살펴보겠습니다.
예를 들어 다음과 같이 대각선 자리가 0으로 비어 있는 3×3 행렬이 있다고 가정해 보겠습니다.
| 0 | 3 | 6 |
| 5 | 0 | 5 |
| 4 | 7 | 0 |
대각선을 알맞게 채우면 아래와 같이 모든 행, 열, 대각선의 합이 15로 같은 마방진이 완성됩니다.
| 6 | 3 | 6 |
| 5 | 5 | 5 |
| 4 | 7 | 4 |
대각선 값 계산 공식
비어 있는 대각선 요소를 각각 x, y, z라고 하면, 다음 공식으로 값을 구할 수 있습니다.
- x = (M[2,3] + M[3,2]) / 2
- z = (M[1,2] + M[2,1]) / 2
- y = (x + z) / 2
여기서 x는 좌상단(첫 번째 행·열) 요소, y는 중앙 요소, z는 우하단 요소입니다. 직관적으로 설명하면, 첫 번째 행과 첫 번째 열, 그리고 주대각선의 합을 모두 더하면 행렬 전체의 합과 같아지는데, 이 식을 정리하면 x는 반대편에 위치한 두 요소 M[2,3]과 M[3,2]의 평균이 됩니다. z도 같은 원리로 구할 수 있으며, 마방진의 성질상 중앙값 y는 항상 양쪽 대각선 끝값인 x와 z의 평균과 같습니다.
참고로 위 공식은 정수 나눗셈(/)을 사용하므로, 두 수의 합이 홀수인 경우 소수점 이하가 잘려나갈 수 있다는 점에 유의해야 합니다.
C++ 구현 예제
#include<iostream>
using namespace std;
void displayMatrix(int matrix[3][3]) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
cout << matrix[i][j] << " ";
cout << endl;
}
}
void fillDiagonal(int matrix[3][3]) {
matrix[0][0] = (matrix[1][2] + matrix[2][1]) / 2;
matrix[2][2] = (matrix[0][1] + matrix[1][0]) / 2;
matrix[1][1] = (matrix[0][0] + matrix[2][2]) / 2;
cout << "Final Matrix" << endl;
displayMatrix(matrix);
}
int main() {
int matrix[3][3] = {{ 0, 7, 6 },
{ 9, 0, 1 },
{ 4, 3, 0 }};
cout << "Given Matrix" << endl;
displayMatrix(matrix);
fillDiagonal(matrix);
}
fillDiagonal() 함수는 위 공식을 그대로 코드로 옮긴 것입니다. 먼저 matrix[0][0]과 matrix[2][2]를 계산한 뒤, 이 두 값을 이용해 중앙값 matrix[1][1]을 구합니다. 전체 과정은 상수 시간 O(1) 안에 완료됩니다.
실행 결과
Given Matrix 0 7 6 9 0 1 4 3 0 Final Matrix 2 7 6 9 5 1 4 3 8
실행 결과를 보면 x = (1 + 3) / 2 = 2, z = (7 + 9) / 2 = 8, y = (2 + 8) / 2 = 5로 계산되어, 최종 행렬의 모든 행·열·대각선의 합이 15로 일치하는 것을 확인할 수 있습니다.