Skip to content

Commit cbde128

Browse files
authored
BAEL-6813: Creating a Magic Square in Java (eugenp#14572)
1 parent 44a53d6 commit cbde128

5 files changed

Lines changed: 292 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<artifactId>core-java-leetcode</artifactId>
7+
<name>core-java-leetcode</name>
8+
<packaging>jar</packaging>
9+
10+
<parent>
11+
<groupId>com.baeldung</groupId>
12+
<artifactId>parent-modules</artifactId>
13+
<version>1.0.0-SNAPSHOT</version>
14+
<relativePath>../../pom.xml</relativePath>
15+
</parent>
16+
17+
<dependencies>
18+
</dependencies>
19+
20+
<build>
21+
<plugins>
22+
<plugin>
23+
<groupId>org.apache.maven.plugins</groupId>
24+
<artifactId>maven-compiler-plugin</artifactId>
25+
<version>${maven-compiler-plugin.version}</version>
26+
<configuration>
27+
<source>${maven.compiler.source.version}</source>
28+
<target>${maven.compiler.target.version}</target>
29+
</configuration>
30+
</plugin>
31+
</plugins>
32+
</build>
33+
34+
<properties>
35+
<maven.compiler.source.version>11</maven.compiler.source.version>
36+
<maven.compiler.target.version>11</maven.compiler.target.version>
37+
</properties>
38+
39+
</project>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.baeldung.leetcode.magicsquare;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
public class GenerationUnitTest {
6+
@Test
7+
public void testGenerate3x3() {
8+
MagicSquare magicSquare = new MagicSquare(3);
9+
System.out.println(magicSquare);
10+
11+
magicSquare.validate();
12+
}
13+
14+
@Test
15+
public void testGenerate9x9() {
16+
MagicSquare magicSquare = new MagicSquare(9);
17+
System.out.println(magicSquare);
18+
19+
magicSquare.validate();
20+
}
21+
22+
@Test
23+
public void testGenerate12x12() {
24+
MagicSquare magicSquare = new MagicSquare(12);
25+
System.out.println(magicSquare);
26+
27+
magicSquare.validate();
28+
}
29+
30+
@Test
31+
public void testGenerate10x10() {
32+
MagicSquare magicSquare = new MagicSquare(10);
33+
System.out.println(magicSquare);
34+
35+
magicSquare.validate();
36+
}
37+
38+
@Test
39+
public void testGenerate18x18() {
40+
MagicSquare magicSquare = new MagicSquare(18);
41+
System.out.println(magicSquare);
42+
43+
magicSquare.validate();
44+
}
45+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package com.baeldung.leetcode.magicsquare;
2+
3+
import org.junit.platform.commons.util.StringUtils;
4+
5+
import java.util.stream.IntStream;
6+
7+
public class MagicSquare {
8+
private int[][] cells;
9+
10+
public MagicSquare(int n) {
11+
this.cells = new int[n][];
12+
13+
for (int i = 0; i < n; ++i) {
14+
this.cells[i] = new int[n];
15+
}
16+
17+
if (n % 2 == 1) {
18+
populateOdd();
19+
} else if (n % 4 == 0) {
20+
populateDoubleEven();
21+
} else if (n >= 6) {
22+
populateSingleEven();
23+
}
24+
}
25+
26+
private void populateOdd() {
27+
int n = getN();
28+
29+
populateOddArea(0, 0, n, 0);
30+
}
31+
32+
private void populateOddArea(int xOffset, int yOffset, int n, int numberOffset) {
33+
int y = 0;
34+
int x = (n - 1) / 2;
35+
setCell(xOffset + x, yOffset + y, numberOffset + 1);
36+
37+
for (int number = 2; number <= n * n; ++number) {
38+
int nextX = x + 1;
39+
if (nextX == n) {
40+
nextX = 0;
41+
}
42+
43+
int nextY = y - 1;
44+
if (nextY == -1) {
45+
nextY = n - 1;
46+
}
47+
48+
if (getCell(xOffset + nextX, yOffset + nextY) != 0) {
49+
nextX = x;
50+
51+
nextY = y + 1;
52+
if (nextY == n) {
53+
nextY = 0;
54+
}
55+
}
56+
57+
setCell(xOffset + nextX, yOffset + nextY, numberOffset + number);
58+
59+
x = nextX;
60+
y = nextY;
61+
}
62+
}
63+
64+
private void populateDoubleEven() {
65+
int n = getN();
66+
int number = 1;
67+
68+
for (int y = 0; y < n; ++y) {
69+
for (int x = 0; x < n; ++x) {
70+
boolean highlighted = false;
71+
72+
if ((y < n/4 || y >= 3*n/4) && (x >= n/4 && x < 3*n/4)) {
73+
highlighted = true;
74+
} else if ((x < n/4 || x >= 3*n/4) && (y >= n/4 && y < 3*n/4)) {
75+
highlighted = true;
76+
}
77+
78+
if (highlighted) {
79+
setCell(x, y, (n * n) - number + 1);
80+
} else {
81+
setCell(x, y, number);
82+
}
83+
84+
number += 1;
85+
}
86+
}
87+
}
88+
89+
private void populateSingleEven() {
90+
int n = getN();
91+
int halfN = n/2;
92+
int swapSize = (int) n/4;
93+
94+
populateOddArea(0, 0, halfN, 0);
95+
populateOddArea(halfN, halfN, halfN, halfN * halfN);
96+
populateOddArea(halfN, 0, halfN, (halfN * halfN) * 2);
97+
populateOddArea(0, halfN, halfN, (halfN * halfN) * 3);
98+
99+
for (int x = 0; x < swapSize; ++x) {
100+
swapCells(x, 0, x, halfN);
101+
swapCells(x, halfN - 1, x, n - 1);
102+
103+
for (int y = 1; y < halfN - 1; ++y) {
104+
swapCells(x + 1, y, x + 1, y + halfN);
105+
}
106+
}
107+
108+
for (int x = 0; x < swapSize - 1; ++x) {
109+
for (int y = 0; y < halfN; ++y) {
110+
swapCells(n - x - 1, y, n - x - 1, y + halfN);
111+
}
112+
}
113+
114+
}
115+
116+
private void swapCells(int x1, int y1, int x2, int y2) {
117+
int cell1 = getCell(x1, y1);
118+
int cell2 = getCell(x2, y2);
119+
120+
setCell(x1, y1, cell2);
121+
setCell(x2, y2, cell1);
122+
}
123+
124+
public int getN() {
125+
return cells.length;
126+
}
127+
128+
public int getCell(int x, int y) {
129+
return cells[x][y];
130+
}
131+
132+
public void setCell(int x, int y, int value) {
133+
cells[x][y] = value;
134+
}
135+
136+
public void validate() {
137+
int n = getN();
138+
int expectedValue = ((n * n * n) + n) / 2;
139+
140+
// Diagonals
141+
if (IntStream.range(0, n).map(i -> getCell(i, i)).sum() != expectedValue) {
142+
throw new IllegalStateException("Leading diagonal is not the expected value");
143+
}
144+
if (IntStream.range(0, n).map(i -> getCell(i, n - i - 1)).sum() != expectedValue) {
145+
throw new IllegalStateException("Trailing diagonal is not the expected value");
146+
}
147+
148+
// Rows
149+
IntStream.range(0, n).forEach(y -> {
150+
if (IntStream.range(0, n).map(x -> getCell(x, y)).sum() != expectedValue) {
151+
throw new IllegalStateException("Row is not the expected value");
152+
}
153+
});
154+
155+
// Cols
156+
IntStream.range(0, n).forEach(x -> {
157+
if (IntStream.range(0, n).map(y -> getCell(x, y)).sum() != expectedValue) {
158+
throw new IllegalStateException("Column is not the expected value");
159+
}
160+
});
161+
}
162+
163+
public String toString() {
164+
int n = getN();
165+
int largestNumberLength = Integer.toString(n * n).length();
166+
String formatString = " %0" + largestNumberLength + "d ";
167+
168+
StringBuilder sb = new StringBuilder();
169+
170+
for (int y = 0; y < n; ++y) {
171+
for (int x = 0; x < n; ++x) {
172+
int value = getCell(x, y);
173+
if (value == 0) {
174+
sb.append(" ");
175+
sb.append(".".repeat(largestNumberLength));
176+
sb.append(" ");
177+
} else {
178+
sb.append(String.format(formatString, value));
179+
}
180+
}
181+
sb.append("\n");
182+
}
183+
184+
return sb.toString();
185+
}
186+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.baeldung.leetcode.magicsquare;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
public class ValidationUnitTest {
6+
@Test
7+
public void testValidate3x3() {
8+
MagicSquare magicSquare = new MagicSquare(3);
9+
magicSquare.setCell(0, 0, 8);
10+
magicSquare.setCell(1, 0, 1);
11+
magicSquare.setCell(2, 0, 6);
12+
magicSquare.setCell(0, 1, 3);
13+
magicSquare.setCell(1, 1, 5);
14+
magicSquare.setCell(2, 1, 7);
15+
magicSquare.setCell(0, 2, 4);
16+
magicSquare.setCell(1, 2, 9);
17+
magicSquare.setCell(2, 2, 2);
18+
19+
magicSquare.validate();
20+
}
21+
}

core-java-modules/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
<module>core-java-lang-operators-2</module>
109109
<module>core-java-lang-syntax</module>
110110
<module>core-java-lang-syntax-2</module>
111+
<module>core-java-leetcode</module>
111112
<module>core-java-locale</module>
112113
<module>core-java-networking</module>
113114
<module>core-java-networking-2</module>

0 commit comments

Comments
 (0)