Hernyák Zoltán)
13. fejezet - A mágikus és bűvös négyzetek (szerző: Hernyák Zoltán)
13.11. forráskód. Törtátlókban található összegek képzése és összehasonlítása
static void panmagikus_kiir_A(int[,] m) {
int N = m.GetLength(0);
ConsoleColor[] color = new ConsoleColor[] { ConsoleColor.Red, ConsoleColor.Green, ConsoleColor.Yellow, ConsoleColor.Cyan, ConsoleColor.White, ConsoleColor.Magenta };
static void panmagikus_kiir_A(int[,] m) {
int N = m.GetLength(0);
ConsoleColor[] color = new ConsoleColor[] { ConsoleColor.Red, ConsoleColor.Green, ConsoleColor.Yellow, ConsoleColor.Cyan, ConsoleColor.White, ConsoleColor.Magenta }; hogy ezenfelül szükséges még a sorok és az oszlopok összegeinek ellenőrzése is (valamint a sorok és oszlopok összegeinek is egyezniük kell a törtátlók összegeivel)!
13.11. forráskód. Törtátlókban található összegek képzése és összehasonlítása
static bool panmagikus_ell(int[,] m) {
int N = m.GetLength(0);
int[] sum1 = new int[N];
int[] sum2 = new int[N];
//
int i1, i2;
for (int i = 0; i < N; i++) {
i1 = i;
i2 = N - i - 1;
for (int j = 0; j < N; j++) {
sum1[i1] = sum1[i1] + m[i, j];
sum2[i2] = sum2[i2] + m[i, j];
i1++;
if (i1>= N) i1= 0;
i2++;
if (i2 >= N) i2 = 0;
} } //
for (int i = 1; i < N; i++) if (sum1[i] != sum1[0]) return false;
for (int i = 1; i < N; i++) if (sum2[i] != sum2[0]) return false;
if (sum1[0] != sum2[0]) return false;
// minden ok return true;
}
Bevezető információk: Az ördögkeretek4 olyan (nagyobb méretű) mágikus négyzetek, melyek külső keretét eltávolítva szintén mágikus négyzetet kapunk – tehát mágikus négyzetek vannak egymásba ágyazva.
Értelemszerűen ezen kisebb méretű mágikus négyzet kulcsértéke is kisebb, mivel a keretet alkotó értékek már nem szerepelnek a sorok és oszlopok összegszámításában. Érdekesebb esetben ez az egymásba ágyazás több szinten is előfordulhat, mígnem egy olyan belső mátrixhoz jutunk el, amire már nem teljesül, hogy ő is egy önálló mágikus négyzet. A 13.6. ábrán egy 12-ed rendű ördögkeret látható.
13.6. ábra. 12-ed rendű ördögkeret
13.5. feladat (Ördögkeretek – szint: 4). Írjunk olyan programot, amely beolvas egy fájlból egy méretű mátrixot, és meghatározza, hogy milyen mélységben tartalmaz mágikus négyzeteket egymásba ágyazva! Ha ez a szám 0, akkor már a kiinduló mátrix sem volt mágikus négyzet.
4angolul néha Border Square-nek nevezik
Magyarázat: Ehhez 13.2 feladatban leírt mágikus négyzet ellenőrzése módszert kell kiterjeszteni, hogy ne a teljes mátrixra, csak annak egy részére terjedjen ki az ellenőrzés. Ez a módosítás nemcsak a fő ellenőrző függvényt (buvos_negyzet_e) érinti, hanem a belőle hívott segédfüggvényeket is.
13.12. forráskód. Bűvös négyzet – „buvos_negyzet_e_2”
static bool magikus_negyzet_e_2(int[,] m,int eltolas) {
int N = m.GetLength(0) - 2 * eltolas;
int[] sorok = new int[N];
int[] oszlopok = new int[N];
osszegekGen2(m, sorok, oszlopok, eltolas);
// sorok, oszlopok osszegei
if (mindEgyenlo(sorok) == false ||
mindEgyenlo(oszlopok) == false ||
sorok[0] != oszlopok[0]) return false;
// atlok osszegei int atlo1, atlo2;
atlokGen2(m, out atlo1, out atlo2,eltolas);
if (atlo1 != atlo2 || atlo1 != sorok[0]) return false;
// egyediseg
for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)
if (megszamol2(m, m[i, j],eltolas) != 1) return false;
// minden rendben return true;
}
13.13. forráskód. Bűvös négyzet – „osszegekGen2”
static void osszegekGen2(int[,] m,int[] sorok,int[] oszlopok,int eltolas) {
for (int i = 0; i < sorok.Length; i++) for (int j = 0; j < oszlopok.Length; j++) {
sorok[i] = sorok[i] + m[i + eltolas, j + eltolas];
oszlopok[j] = oszlopok[j] + m[i + eltolas, j + eltolas];
} }
13.14. forráskód. Bűvös négyzet – „mindEgyenlo”
static bool mindEgyenlo(int[] l) {
int x = l[0];
foreach (int a in l)
if (x != a) return false;
return true;
}
13.15. forráskód. Bűvös négyzet – „atlokGen2”
static void atlokGen2(int[,] m, out int a, out int b, int eltolas) {
a = 0; b = 0;
int N = m.GetLength(0);
for (int i = 0; i < N; i++) {
a = a + m[i + eltolas, i + eltolas];
b = b + m[i + eltolas, N - i - 1 - +eltolas];
} }
13.16. forráskód. Bűvös négyzet – „megszamol2”
static int megszamol2(int[,] m, int x, int eltolas) {
int N = m.GetLength(0)-eltolas;
int db = 0;
for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)
if (m[i+eltolas, j+eltolas] == x) db++;
return db;
}
Bevezető információk: Az olyan méretű mátrixok, amelyekben minden szám szerepel
intervallumból, s melyeknél a sorok, az oszlopok és az átlókban szereplő összegek különbözőek: antimágikus négyzetnek nevezzük. Bizonyítható, hogy nem létezik , , méretű anti mágikus négyzet.
13.6. feladat (Antimágikus négyzet ellenőrzése – szint: 2). Egy méretű kitöltött mátrixot ellenőrizzünk le, hogy antimágikus négyzet-e! Az ellenőrzés után jelenítsük meg a mátrixot a képernyőn, minden sorhoz és oszlophoz jelenítsük meg az összegeket, a főátló és a mellékátló összegét is! Az ellenőrzés eredményét írjuk vörös színnel, ha nem felelt meg, és zölddel, ha megfelelt!
Magyarázat: A főprogramban (a 13.57. forráskód) a mátrixot az alapadatokal történő feltöltés után megjelenítjük a képernyőn. A 13.59. forráskódban egy intelligens megjelenítő függvényt készítettünk, amely maga számolja ki a sor- és oszlopösszegeket, valamint az átlók összegét (semmit sem bízván a véletlenre). A sorok összegét kiírás közben számolja a sum változóba, és minden sor kiírásának végén azt meg is jeleníti. Az oszlopösszegeket a oszlopok vektorban számolja, mert az csak a legalsó sor kiírása után lesz látható. A főátlóbeli összeget a jobb sarokban jeleníti meg, a foatlo változó alapján. A mellékátló összegét az alsó sorban, az oszlopátlók előtt írja ki. A vizsgálatot a 13.58. forráskódban szereplő anti_buvos_negyzet_e függvény végzi.
A sorok összege N, az oszlopok összege is N, a főátlóbeli és a mellékátlóbeli elemek összege 2 darab szám, így összesen 2 * N + 2 összeget kell kiszámítani, ezért készül az osszegek vektor ezzel a mérettel el. Az első N elemében szerepelnek majd a sorok összegei, a további N elemében az oszlopok, az utolsó előtti a főátló, az utolsó a mellékátló összege. A vektor feltöltése után ellenőrizzük, hogy van-e az összegek között két egyforma.
Ha idáig minden rendben, akkor még azt is ellenőrizni kell, hogy minden szám szerepel-e az intervallumból, mindegyik pontosan egyszer.
13.7. ábra. A program outputja
13.17. forráskód. Anti bűvös négyzet-e – teszt főprogram
static void Main() {
const int N = 5;
int[,] m = new int[N, N];
Console.SetCursorPosition(0, N + 2);
if (anti_magikus_negyzet_e(m) == false) {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("NEM ANTI-MAGIKUS NEGYZET");
} else {
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("IGENIS ANTI-MAGIKUS NEGYZET");
}
Console.ReadLine();
}
13.18. forráskód. Anti bűvös négyzet-e – az ellenőrző függvény
13.19. forráskód. Anti bűvös négyzet-e – mátrix megjelenítés
static void Magikus_Kiiras(int[,] m) {
int N = m.GetLength(0);
int[] oszlopok = new int[N];
int foatlo = 0;
int mellekatlo = 0;
//
//
for (int i = 0; i < N; i++) {
Console.ForegroundColor = ConsoleColor.Yellow;
int sum = 0;
Console.Write(" ");
for (int j = 0; j < N; j++) {
Console.Write("{0,3} ", m[i, j]);
//
sum = sum + m[i, j];
oszlopok[j] = oszlopok[j] +m[i, j];
if (i==j) foatlo=foatlo+m[i,j];
if (i == N - j - 1)
mellekatlo = mellekatlo + m[i, j];
} //
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write("{0,4} ", sum);
Console.WriteLine();
} //
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("{0,3} ", mellekatlo);
Console.ForegroundColor = ConsoleColor.Cyan;
for (int j = 0; j < N; j++)
Console.Write("{0,3} ", oszlopok[j]);
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("{0,3} ", foatlo);
Console.ForegroundColor = ConsoleColor.Gray;
}
13.7. feladat (Antimágikus négyzet generálása – szint: 2). Generáljunk egy méretű mátrixot oly módon, hogy a végeredménye antimágikus négyzet legyen!
Magyarázat: A generálás során először feltöltjük a mátrixot módszeresen közötti értékekkel. Majd kiszámítjuk a sorok, oszlopok, átlók összegeit az előző feladatban ismertetett módon egy 2 * N + 2 méretű vektorba. Megkeressük, melyik két összeg egyenlő egymással. Ha nincs egyenlőség, akkor készen vagyunk. Ha találunk egyenlőséget, akkor választunk egy cellát a problémás sorból/oszlopból/átlóból, valamint egy véletlen cellát a mátrix tetszőleges helyéről. A két cellában lévő értéket felcseréljük.
Ezt addig ismételjük, amíg már nem lesz egyenlőség sehol. A mátrix megjelenítésén is finomítottunk: amelyik két összeg egyenlő egymással, azokat piros színnel jelenítjük meg. Valamint kiírásra kerül az is, hogy hány cserét kellett elvégezni, hogy a kívánt eredményt elérjük. Ez általában kevés csere, mivel a mátrix kezdeti feltöltése majdnem megfelelő. Ezért azzal bonyolítottuk a megoldást, hogy a kezdeti feltöltés után sok cserét hajtottunk végre a mátrix cellái között, hogy egy összekevert kezdő állapotot elérjünk. A mátrix ezen állapota is elég kedvező az antimágikus négyzet kiindulási állapotához, mert ezek után sincs szükség sok cserére. Úgy tűnik, ilyen négyzetek előállítása könnyű. A 13.60. ... 13.65. közötti forráskódok fedik le a megoldást.
13.8. ábra. A program outputja