13. fejezet - A mágikus és bűvös négyzetek (szerző: Hernyák Zoltán)

Tartalom

A fejezet forráskódjai

Bevezető információk: Egy A mátrix soraira nézve sztochasztikus, ha elemei nemnegatívak, és minden sorösszege 1, és oszlopaira nézve sztochasztikus, ha elemei nemnegatívak, és minden oszlopösszege 1. Ha soraira és oszlopaira nézve is sztochasztikus, akkor kétszeresen (duplán) sztochasztikusnak nevezzük.

13.1. feladat (Sztochasztikus mátrixszint: 2). Egy text fájlban szereplő (tört számokat tároló) mátrix elemeit olvassuk be, majd dönstük el, hogy a mátrix duplán sztochasztikus-e!

Magyarázat: Ezt egy egyszerű függvény képes eldönteni (13.41. forráskód). A „minden szám nemnegatív” vizsgálatot érdemes belefoglalni valamelyik sor- vagy oszlopösszeg- ellenőrző lépésbe, mivel azok szkennelik a mátrix minden elemét, illetve kis ügyességgel egyetlen mátrixbejárással elvégezhető a teljes ellenőrzés (13.42. forráskód).

13.1. forráskód. Duplán sztochasztikusság ellenőrzése klasszikus megoldással

     
static bool duplan_sztochasztikus(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int M = m.GetLength(1); 
   // minden eleme nemnegatív ? 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < M; j++) 
         if (m[i, j] < 0) return false; 
   // sorosszeg mindenütt 1.0 ? 
   for (int i = 0; i < N; i++) 
   { 
      double sum = 0.0; 
      for (int j = 0; j < M; j++) 
         sum = sum + m[i, j]; 
      if (sum != 1.0) return false; 
   } 
   // oszlop osszegek mindenütt 1.0 ? 
   for (int j = 0; j < M; j++) 
   { 
      double sum = 0.0; 
      for (int i = 0; i < N; i++) 
         sum = sum + m[i, j]; 
      if (sum != 1.0) return false; 
   } 
   // minden rendben 
   return true; 
}
    

13.2. forráskód. Duplán sztochasztikusság ellenőrzése optimalizált módon

 
static bool duplan_sztochasztikus_opt(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int M = m.GetLength(1); 
   double[] sorok = new double[N]; 
   double[] oszlopok = new double[M]; 
   // matrix bejarasa 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < M; j++) 
      { 
         if (m[i, j] < 0) return false; 
         sorok[i] = sorok[i] + m[i, j]; 
         oszlopok[j] = oszlopok[j] + m[i, j]; 
      } 
   // ellenorzes 
   for (int i = 0; i < N; i++) 
   if (sorok[i]!=1.0) return false; 
   for (int j = 0; j < M; j++) 
      if (oszlopok[j] != 1.0) return false; 
   // minden rendben 
   return true; 
}

Bevezető információk: A duplán sztochasztikus mátrixokhoz hasonlóak a mágikus négyzetek. Ezek olyan mátrixok, melyek egész számokat tartalmaznak, minden szám egyedi (nem ismétlődik a mátrixban), és soraikban, oszlopaikban, valamint az átlókban szereplő számok összege egyenlő egymással. Ezt az értéket nevezzük mágikus értéknek, vagy kulcsértéknek[1].

A mágikus négyzetek több ezer éve ismertek, a középkorban talizmánként is használták őket. Egyik híres felbukkanási helye Albrecht Dürer (1471–1528) német festő és grafikus Melankólia c. metszetének (lásd a 13.1. ábra) jobb felső sarka, ahol egy méretű mágikus négyzet[2] látható. A négyzet alsó sorában középen szereplő két érték összeolvasva 1514, mely a kép keletkezésének éve is egyben.

A mágikus négyzeteket már a kínaiak is ismerték, egyik legrégebbi felbukkanása a változások könyve jóskönyv, mely i. e. 3000 körül készülhetett.

13.1. ábra. Albrecht Dürer – Melankólia

13.2. feladat (Mágikus négyzet-eszint: 2). Egy fájlban szereplő méretű mátrixról döntsük el, hogy mágikus négyzet-e! Ha igen, adjuk meg a mágikus mátrix kulcsértékét!

Magyarázat: A 13.2. ábrán látható egy Benjamin Franklin által készített méretű mágikus négyzet[3], ahol a sorok és oszlopok összege 260. A 13.1 feladatban elkészített ellenőrző függvény módosításokkal alkalmas a mágikus négyzet tulajdonság ellenőrzésére is. A különbség nemcsak az, hogy nem 1.0-nak kell lenni az összegeknek, de egymással is egyezőknek. Ha minden sorösszeg egyezik az első sor összegével, valamint minden oszlopösszeg egyezik az első oszlop összegével, akkor ez a tulajdonság már majdnem rendben is van. De meg kell még vizsgálni, hogy a sorok és oszlopok összege egymással is egyenlő-e! Ezenfelül ugyanezen összegnek kell szerepelni a két főátlóbeli számok összegeiként is. Nem szabad elfelejtkezni a számok egyediségének ellenőrzéséről sem! Mindezek a 13.43. ... 13.47. forráskódokban találhatók.

13.2. ábra. Franklin méretű mágikus négyzete

13.3. forráskód. Bűvös négyzet – „buvos_negyzet_e”

     
   static bool magikus_negyzet_e(int[,] m) 
   { 
      int N = m.GetLength(0); 
      int[] sorok = new int[N]; 
      int[] oszlopok = new int[N]; 
      osszegekGen(m, sorok, oszlopok); 
      // sorok, oszlopok osszegei 
      if (mindEgyenlo(sorok) == false || 
         mindEgyenlo(oszlopok) == false || 
         sorok[0] != oszlopok[0]) return false; 
      // atlok osszegei 
      int atlo1, atlo2; 
      atlokGen(m, out atlo1, out atlo2); 
      if (atlo1 != atlo2 || atlo1 != sorok[0]) 
         return false; 
      // egyediseg 
      for (int i = 0; i < N; i++) 
         for (int j = 0; j < N; j++) 
            if (megszamol(m, m[i, j]) != 1) 
               return false; 
      // minden rendben 
      return true; 
   }
    

13.4. forráskód. Bűvös négyzet – „osszegekGen”

     
static void osszegekGen(int[,] m, int[] sorok, int[] oszlopok) 
{ 
 for (int i = 0; i < sorok.Length; i++) 
   for (int j = 0; j < oszlopok.Length; j++) 
   { 
   sorok[i] = sorok[i] + m[i, j]; 
   oszlopok[j] = oszlopok[j] + m[i, j]; 
   } 
}
    

13.5. 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.6. forráskód. Bűvös négyzet – „atlokGen”

 
   static void atlokGen(int[,] m, out int a, out int b) 
   { 
      a = 0; b = 0; 
      int N = m.GetLength(0); 
      for (int i = 0; i < N; i++) 
      { 
         a = a + m[i, i]; 
         b = b + m[i, N - i - 1]; 
      } 
   }

13.7. forráskód. Bűvös négyzet – „megszamol”

 
   static int megszamol(int[,] m, int x) 
   { 
      int N = m.GetLength(0); 
      int db = 0; 
      for (int i = 0; i < N; i++) 
         for (int j = 0; j < N; j++) 
            if (m[i, j] == x) db++; 
      return db; 
   }

Bevezető információk: Az olyan mágikus négyzeteket, melyekben minden érték prímszám, prím mágikus négyzeteknek nevezzük (lásd pl. a 13.3. ábra).

13.3. ábra. Prímszámokból felépített méretű mágikus négyzet

13.3. feladat (Prím mágikus négyzet-eszint: 3). Feladat: egy fájlból beolvasott méretű mátrixról döntsük el, hogy bűvös négyzet-e, és ha igen, akkor prímekből felépített mágikus négyzet-e! Soroljuk fel tételesen, melyik cellában szereplő mely értékek nem prímek, amelyek elrontják ezt a tulajdonságot! A megoldás során az 1 értéket kivételesen kell kezelni. Ha szerepel valamelyik cellában, de mindegyik másik cellaérték prím, akkor az még elfogadható prím mágikus négyzet kategóriának.

Magyarázat: A prímszám eldöntésére több módszer is létezik, jelen probléma esetén majdnem mindegy, melyik módszert választjuk. Egy „prímszám-e” bevizsgáló függvény megírása után a probléma kezelhető szintre redukálódik: a 13.2 feladatban leírt ellenőrzést esetünkben csak azzal kell kiegészíteni, hogy a mátrix minden egyes számáról el kell dönteni, hogy prímszám-e vagy sem.

13.8. forráskód. A mátrix értékeinek ellenőrzése

     
bool mindegyikPrim = true; 
for(int i=0;i<N && mindegyikPrim;i++) 
{ 
 for(int j=0;j<M && mindegyikPrim;j++) 
 { 
   if (prim-e(m[i,j]==false) 
      mindegyikPrim = false; 
 } 
}
    

Bevezető információk: A pánmágikus négyzetek nem egyszerű mágikus négyzetek, hanem egyéb jellemzőkkel is bírnak. Nemcsak a sorokban és oszlopokban szereplő értékek összege egyenlő, hanem a főátlókban lévő számok összege is, valamint az ún. törtátlókban is. A 13.4. ábrán látható, mit értünk törtátlón. Egy méretű mátrixnál berajzoltuk ezeket is. A 13.5. ábrán újabb pánmágikus mátrixokat mutatunk be.

13.4. ábra. Pánmágikus mátrixok törtátlói

13.5. ábra. Újabb lehetséges pánmágikus mátrixok

13.4. feladat (Pánmágikus négyzetszint: 4). A feladat: írjunk olyan programot, amely beolvas fájlból egy méretű mátrixot, és eldönti, hogy pánmágikus-e! A program jelenítse meg az egyes törtátlókat eltérő színnel, és adja meg az adott törtátlóban lévő értékek összegét (egy időben csak egy törtátlóra koncentrálva, vagyis az adott törtátló számai legyenek zöldek, minden más szám legyen szürke)!

A mátrix törtátlós színezésével foglalkozik a 13.49. forráskód (jobbra-le törtátlók), a másik (balra-le) törtátlós színes kiírásával a 13.50. forráskódban található egyfajta megoldás. A színeket egy vektorba helyezzük. Konzolos felületen limitált mennyiségű színt használhatunk fel, és érdemes úgy válogatni a színeket egymás mellé, hogy lényegesen elüssenek egymástól. Ezért a színek vektorát manuálisan töltöttük fel színekkel. A két kiírás között egyébként a lényeges különbség mindössze a külső i ciklusban lévő szin kiválasztás módja.

13.9. forráskód. Jobbra-le törtátlók

                                                                                                                                     

                                                                                                                                     
     
   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 }; 
      // 
      int szin = 0; 
      for (int i = 0; i < N; i++) 
      { 
         szin = i; 
         for (int j = 0; j < N; j++) 
         { 
            Console.ForegroundColor = color[szin]; 
            Console.Write("{0,4}", m[i, j]); 
            szin++; 
            if (szin >= N) szin = 0; 
         } 
         Console.WriteLine(); 
      } 
  }
    

13.10. forráskód. Balra-le törtátlók

 
   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 }; 
      // 
      int szin = 0; 
      for (int i = 0; i < N; i++) 
      { 
         szin = i; 
         for (int j = 0; j < N; j++) 
         { 
            Console.ForegroundColor = color[szin]; 
            Console.Write("{0,4}", m[i, j]); 
            szin++; 
            if (szin >= N) szin = 0; 
         } 
         Console.WriteLine(); 
      } 
  }

A színek váltogatása során ismertetett módszer egyúttal a törtátlók szummájának képzéséhez is szükséges. A 13.51. forráskódban a két törtátlós összegek képzése és összehasonlítása történik meg. Ne feledjük azonban, 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ögkeretek[4] 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ögkeretekszint: 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.

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éseszint: 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]; 
   // kezdo feltoltes 
   int a = 1; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = a; 
         a++; 
      } 
   // 
   Magikus_Kiiras_2(m); 
   // 
   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

 
static bool anti_magikus_negyzet_e(int[,] m) 
{ 
 int N = m.GetLength(0); 
 int[] osszegek = new int[2*N+2]; 
 // az osszegek kepzese 
 for (int i = 0; i < N; i++) 
   for (int j = 0; j < N; j++) 
   { 
    // i. sor osszege 
    osszegek[i]  = osszegek[i] + m[i, j]; 
    // j. oszlop osszege 
    osszegek[N+j] = osszegek[i] + m[i, j]; 
    // foatlo osszege 
    if (i==j) osszegek[2 * N] = osszegek[2*N] + m[i, j]; 
    // mellekatlo osszege 
    if (i == N-j-1) osszegek[2 * N+1] = osszegek[2 * N+1] + m[i, j]; 
   } 
 
 // van-e ket egyforma osszeg ? 
 for (int i = 0; i < osszegek.Length; i++) 
   for (int j = i + 1; j < osszegek.Length; j++) 
    if (osszegek[i] == osszegek[j]) 
      return false; 
 // minden szam szerepel? 
 for (int k = 1; k <= N * N; k++) 
 { 
   int db = 0; 
   for (int i = 0; i < N; i++) 
    for (int j = 0; j < N; j++) 
      if (m[i, j] == k) db++; 
   if (db != 1) return false; 
 } 
 // minden ok 
 return true; 
}

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ásaszint: 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

13.20. forráskód. Anti bűvös négyzet generálás – főprogram

     
static void Main() 
{ 
   const int N = 8; 
   int[,] m = new int[N, N]; 
   int[] osszegek = new int[2 * N + 2]; 
   kezdoFeltoltes(m); 
   osszekeveres(m, N * N * 40); 
   // 
   ulong fdb = 0; 
   while (true) 
   { 
      int i, j; 
      osszegekSzamol(m, osszegek); 
      if (egyformaIndexek(osszegek, out i, out j)) 
      { 
         int a, b, c, d; 
         valasztElem(i, out a, out b, N); 
         c = rnd.Next(0, N); 
         d = rnd.Next(0, N); 
         // csere 
         int x = m[a, b]; 
         m[a, b] = m[c, d]; 
         m[c, d] = x; 
      } 
      else break; 
      // folyamat kozbeni kijelzes 
      if (fdb % 100000 == 0) 
      { 
         Console.Clear(); 
         Magikus_Kiiras_2(m); 
         Console.SetCursorPosition(0, N + 1); 
         Console.Write(fdb); 
      } 
      fdb++; 
   } 
   // 
   Console.Clear(); 
   Magikus_Kiiras_2(m); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("{0} | K É S Z ! ", fdb); 
   Console.ReadLine(); 
}
    

13.21. forráskód. Anti bűvös négyzet generálás – az összegek számítása

 
static void osszegekSzamol(int[,] m, int[] osszegek) 
{ 
   int N = m.GetLength(0); 
   for (int i = 0; i < osszegek.Length; i++) 
      osszegek[i] = 0; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         // i. sor osszege 
         osszegek[i] = osszegek[i] + m[i, j]; 
         // j. oszlop osszege 
         osszegek[N + j] = osszegek[i] + m[i, j]; 
         // foatlo osszege 
         if (i == j) 
            osszegek[2 * N] = osszegek[2 * N] + m[i, j]; 
         // mellekatlo osszege 
         if (i == N - j - 1) 
            osszegek[2 * N + 1] = osszegek[2 * N + 1] + m[i, j]; 
      } 
}

13.22. forráskód. Anti bűvös négyzet generálás – mátrix megjelenítése v2

                                                                                                                                     

                                                                                                                                     
     
static void Magikus_Kiiras_2(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   osszegekSzamol(m, osszegek); 
   int x,y; 
   egyformaIndexek(osszegek, out x, out y); 
 
   // 
   Console.ForegroundColor = ConsoleColor.Yellow; 
   for (int i = 0; i < N; i++) 
   { 
      Console.Write("  "); 
      for (int j = 0; j < N; j++) 
      { 
         Console.ForegroundColor = ConsoleColor.Yellow; 
         Console.Write("{0,3} ", m[i, j]); 
      } 
      Console.WriteLine(); 
   } 
   // sorok osszegei 
   for(int i=0;i<N;i++) 
   { 
      if (i==x || i==y) Console.ForegroundColor = ConsoleColor.Red; 
      else Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(N*4+4,i); 
      Console.Write("{0,3} ", osszegek[i]); 
   } 
   // oszlopok osszegei 
   for (int i = 0; i < N; i++) 
   { 
      if (i+N == x || i+N == y) 
        Console.ForegroundColor = ConsoleColor.Red; 
      else 
        Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(4+i*4, N); 
      Console.Write("{0,3} ", osszegek[i+N]); 
   } 
   // foatlo 
   if (2*N == x || 2*N == y) Console.ForegroundColor = ConsoleColor.Red; 
   else Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(4 + N * 4, N); 
   Console.Write("{0,3} ", osszegek[2*N]); 
   // mellektalo 
   if (2 * N+1 == x || 2 * N+1 == y) 
      Console.ForegroundColor = ConsoleColor.Red; 
   else 
      Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(0, N); 
   Console.Write("{0,3} ", osszegek[2 * N+1]); 
}
    

13.23. forráskód. Anti bűvös négyzet generálás – elem választása

 
static void valasztElem(int i, out int a, out int b, int N) 
{ 
   // i egy sor indexe 
   if (i < N) 
   { 
      a = i; 
      b = rnd.Next(0, N); 
      return; 
   } 
   // i egy oszlop indexe 
   if (i < 2*N) 
   { 
      a = rnd.Next(0, N); 
      b = i-N; 
      return; 
   } 
   // i a foatlo 
   if (i == 2 * N) 
   { 
      a = rnd.Next(0, N); 
      b = a; 
      return; 
   } 
   // i a mellekatlo 
   a = rnd.Next(0, N); 
   b = N - a - 1; 
}

13.24. forráskód. Anti bűvös négyzet generálás – mátrix kezdőfeltöltése

 
static void kezdoFeltoltes(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int k = 1; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = k; 
         k++; 
      } 
}

13.25. forráskód. Anti bűvös négyzet generálás – elem összekeverése

 
static void osszekeveres(int[,] m, int db) 
{ 
   int N = m.GetLength(0); 
   while (db > 0) 
   { 
      int x = rnd.Next(0, N); 
      int y = rnd.Next(0, N); 
      int v = rnd.Next(0, N); 
      int w = rnd.Next(0, N); 
      // 
      int c = m[x, y]; 
      m[x, y] = m[v, w]; 
      m[v, w] = c; 
      // 
      db--; 
   } 
}

13.8. feladat (Antimágikus négyzet befejezéseszint: 3). Egy text fájlból olvassunk be egy mátrixot, melynek bizonyos celláiban a 0 érték fog szerepelni! Ezen 0 értékeket tekintsük úgy, mintha a mátrix ezen a ponton még kitöltetlen lenne! Fejezzük be az antimágikus négyzetet oly módon, hogy a kitöltetlen cellákba közötti számokat helyezünk! Ügyeljünk arra, hogy a feladat esetleg megoldhatatlan! Ha ha a kitöltött cellákban ismétlődés szerepel, vagy van teljesen kitöltött sor, oszlop, átló, melyek valamelyikében a benne szereplő értékek összege megegyezik, akkor nem lehetséges a definíciónak megfelelni.

Magyarázat: A mátrix kitöltetlen celláiba eleve olyan értékeket kell elhelyezni az értékekből, amelyek még nem szerepeltek benne. A továbbiakban az előző feladatban ismertetett módon hajthatunk végre cseréket a mátrixon belül, csak arra kell ügyelnünk, hogy a kitöltött cellákat kihagyjuk. Ez azonban nem is olyan egyszerű. A valasztElem függvényt alaposan módosítani kell, ha például egy teljes kitöltött sorból kellene neki véletlen cellát választani, akkor az nem sikerülhet. Emiatt Main függvényben is alaposan át kell gyúrni ezt a részt.

Külön problémát okoz, hogyan különítjük el a fixen kitöltött cellákat a kitöltetlenektől. Ennek támogatásához bevezettünk egy fix nevű logikai mátrixot, melyben a benne lévő érték true, ha a cella fixen kitöltött, false ha szabadon módosítható. A mágikus négyzetet megjelenítő eljárást is módosítottuk, hogy a fix cellákat más színnel jelenítse meg, mint a szabad cellákat.

A program a fájl beolvasása után megjeleníti a kitöltött és kitöltetlen cellákat (a fix cellákat zöld alapon feketével). Majd kitölti a maradék cellákat a soron következő sorszámokkal, és ezt az állapotot is megjeleníti, végül megpróbálja megoldani a feladatot. A 13.74. és a 13.73. forráskódok olyan szinten fedik le a feladatot, hogy a megoldhatatlansági kérdéssel nem foglalkozunk.

13.9. ábra. A program outputja 1.

13.10. ábra. A program outputja 2.

13.26. forráskód. Anti bűvös négyzet generálás – elem összekeverése

     
static void Main() 
{ 
   int[,] m; 
   bool[,] fix; 
   beolvasas(out m,out fix,@"hianyos-anti-magikus-negyzet.txt"); 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   Console.Clear(); 
   Magikus_Kiiras_3(m, fix); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("Kezdeti allapot beolvasva (nyomj le egy billt)"); 
   Console.ReadLine(); 
   // 
   matrixBefejez(m); 
   Console.Clear(); 
   Magikus_Kiiras_3(m, fix); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("Kezdeti allapot befejezve (nyomj le egy billt)"); 
   Console.ReadLine(); 
   // 
   ulong fdb = 0; 
   while (true) 
   { 
      int i, j; 
      osszegekSzamol(m, osszegek); 
      if (egyformaIndexek(osszegek, out i, out j)) 
      { 
         int a, b, c, d; 
         valasztElem2(i, j,out a, out b, N, fix); 
         while (true) 
         { 
            c = rnd.Next(0, N); 
            d = rnd.Next(0, N); 
            if (fix[c, d] == false) break; 
         } 
         int x = m[a, b]; 
         m[a, b] = m[c, d]; 
         m[c, d] = x; 
      } 
      else break; 
      if (fdb % 100000 == 0) 
      { 
         Console.Clear(); 
         Magikus_Kiiras_3(m,fix); 
         Console.SetCursorPosition(0, N + 1); 
         Console.Write(fdb); 
      } 
      fdb++; 
   } 
   // 
   Console.Clear(); 
   Magikus_Kiiras_3(m,fix); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("{0} | K É S Z ! ", fdb); 
   Console.ReadLine(); 
}
    

13.27. forráskód. Anti bűvös négyzet generálás – beolvasás

 
static void beolvasas(out int[,] m, out bool[,] fix, string fnev) 
{ 
   m = null; 
   fix = null; 
   int N = 0; 
   int i = 0; 
   System.IO.StreamReader r = 
    new System.IO.StreamReader(fnev, System.Text.Encoding.Default); 
   while (!r.EndOfStream) 
   { 
      string s = r.ReadLine().Trim(); 
      string[] ss = s.Split(’ ’); 
      if (m == null) 
      { 
         N = ss.Length; 
         m = new int[N, N]; 
         fix = new bool[N, N]; 
      } 
      if (ss.Length != N) 
         throw new Exception("File feldolgozasi hiba"); 
      if (i>=N) 
         throw new Exception("Tul sok sor a file-ban"); 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = int.Parse(ss[j]); 
         fix[i, j] = (m[i, j] != 0); 
      } 
      i++; 
   } 
   r.Close(); 
   if (m==null) 
      throw new Exception("File ures volt"); 
}
                                                                                                                                     

                                                                                                                                     
    

13.28. forráskód. Anti bűvös négyzet generálás – a maradék cellák kitöltése

 
static void matrixBefejez(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int k = 1; 
   for(int i=0;i<N;i++) 
   { 
      for (int j = 0; j < N; j++) 
      { 
         if (m[i, j] == 0) 
         { 
            k = kovNemSzereplo(m, k); 
            m[i, j] = k; 
         } 
      } 
   } 
}

13.29. forráskód. Anti bűvös négyzet generálás – következő még nem szereplő érték keresése

 
static int kovNemSzereplo(int[,] m, int k) 
{ 
   int N = m.GetLength(0); 
   while (true) 
   { 
      int db = 0; 
      for (int i = 0; i < N && db==0; i++) 
         for (int j = 0; j < N && db == 0; j++) 
            if (k == m[i, j]) db++; 
      if (db == 0) return k; 
      k++; 
   } 
}

13.30. forráskód. Anti bűvös négyzet generálás – megjelenítés

 
static void Magikus_Kiiras_3(int[,] m, bool[,] fix) 
{ 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   osszegekSzamol(m, osszegek); 
   int x,y; 
   egyformaIndexek(osszegek, out x, out y); 
 
   // 
   Console.ForegroundColor = ConsoleColor.Yellow; 
   for (int i = 0; i < N; i++) 
   { 
      Console.Write("  "); 
      for (int j = 0; j < N; j++) 
      { 
         if (fix[i, j]) 
         { 
            Console.BackgroundColor = ConsoleColor.Green; 
            Console.ForegroundColor = ConsoleColor.Black; 
         } 
         else 
         { 
            Console.BackgroundColor = ConsoleColor.Black; 
            Console.ForegroundColor = ConsoleColor.Yellow; 
         } 
         Console.Write("{0,3} ", m[i, j]); 
         Console.BackgroundColor = ConsoleColor.Black; 
      } 
      Console.WriteLine(); 
   } 
   // sorok osszegei 
   for(int i=0;i<N;i++) 
   { 
      if (i==x || i==y) Console.ForegroundColor = ConsoleColor.Red; 
      else Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(N*4+4,i); 
      Console.Write("{0,3} ", osszegek[i]); 
   } 
 
 
   // oszlopok osszegei 
   for (int i = 0; i < N; i++) 
   { 
      if (i+N == x || i+N == y) 
         Console.ForegroundColor = ConsoleColor.Red; 
      else 
         Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(4+i*4, N); 
      Console.Write("{0,3} ", osszegek[i+N]); 
   } 
   // foatlo 
   if (2*N == x || 2*N == y) 
      Console.ForegroundColor = ConsoleColor.Red; 
   else 
      Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(4 + N * 4, N); 
   Console.Write("{0,3} ", osszegek[2*N]); 
   // mellektalo 
   if (2 * N+1 == x || 2 * N+1 == y) 
     Console.ForegroundColor = ConsoleColor.Red; 
   else 
     Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(0, N); 
   Console.Write("{0,3} ", osszegek[2 * N+1]); 
   Console.ForegroundColor = ConsoleColor.Gray; 
}

13.31. forráskód. Anti bűvös négyzet generálás – cserélendő cellák választása

 
static void valasztElem2(int i, int j,out int a, out int b, 
                  int N, bool[,] fix) 
{ 
   while (true) 
   { 
      valasztElem(i, out a, out b, N); 
      if (fix[a, b] == false) return; 
      valasztElem(j, out a, out b, N); 
      if (fix[a, b] == false) return; 
   } 
}

Bevezető információk: A szép antimágikus négyzetek alatt értsük azt az eset, amikor az egyes sorokban szereplő értékek egymást követő természetes számok, valamint (hasonlóan) az oszlopokban szereplő értékek összegei is egymást követő természetes számok!

13.9. feladat (Szép antimágikus négyzet ellenőrzéseszint: 2). Készítsünk olyan függvényt, amely beolvas fájlból egy méretű mátrixot, majd ellenőrzi, hogy az szép antimágikus négyzet-e!

Magyarázat: A 13.68. függvény képes beolvasni mátrixot fájlból. A 13.58. függvény képes eldönteni, hogy antimágikus négyzet-e. A 13.61. forráskódban bemutatott osszegekSzamol függvény képes előállítani a sorok és oszlopok összegeit. Az összegek ellenőrzése ettől kezdve már nem nehéz (lásd a 13.74. forráskód).

13.32. forráskód. Szép anti bűvös négyzet ellenőrzés

     
static bool szep_magikus_negyzet_e(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   osszegekSzamol(m, osszegek); 
   // sorok osszegei 
   for (int i = 1; i < N; i++) 
      if (osszegek[i - 1] != osszegek[i] + 1) 
         return false; 
   // oszlopok osszegei 
   for (int i = N; i < 2*N; i++) 
      if (osszegek[i - 1] != osszegek[i] + 1) 
         return false; 
   // minden rendben 
   return true; 
}
    

Bevezető információk: A magyar kártyában négy szín (piros, zöld, makk, tök) fordul elő, mindegyik színből van számozott (7...10) és figurás (alsó, felső, király, ász) lap, így összesen 32 lapos. Figurás lapokból 4 különböző van, ha mind a 4 szín figurás lapjait összeszedjük, akkor pontosan 16 lapot kapunk.

13.10. feladat (Kártyaalapú mágikus négyzetszint: 3). Helyezzük el a magyar kártya figurás lapjait egy 4 x 4-es mágikus négyzetben úgy, hogy minden sorban, minden oszlopban, valamint a két átlóban is különböző színű és különböző figurás lapok legyenek!

13.11. ábra. Egy lehetséges megoldás

Magyarázat: Természetesen konzolos felületen nem lehet ilyen szép outputot generálni, mint amit a 13.11. ábrán láthatunk. Alkalmazzunk kódolást a kártyákra. Jelöljük 11, 12, 13, 14-gyel a piros színű alsó, felső, király, ász lapokat! Hasonlóan 21, 22, 23, 24 értékekkel a zöld alsó, felső, király, ász, 31, 32, 33, 34-gyel a makk, 41, 42, 43, 44 értékkel a tök színű lapokat. A szabályt ekkor úgy fogalmazhatjuk meg: egyetlen sorban, oszlopban, átlóban sem fordulhat elő két olyan számérték, melyeknek 10-zel való egész vagy maradékos osztásának eredménye egyenlő. Ha a 10-zel való egész osztás eredménye egyenlő lenne, akkor az egyforma színt jelentene. Ha a modulo 10 értéke egyenlő, akkor az egyforma figurát jelentene.

Készítsük el a mátrix egy alapkitöltését, helyezzük el benne az összes számértéket módszeresen sorfolytonosan! Az így feltöltött mátrix nyilván nem felel meg a feltételeknek. Válasszunk ki két cellát véletlenszerűen, és cseréljük fel a bennük lévő értékeket, mindaddig, míg meg nem kapjuk a kért tulajdonságú végeredményt! Ez lényegében egyezik az antimágikus négyzet generálásánál bemutatott módszerrel.

Sajnos gyakorlatilag reménytelen, hogy a véletlen cserék révén helyes mátrixot kapjunk. Ezért hasonlóan, most is meg kell keresnünk, melyik sorok vagy mely oszlopok hiúsítják meg a kívánt végeredmény elérését, azon belül melyik két cella okozza a konfliktust. Elegendőek az egyik problémás cella koordinátái. Válasszunk hozzá véletlenszerűen egy másik cellát a mátrixból, és cseréljük fel e két cella tartalmát! A módszer elvileg működőképes, de gyakorlatilag nem lehet megmondani, mennyi időbe kerül. A futási idő egy dupla magos gépen futtatva körülbelül 3 perc és 5 perc között változott. A program outputja a 13.76. ábrán látható, a 13.75. ... 13.82. forráskódok tartalmazzák a megoldást.

13.12. ábra. Egy lehetséges megoldás

13.33. forráskód. Kártyás – főprogram

     
static void Main() 
{ 
   const int N = 4; 
   int[,] m = new int[N,N]; 
   kezdoFeltoltes(m); 
   ulong fdb = 0; 
   int v,w; 
   DateTime start = DateTime.Now; 
   while (matrixRendben(m, out v, out w ) == false) 
   { 
      int x = rnd.Next(0, N); 
      int y = rnd.Next(0, N); 
      // 
      int c = m[x, y]; 
      m[x, y] = m[v, w]; 
      m[v, w] = c; 
      // 
      // fdb++; 
      // if (fdb % 1000000 == 0) Megjelenit(m); 
   } 
   DateTime stop = DateTime.Now; 
   TimeSpan kul = stop - start; 
   Megjelenit(m); 
   Console.WriteLine(); 
   Console.WriteLine(); 
   Console.ForegroundColor = ConsoleColor.Gray; 
   Console.WriteLine("Futasi ido={0}", kul); 
   Console.ReadLine(); 
}
    

13.34. forráskód. Kártyás – megjelenítés

 
static void Megjelenit(int[,] m) 
{ 
   Console.Clear(); 
   int N = m.GetLength(0); 
   ConsoleColor[] szinek = new ConsoleColor[] 
      { ConsoleColor.Green, ConsoleColor.Red, 
        ConsoleColor.Cyan, ConsoleColor.Yellow}; 
   string[] lapok = new string[] { "also", "felso", "kiraly", "asz" }; 
   for (int i = 0; i < N; i++) 
   { 
      for (int j = 0; j < N; j++) 
      { 
         Console.SetCursorPosition(j * 8, i * 2); 
         int x = m[i, j]; 
         int v = x / 10 - 1; 
         int w = x % 10 - 1; 
         Console.ForegroundColor = szinek[v]; 
         Console.Write(lapok[w]); 
      } 
   } 
}

13.35. forráskód. Kártyás – a mátrix megfelelőségének ellenőrzése

     
static bool matrixRendben(int[,] m, out int k, out int l) 
{ 
   k = -1; 
   l = -1; 
   int N = m.GetLength(0); 
   for (int i = 0; i < N; i++) 
   { 
      if (sorRendben(m, i, N, out l) == false) 
      { 
        k = i; 
        return false; 
      } 
      if (oszlopRendben(m, i, N, out k) == false) 
      { 
       l = i; 
       return false; 
      } 
   } 
   if (atlokRendben(m, N,out k, out l) == false) 
      return false; 
   return true; 
}
    

13.36. forráskód. Kártyás – átlók megfelelőségének ellenőrzése

 
static bool atlokRendben(int[,] m, int N, out int v, out int w) 
{ 
   v = -1; 
   w = -1; 
   for (int i = 0; i < N; i++) 
    for (int j = i + 1; j < N; j++) 
    { 
      if (hasonlo(m[i, i], m[j, j])) 
      { 
        v = i; 
        w = i; 
        return false; 
      } 
      if (hasonlo(m[i, N - i - 1], m[j, N - j - 1])) 
      { 
        v = i; 
        w = N - i - 1; 
        return false; 
      } 
    } 
   // 
   return true; 
}

13.37. forráskód. Kártyás – a mátrix k. oszlopának ellenőrzése

 
static bool oszlopRendben(int[,] m, int k, int N, out int w) 
{ 
   w = -1; 
   for (int i = 0; i < N; i++) 
      for (int j = i + 1; j < N; j++) 
         if (hasonlo(m[i, k], m[j, k])) { w = i; return false; } 
   // 
   return true; 
}

13.38. forráskód. Kártyás – a mátrix k. sorának ellenőrzése

 
static bool sorRendben(int[,] m, int k, int N, out int w) 
{ 
   w = -1; 
   for (int i = 0; i < N; i++) 
      for (int j = i + 1; j < N; j++) 
         if (hasonlo(m[k, i], m[k, j])) { w = i; return false; } 
   // 
   return true; 
}

13.39. forráskód. Kártyás – két cella színének és lapjának vizsgálata

 
static bool hasonlo(int a, int b) 
{ 
   if (a / 10 == b / 10 || a % 10 == b % 10) return true; 
   return false; 
}
                                                                                                                                     

                                                                                                                                     
    

13.40. forráskód. Kártyás – a mátrix kezdő feltöltése

 
static void kezdoFeltoltes(int[,] m) 
{ 
   int N = m.GetLength(0); 
   for (int i = 0; i < N; i++) 
   { 
      int k = (i+1)*10+1; 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = k; 
         k++; 
      } 
   } 
}

Bevezető információk: Egy mátrixot latin négyzetnek nevezünk, ha minden sorában és minden oszlopában – tetszőleges sorrendben – ugyanaz az N darab szám áll, de mindegyik csak egyszer.

Tehát nem kell a mágikus négyzetekhez hasonlóan minden mezőbe különböző számot írni, és – általában – az átlókra sincs kikötés.

13.11. feladat (Latin négyzetszint: 2). Generáljunk egy méretű latin négyzetet, ahol N értékét a program indulásakor a felhasználó adja meg! A generált négyzetet táblázatos alakban írjuk ki a latin-negyzet.txt fájlba!

Magyarázat: Ez utóbbi könnyítések miatt a latin négyzetek kitöltése rendkívül egyszerű: az első sorba írjuk tetszőleges sorrendben az 1, 2, ..., n számokat, majd lefelé haladva a következő sorba – a sorrendet megtartva – eggyel jobbra (vagy balra) tolva írjuk le, azaz ciklikusan permutáljuk. A megoldás a 13.83. forráskódban olvasható.

Bevezető információk: A matematikában egy mágikus négyzetet másodfokúnak[5] nevezhetünk, ha mágikus négyzet marad akkor is, ha a benne szereplő minden n számot négyzetre emeljük. Harmadfokúnak[6] nevezhetjük, ha minden számot harmadik hatványára emelve az szintén mágikus négyzet marad. A harmadfokúak nem feltétlenül másodfokúak. Általában véve, k-ad fokúnak nevezünk egy mágikus négyzetet, ha minden számot k. hatványra emelve szintén egy mágikus négyzetet kapunk.

13.12. feladat (K-ad fokú mágikus négyzetekszint: 2). Készítsünk olyan függvényt, amely egy adott méretű mágikus négyzetről eldönti, hogy még milyen k-ad fokú mágikus négyzet is egyben! A függvény kimenete egy lista, melyben a k értékei szerepelnek. Ez a lista legyen üres, ha a mágikus négyzetünk semmilyen k értékre nem k-ad fokú! A k értékeit [1 ... 10] között vizsgálja a program!

Magyarázat: A feladat nagyon egyszerű. A 13.43. kódban megadott ellenőrző függvény képes ellenőrizni, hogy egy m mátrix mágikus négyzet-e. Mindössze elő kell állítani a mátrixelemek különböző hatványát, és alkalmazni kell az ellenőrző függvényt (lásd a 13.84. forráskódot).

Bevezető információk: Egy négyzetet bűvös négyzetnek nevezünk, ha mágikus négyzet, és az NN méretű mátrix celláiban az összes szám szerepel (13.87. ábra).

13.13. ábra. Bűvös négyzet

13.13. feladat (Bűvös négyzet-eszint: 2). Készítsünk programot, amely egy méretű mátrixot beolvas fájlból, majd eldönti, hogy a mátrix bűvös négyzet-e!

Magyarázat: A 13.43. forráskódban leírt mágikusnégyzet-ellenőrző függvényt kell annyiban bővíteni, hogy közötti minden szám szerepel-e a mátrixban (pontosan egyszer szerepel-e). Mivel a mátrix mérete is , így ha minden szám szerepel a szóban forgó intervallumból, akkor egyúttal pontosan egyszer szerepel. A plusz ellenőrzés kódja (melyet be lehet szúrni a 13.43. kódban megadott függvény belsejébe) a 13.85. forráskódban olvasható.

Bevezető információk: A misztikus négyzetek előállításának több módszere is van. Általában külön szokták venni a páros és a páratlan N méretű mátrixok előállítási módszereit. Ha N páratlan, akkor a huszármódszerrel próbálkozhatunk. Ennek során írjuk be a mátrix tetszőleges pontjára az 1 értéket, majd a sakkban ismert huszár L lépési technikájával lépjünk 2-t fel 1-et jobbra, és ide írjuk a következő számot! Ha eközben kilépnénk a mátrixból, akkor úgy kell kezelni a cellát, hogy ott is egy ugyanilyen mátrix áll, és az abba eső pozíciót kell az itteni mátrixban felölteni. Ha az a cella már foglalt, akkor a lóugrás kiindulási pontja alatti cellába kell írni (lásd a 13.14. és a 13.15. ábrák).

13.14. ábra. Huszár módszer 1. lépés

13.15. ábra. Huszár módszer folytatás

13.14. feladat (Huszármódszerszint: 4). Kérjük be N értékét billentyűzetről, , és páratlan. Készítsük el az méretű misztikus mátrixot a huszármódszerrel, jelenítsük meg táblázatos alakban a képernyőn, és ellenőrízzük le, hogy valóban teljesíti-e a misztikus mátrixok tulajdonságait!

Az algoritmus alapján készült 13.86. forráskód tartalmazza a huszármódszer C# nyelvi kódját. Az utólagos ellenőrzést a 13.85. forráskódban található függvénnyel végezhetjük el. A program futását a 13.1. videón követketjük nyomon.

13.1. videó. A huszármódszer futási képernyője

Bevezető információk: Az ún. lépcsős módszer[7] nagyon sokban hasonlít a huszármódszerre, de ennek során felfele nem kettőt, csak 1-et kell lépni, és kezdőpontja kötelezően adott. Segítségével ugyanúgy páratlan N méretű bűvös négyzeteket lehet generálni. A módszer az alábbi lépésekből áll:

Ha mindent jól csináltunk, a legmagasabb szám a mátrix legalsó sorának közepére fog esni (itt kell befejeznünk a generálást).

13.16. ábra. Lépcsős módszer

13.15. feladat (Lépcsős generáló módszerszint: 2). Készítsünk olyan programot, amely bekéri N értékét, ahol és N páratlan! Generáljunk bűvös négyzetet a lépcsős módszer segítségével, és jelenítsük meg a képernyőn táblázatos formában!

Magyarázat: Az algoritmus alapján a kód elkészítése nem különösebben nehéz (13.87. forráskód).

Bevezető információk: A mindennapi életben a keresztrejtvények szintjén a bűvös négyzetet sokkal szabadabban értelmezik. Ott gyakran csak egy olyan négyzetre gondolnak, melynek celláiban számok szerepelnek, mindegyik csak egyszer, és a sorok és oszlopok összegei egyeznek egy (az adott sorhoz és oszlophoz külön-külön megadott) értékkel. Tehát korántsem kikötés, hogy ezen oszlop- és sorösszegek egymással egyezzenek, illetve jellemzően nincs szó az átlókban szereplő összegekről. Ezen rejtvényfeladványok esetén a mátrixok kitöltését valahány elemig meg is adják, a feladvány csak ezen kezdemény jó befejezése. Ez persze papíron ceruzával ettől még igazi feladvány, melynek megoldása a fejben számolást mindenképpen fejleszti, de egyéb logikai képességeket is, és igazi sikerélményhez juttat.

13.16. feladat (Keresztrejtvény bűvös mátrixaszint: 3). Egy méretű mátrix kezdő feltöltését egy szöveges fájlban adjuk meg. A fájlban soronként N + 1 cella értéke szerepel, mely kétféle lehet: vagy egy szám szerepel (a cella értéke), vagy a nem kitöltött cellákat egy . (pont) karakter jelöli. Az utolsó szám a sorokban nem valamely cella értéke, hanem az adott sor elvárt sorösszege (és emiatt sosem pont, hanem konkrét szám szerepel ott). A mátrix méretét az első sorában szereplő számok és pont karakterek számából állapíthatjuk meg. A fájlban az N + 1 sorban a mátrix N oszlopának elvárt oszlopösszegei szerepelnek (emiatt itt csak N számérték szerepel, nem N + 1). A fájl további sorában újabb számok vannak szóközzel határolva, melyek mennyisége pontosan egyezik a korábban a mátrix nem kitöltött (pont karakterrel jelölt) celláinak számával. Ezen felhasználható számok listája alapján próbáljunk meg a kitöltetlen cellákba számokat írni oly módon, hogy a korábban megadott sor- és oszlopösszegek előálljanak! Minden felhasználható számot pontosan egyszer használhatunk fel valamely cella feltöltésére. A már kitöltött cellákban lévő számokat nem cserélhetjük ki. Ha a mátrix nem megoldható (nincs olyan feltöltés, mellyel a sor- és oszlopösszegek előállnak), akkor jelezzük (a feladat értelmezéséhez segítség a 13.84. ábra)!

13.17. ábra. Keresztrejtvény-feladvány

Magyarázat: A feladat nagyban hasonlít a 13.8. feladatban leírt antimágikus négyzet befejezéséhez. Ott is közötti kell számokkal kell kiegészíteni a mátrixot, el kell különíteni a fixen rögzített cellákat a szabad celláktól. A különbség mindössze az, mikor kapunk megfelelő kitöltést. A megoldással kapcsolatos C# függvények az 13.88... 13.94. forráskódokban olvashatóak. A program futását a 13.2. képernyőn követhetjük nyomon.

13.2. videó. A keresztrejtvény-feladat megoldása

A fejezet forráskódjai

13.41. forráskód. Duplán sztochasztikusság ellenőrzése klasszikus megoldással

     
static bool duplan_sztochasztikus(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int M = m.GetLength(1); 
   // minden eleme nemnegatív ? 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < M; j++) 
         if (m[i, j] < 0) return false; 
   // sorosszeg mindenütt 1.0 ? 
   for (int i = 0; i < N; i++) 
   { 
      double sum = 0.0; 
      for (int j = 0; j < M; j++) 
         sum = sum + m[i, j]; 
      if (sum != 1.0) return false; 
   } 
   // oszlop osszegek mindenütt 1.0 ? 
   for (int j = 0; j < M; j++) 
   { 
      double sum = 0.0; 
      for (int i = 0; i < N; i++) 
         sum = sum + m[i, j]; 
      if (sum != 1.0) return false; 
   } 
   // minden rendben 
   return true; 
}
    

13.42. forráskód. Duplán sztochasztikusság ellenőrzése optimalizált módon

 
static bool duplan_sztochasztikus_opt(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int M = m.GetLength(1); 
   double[] sorok = new double[N]; 
   double[] oszlopok = new double[M]; 
   // matrix bejarasa 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < M; j++) 
      { 
         if (m[i, j] < 0) return false; 
         sorok[i] = sorok[i] + m[i, j]; 
         oszlopok[j] = oszlopok[j] + m[i, j]; 
      } 
   // ellenorzes 
   for (int i = 0; i < N; i++) 
   if (sorok[i]!=1.0) return false; 
   for (int j = 0; j < M; j++) 
      if (oszlopok[j] != 1.0) return false; 
   // minden rendben 
   return true; 
}

13.43. forráskód. Bűvös négyzet – „buvos_negyzet_e”

 
   static bool magikus_negyzet_e(int[,] m) 
   { 
      int N = m.GetLength(0); 
      int[] sorok = new int[N]; 
      int[] oszlopok = new int[N]; 
      osszegekGen(m, sorok, oszlopok); 
      // sorok, oszlopok osszegei 
      if (mindEgyenlo(sorok) == false || 
         mindEgyenlo(oszlopok) == false || 
         sorok[0] != oszlopok[0]) return false; 
      // atlok osszegei 
      int atlo1, atlo2; 
      atlokGen(m, out atlo1, out atlo2); 
      if (atlo1 != atlo2 || atlo1 != sorok[0]) 
         return false; 
      // egyediseg 
      for (int i = 0; i < N; i++) 
         for (int j = 0; j < N; j++) 
            if (megszamol(m, m[i, j]) != 1) 
               return false; 
      // minden rendben 
      return true; 
   }

13.44. forráskód. Bűvös négyzet – „osszegekGen”

 
static void osszegekGen(int[,] m, int[] sorok, int[] oszlopok) 
{ 
 for (int i = 0; i < sorok.Length; i++) 
   for (int j = 0; j < oszlopok.Length; j++) 
   { 
   sorok[i] = sorok[i] + m[i, j]; 
   oszlopok[j] = oszlopok[j] + m[i, j]; 
   } 
}

13.45. 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.46. forráskód. Bűvös négyzet – „atlokGen”

 
   static void atlokGen(int[,] m, out int a, out int b) 
   { 
      a = 0; b = 0; 
      int N = m.GetLength(0); 
      for (int i = 0; i < N; i++) 
      { 
         a = a + m[i, i]; 
         b = b + m[i, N - i - 1]; 
      } 
   }

13.47. forráskód. Bűvös négyzet – „megszamol”

 
   static int megszamol(int[,] m, int x) 
   { 
      int N = m.GetLength(0); 
      int db = 0; 
      for (int i = 0; i < N; i++) 
         for (int j = 0; j < N; j++) 
            if (m[i, j] == x) db++; 
      return db; 
   }

13.48. forráskód. A mátrix értékeinek ellenőrzése

 
bool mindegyikPrim = true; 
for(int i=0;i<N && mindegyikPrim;i++) 
{ 
 for(int j=0;j<M && mindegyikPrim;j++) 
 { 
   if (prim-e(m[i,j]==false) 
      mindegyikPrim = false; 
 } 
}

13.49. forráskód. Jobbra-le törtátlók

 
   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 }; 
      // 
      int szin = 0; 
      for (int i = 0; i < N; i++) 
      { 
         szin = i; 
         for (int j = 0; j < N; j++) 
         { 
            Console.ForegroundColor = color[szin]; 
            Console.Write("{0,4}", m[i, j]); 
            szin++; 
            if (szin >= N) szin = 0; 
         } 
         Console.WriteLine(); 
      } 
  }
                                                                                                                                     

                                                                                                                                     
    

13.50. forráskód. Balra-le törtátlók

 
   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 }; 
      // 
      int szin = 0; 
      for (int i = 0; i < N; i++) 
      { 
         szin = i; 
         for (int j = 0; j < N; j++) 
         { 
            Console.ForegroundColor = color[szin]; 
            Console.Write("{0,4}", m[i, j]); 
            szin++; 
            if (szin >= N) szin = 0; 
         } 
         Console.WriteLine(); 
      } 
  }

13.51. 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; 
   }

13.52. 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.53. 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.54. 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.55. 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.56. 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; 
}

13.57. forráskód. Antimágikus négyzet-e – teszt főprogram

 
static void Main() 
{ 
   const int N = 5; 
   int[,] m = new int[N, N]; 
   // kezdo feltoltes 
   int a = 1; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = a; 
         a++; 
      } 
   // 
   Magikus_Kiiras_2(m); 
   // 
   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.58. forráskód. Antimágikus négyzet-e – az ellenőrző függvény

 
static bool anti_magikus_negyzet_e(int[,] m) 
{ 
 int N = m.GetLength(0); 
 int[] osszegek = new int[2*N+2]; 
 // az osszegek kepzese 
 for (int i = 0; i < N; i++) 
   for (int j = 0; j < N; j++) 
   { 
    // i. sor osszege 
    osszegek[i]  = osszegek[i] + m[i, j]; 
    // j. oszlop osszege 
    osszegek[N+j] = osszegek[i] + m[i, j]; 
    // foatlo osszege 
    if (i==j) osszegek[2 * N] = osszegek[2*N] + m[i, j]; 
    // mellekatlo osszege 
    if (i == N-j-1) osszegek[2 * N+1] = osszegek[2 * N+1] + m[i, j]; 
   } 
 
 // van-e ket egyforma osszeg ? 
 for (int i = 0; i < osszegek.Length; i++) 
   for (int j = i + 1; j < osszegek.Length; j++) 
    if (osszegek[i] == osszegek[j]) 
      return false; 
 // minden szam szerepel? 
 for (int k = 1; k <= N * N; k++) 
 { 
   int db = 0; 
   for (int i = 0; i < N; i++) 
    for (int j = 0; j < N; j++) 
      if (m[i, j] == k) db++; 
   if (db != 1) return false; 
 } 
 // minden ok 
 return true; 
}
                                                                                                                                     

                                                                                                                                     
    

13.59. forráskód. Antimágikus négyzet-e – mátrixmegjelení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.60. forráskód. Antimágikus négyzet generálása – főprogram

 
static void Main() 
{ 
   const int N = 8; 
   int[,] m = new int[N, N]; 
   int[] osszegek = new int[2 * N + 2]; 
   kezdoFeltoltes(m); 
   osszekeveres(m, N * N * 40); 
   // 
   ulong fdb = 0; 
   while (true) 
   { 
      int i, j; 
      osszegekSzamol(m, osszegek); 
      if (egyformaIndexek(osszegek, out i, out j)) 
      { 
         int a, b, c, d; 
         valasztElem(i, out a, out b, N); 
         c = rnd.Next(0, N); 
         d = rnd.Next(0, N); 
         // csere 
         int x = m[a, b]; 
         m[a, b] = m[c, d]; 
         m[c, d] = x; 
      } 
      else break; 
      // folyamat kozbeni kijelzes 
      if (fdb % 100000 == 0) 
      { 
         Console.Clear(); 
         Magikus_Kiiras_2(m); 
         Console.SetCursorPosition(0, N + 1); 
         Console.Write(fdb); 
      } 
      fdb++; 
   } 
   // 
   Console.Clear(); 
   Magikus_Kiiras_2(m); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("{0} | K É S Z ! ", fdb); 
   Console.ReadLine(); 
}

13.61. forráskód. Antimágikus négyzet generálása – az összegek számítása

 
static void osszegekSzamol(int[,] m, int[] osszegek) 
{ 
   int N = m.GetLength(0); 
   for (int i = 0; i < osszegek.Length; i++) 
      osszegek[i] = 0; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         // i. sor osszege 
         osszegek[i] = osszegek[i] + m[i, j]; 
         // j. oszlop osszege 
         osszegek[N + j] = osszegek[i] + m[i, j]; 
         // foatlo osszege 
         if (i == j) 
            osszegek[2 * N] = osszegek[2 * N] + m[i, j]; 
         // mellekatlo osszege 
         if (i == N - j - 1) 
            osszegek[2 * N + 1] = osszegek[2 * N + 1] + m[i, j]; 
      } 
}

13.62. forráskód. Antimágikus négyzet generálása – mátrix megjelenítése v2

 
static void Magikus_Kiiras_2(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   osszegekSzamol(m, osszegek); 
   int x,y; 
   egyformaIndexek(osszegek, out x, out y); 
 
   // 
   Console.ForegroundColor = ConsoleColor.Yellow; 
   for (int i = 0; i < N; i++) 
   { 
      Console.Write("  "); 
      for (int j = 0; j < N; j++) 
      { 
         Console.ForegroundColor = ConsoleColor.Yellow; 
         Console.Write("{0,3} ", m[i, j]); 
      } 
      Console.WriteLine(); 
   } 
   // sorok osszegei 
   for(int i=0;i<N;i++) 
   { 
      if (i==x || i==y) Console.ForegroundColor = ConsoleColor.Red; 
      else Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(N*4+4,i); 
      Console.Write("{0,3} ", osszegek[i]); 
   } 
   // oszlopok osszegei 
   for (int i = 0; i < N; i++) 
   { 
      if (i+N == x || i+N == y) 
        Console.ForegroundColor = ConsoleColor.Red; 
      else 
        Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(4+i*4, N); 
      Console.Write("{0,3} ", osszegek[i+N]); 
   } 
   // foatlo 
   if (2*N == x || 2*N == y) Console.ForegroundColor = ConsoleColor.Red; 
   else Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(4 + N * 4, N); 
   Console.Write("{0,3} ", osszegek[2*N]); 
   // mellektalo 
   if (2 * N+1 == x || 2 * N+1 == y) 
      Console.ForegroundColor = ConsoleColor.Red; 
   else 
      Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(0, N); 
   Console.Write("{0,3} ", osszegek[2 * N+1]); 
}

13.63. forráskód. Antimágikus négyzet generálása – elem választása

     
static void valasztElem(int i, out int a, out int b, int N) 
{ 
   // i egy sor indexe 
   if (i < N) 
   { 
      a = i; 
      b = rnd.Next(0, N); 
      return; 
   } 
   // i egy oszlop indexe 
   if (i < 2*N) 
   { 
      a = rnd.Next(0, N); 
      b = i-N; 
      return; 
   } 
   // i a foatlo 
   if (i == 2 * N) 
   { 
      a = rnd.Next(0, N); 
      b = a; 
      return; 
   } 
   // i a mellekatlo 
   a = rnd.Next(0, N); 
   b = N - a - 1; 
}
    

13.64. forráskód. Antimágikus négyzet generálása – mátrix kezdőfeltöltése

 
static void kezdoFeltoltes(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int k = 1; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = k; 
         k++; 
      } 
}

13.65. forráskód. Antimágikus négyzet generálása – elem összekeverése

 
static void osszekeveres(int[,] m, int db) 
{ 
   int N = m.GetLength(0); 
   while (db > 0) 
   { 
      int x = rnd.Next(0, N); 
      int y = rnd.Next(0, N); 
      int v = rnd.Next(0, N); 
      int w = rnd.Next(0, N); 
      // 
      int c = m[x, y]; 
      m[x, y] = m[v, w]; 
      m[v, w] = c; 
      // 
      db--; 
   } 
}

13.66. forráskód. Antimágikus négyzet generálása – egyforma index-e

 
static bool egyformaIndexek(int[] v, out int a, out int b) 
{ 
   a = -1; 
   b = -1; 
   for (int i = 0; i < v.Length; i++) 
      for (int j = i + 1; j < v.Length; j++) 
         if (v[i] == v[j]) 
         { 
            a = i; 
            b = j; 
            return true; 
         } 
   // 
   return false; 
}

13.67. forráskód. Antimágikus négyzet generálása – elem összekeverése

 
static void Main() 
{ 
   int[,] m; 
   bool[,] fix; 
   beolvasas(out m,out fix,@"hianyos-anti-magikus-negyzet.txt"); 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   Console.Clear(); 
   Magikus_Kiiras_3(m, fix); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("Kezdeti allapot beolvasva (nyomj le egy billt)"); 
   Console.ReadLine(); 
   // 
   matrixBefejez(m); 
   Console.Clear(); 
   Magikus_Kiiras_3(m, fix); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("Kezdeti allapot befejezve (nyomj le egy billt)"); 
   Console.ReadLine(); 
   // 
   ulong fdb = 0; 
   while (true) 
   { 
      int i, j; 
      osszegekSzamol(m, osszegek); 
      if (egyformaIndexek(osszegek, out i, out j)) 
      { 
         int a, b, c, d; 
         valasztElem2(i, j,out a, out b, N, fix); 
         while (true) 
         { 
            c = rnd.Next(0, N); 
            d = rnd.Next(0, N); 
            if (fix[c, d] == false) break; 
         } 
         int x = m[a, b]; 
         m[a, b] = m[c, d]; 
         m[c, d] = x; 
      } 
      else break; 
      if (fdb % 100000 == 0) 
      { 
         Console.Clear(); 
         Magikus_Kiiras_3(m,fix); 
         Console.SetCursorPosition(0, N + 1); 
         Console.Write(fdb); 
      } 
      fdb++; 
   } 
   // 
   Console.Clear(); 
   Magikus_Kiiras_3(m,fix); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("{0} | K É S Z ! ", fdb); 
   Console.ReadLine(); 
}
                                                                                                                                     

                                                                                                                                     
    

13.68. forráskód. Antimágikus négyzet generálása – beolvasás

 
static void beolvasas(out int[,] m, out bool[,] fix, string fnev) 
{ 
   m = null; 
   fix = null; 
   int N = 0; 
   int i = 0; 
   System.IO.StreamReader r = 
    new System.IO.StreamReader(fnev, System.Text.Encoding.Default); 
   while (!r.EndOfStream) 
   { 
      string s = r.ReadLine().Trim(); 
      string[] ss = s.Split(’ ’); 
      if (m == null) 
      { 
         N = ss.Length; 
         m = new int[N, N]; 
         fix = new bool[N, N]; 
      } 
      if (ss.Length != N) 
         throw new Exception("File feldolgozasi hiba"); 
      if (i>=N) 
         throw new Exception("Tul sok sor a file-ban"); 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = int.Parse(ss[j]); 
         fix[i, j] = (m[i, j] != 0); 
      } 
      i++; 
   } 
   r.Close(); 
   if (m==null) 
      throw new Exception("File ures volt"); 
}

13.69. forráskód. Antimágikus négyzet generálása – a maradék cellák kitöltése

 
static void matrixBefejez(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int k = 1; 
   for(int i=0;i<N;i++) 
   { 
      for (int j = 0; j < N; j++) 
      { 
         if (m[i, j] == 0) 
         { 
            k = kovNemSzereplo(m, k); 
            m[i, j] = k; 
         } 
      } 
   } 
}

13.70. forráskód. Antimágikus négyzet generálása – következő még nem szereplő érték keresése

 
static int kovNemSzereplo(int[,] m, int k) 
{ 
   int N = m.GetLength(0); 
   while (true) 
   { 
      int db = 0; 
      for (int i = 0; i < N && db==0; i++) 
         for (int j = 0; j < N && db == 0; j++) 
            if (k == m[i, j]) db++; 
      if (db == 0) return k; 
      k++; 
   } 
}

13.71. forráskód. Antimágikus négyzet generálása – megjelenítés (1. rész)

 
static void Magikus_Kiiras_3(int[,] m, bool[,] fix) 
{ 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   osszegekSzamol(m, osszegek); 
   int x,y; 
   egyformaIndexek(osszegek, out x, out y); 
 
   // 
   Console.ForegroundColor = ConsoleColor.Yellow; 
   for (int i = 0; i < N; i++) 
   { 
      Console.Write("  "); 
      for (int j = 0; j < N; j++) 
      { 
         if (fix[i, j]) 
         { 
            Console.BackgroundColor = ConsoleColor.Green; 
            Console.ForegroundColor = ConsoleColor.Black; 
         } 
         else 
         { 
            Console.BackgroundColor = ConsoleColor.Black; 
            Console.ForegroundColor = ConsoleColor.Yellow; 
         } 
         Console.Write("{0,3} ", m[i, j]); 
         Console.BackgroundColor = ConsoleColor.Black; 
      } 
      Console.WriteLine(); 
   } 
   // sorok osszegei 
   for(int i=0;i<N;i++) 
   { 
      if (i==x || i==y) Console.ForegroundColor = ConsoleColor.Red; 
      else Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(N*4+4,i); 
      Console.Write("{0,3} ", osszegek[i]); 
   } 
/* --- folytatása a következő forráskódban --- */

13.72. forráskód. Antimágikus négyzet generálása – megjelenítés (befejezés)

     
/* ---- folytatása a "Magikus_Kiiras_3" függvény kódjának 
  static void Magikus_Kiiras_3(int[,] m, bool[,] fix) 
  -------------------------------------------------------- */ 
 
   // oszlopok osszegei 
   for (int i = 0; i < N; i++) 
   { 
      if (i+N == x || i+N == y) 
         Console.ForegroundColor = ConsoleColor.Red; 
      else 
         Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(4+i*4, N); 
      Console.Write("{0,3} ", osszegek[i+N]); 
   } 
   // foatlo 
   if (2*N == x || 2*N == y) 
      Console.ForegroundColor = ConsoleColor.Red; 
   else 
      Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(4 + N * 4, N); 
   Console.Write("{0,3} ", osszegek[2*N]); 
   // mellektalo 
   if (2 * N+1 == x || 2 * N+1 == y) 
     Console.ForegroundColor = ConsoleColor.Red; 
   else 
     Console.ForegroundColor = ConsoleColor.Green; 
   Console.SetCursorPosition(0, N); 
   Console.Write("{0,3} ", osszegek[2 * N+1]); 
   Console.ForegroundColor = ConsoleColor.Gray; 
}
    

13.73. forráskód. Antimágikus négyzet generálása – cserélendő cellák választása

 
static void valasztElem2(int i, int j,out int a, out int b, 
                  int N, bool[,] fix) 
{ 
   while (true) 
   { 
      valasztElem(i, out a, out b, N); 
      if (fix[a, b] == false) return; 
      valasztElem(j, out a, out b, N); 
      if (fix[a, b] == false) return; 
   } 
}

13.74. forráskód. Szép anti bűvös négyzet ellenőrzés

 
static bool szep_magikus_negyzet_e(int[,] m) 
{ 
   int N = m.GetLength(0); 
   int[] osszegek = new int[2 * N + 2]; 
   osszegekSzamol(m, osszegek); 
   // sorok osszegei 
   for (int i = 1; i < N; i++) 
      if (osszegek[i - 1] != osszegek[i] + 1) 
         return false; 
   // oszlopok osszegei 
   for (int i = N; i < 2*N; i++) 
      if (osszegek[i - 1] != osszegek[i] + 1) 
         return false; 
   // minden rendben 
   return true; 
}

13.75. forráskód. Kártyás – főprogram

 
static void Main() 
{ 
   const int N = 4; 
   int[,] m = new int[N,N]; 
   kezdoFeltoltes(m); 
   ulong fdb = 0; 
   int v,w; 
   DateTime start = DateTime.Now; 
   while (matrixRendben(m, out v, out w ) == false) 
   { 
      int x = rnd.Next(0, N); 
      int y = rnd.Next(0, N); 
      // 
      int c = m[x, y]; 
      m[x, y] = m[v, w]; 
      m[v, w] = c; 
      // 
      // fdb++; 
      // if (fdb % 1000000 == 0) Megjelenit(m); 
   } 
   DateTime stop = DateTime.Now; 
   TimeSpan kul = stop - start; 
   Megjelenit(m); 
   Console.WriteLine(); 
   Console.WriteLine(); 
   Console.ForegroundColor = ConsoleColor.Gray; 
   Console.WriteLine("Futasi ido={0}", kul); 
   Console.ReadLine(); 
}

13.76. forráskód. Kártyás – megjelenítés

 
static void Megjelenit(int[,] m) 
{ 
   Console.Clear(); 
   int N = m.GetLength(0); 
   ConsoleColor[] szinek = new ConsoleColor[] 
      { ConsoleColor.Green, ConsoleColor.Red, 
        ConsoleColor.Cyan, ConsoleColor.Yellow}; 
   string[] lapok = new string[] { "also", "felso", "kiraly", "asz" }; 
   for (int i = 0; i < N; i++) 
   { 
      for (int j = 0; j < N; j++) 
      { 
         Console.SetCursorPosition(j * 8, i * 2); 
         int x = m[i, j]; 
         int v = x / 10 - 1; 
         int w = x % 10 - 1; 
         Console.ForegroundColor = szinek[v]; 
         Console.Write(lapok[w]); 
      } 
   } 
}
                                                                                                                                     

                                                                                                                                     
    

13.77. forráskód. Kártyás – a mátrix megfelelőségének ellenőrzése

 
static bool matrixRendben(int[,] m, out int k, out int l) 
{ 
   k = -1; 
   l = -1; 
   int N = m.GetLength(0); 
   for (int i = 0; i < N; i++) 
   { 
      if (sorRendben(m, i, N, out l) == false) 
      { 
        k = i; 
        return false; 
      } 
      if (oszlopRendben(m, i, N, out k) == false) 
      { 
       l = i; 
       return false; 
      } 
   } 
   if (atlokRendben(m, N,out k, out l) == false) 
      return false; 
   return true; 
}

13.78. forráskód. Kártyás – átlók megfelelőségének ellenőrzése

 
static bool atlokRendben(int[,] m, int N, out int v, out int w) 
{ 
   v = -1; 
   w = -1; 
   for (int i = 0; i < N; i++) 
    for (int j = i + 1; j < N; j++) 
    { 
      if (hasonlo(m[i, i], m[j, j])) 
      { 
        v = i; 
        w = i; 
        return false; 
      } 
      if (hasonlo(m[i, N - i - 1], m[j, N - j - 1])) 
      { 
        v = i; 
        w = N - i - 1; 
        return false; 
      } 
    } 
   // 
   return true; 
}

13.79. forráskód. Kártyás – a mátrix k. oszlopának ellenőrzése

 
static bool oszlopRendben(int[,] m, int k, int N, out int w) 
{ 
   w = -1; 
   for (int i = 0; i < N; i++) 
      for (int j = i + 1; j < N; j++) 
         if (hasonlo(m[i, k], m[j, k])) { w = i; return false; } 
   // 
   return true; 
}

13.80. forráskód. Kártyás – a mátrix k. sorának ellenőrzése

 
static bool sorRendben(int[,] m, int k, int N, out int w) 
{ 
   w = -1; 
   for (int i = 0; i < N; i++) 
      for (int j = i + 1; j < N; j++) 
         if (hasonlo(m[k, i], m[k, j])) { w = i; return false; } 
   // 
   return true; 
}

13.81. forráskód. Kártyás – két cella színének és lapjának vizsgálata

     
static bool hasonlo(int a, int b) 
{ 
   if (a / 10 == b / 10 || a % 10 == b % 10) return true; 
   return false; 
}
    

13.82. forráskód. Kártyás – a mátrix kezdő feltöltése

 
static void kezdoFeltoltes(int[,] m) 
{ 
   int N = m.GetLength(0); 
   for (int i = 0; i < N; i++) 
   { 
      int k = (i+1)*10+1; 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = k; 
         k++; 
      } 
   } 
}

13.83. forráskód. Latin négyzet feltöltése

 
static void latinFeltoltes(int[,] m) 
{ 
   int N = m.GetLength(0); 
   for (int i = 0; i < N; i++) 
   { 
      int k = 1+ i; 
      for (int j = 0; j < N; j++) 
      { 
         m[i, j] = k; 
         k++; 
         if (k > N) k = 1; 
      } 
   } 
}

13.84. forráskód. K-ad fokú bűvös négyzetek

 
static List<int> K_ad_foku(int[,] m) 
{ 
   List<int> ret = new List<int>(); 
   int N = m.GetLength(0); 
   int[,] mm = (int[,])(m.Clone()); 
   for (int k = 2; k <= 10; k++) 
   { 
      // hatvanyozas 
      for (int i = 0; i < N; i++) 
         for (int j = 0; j < N; j++) 
            mm[i, j] = mm[i, j] * m[i, j]; 
      // ellenorzes 
      if (magikus_negyzet_e(mm)) 
         ret.Add(k); 
   } 
   return ret; 
}

13.85. forráskód. Kiegészítő ellenőrzés a bűvös négyzethez

 
for(int k=0;k<N*N;k++) 
if (megszamol(m, k) != 1) 
  return false;
                                                                                                                                     

                                                                                                                                     
    

13.86. forráskód. Huszármódszer algoritmusa

 
static void huszarModszer(int[,] m) 
{ 
   int N = m.GetLength(0); // paratlan! 
   int y = rnd.Next(0,N); 
   int x = rnd.Next(0, N); 
   // kezdo pozicio 
   m[x, y] = 1; 
   // 
   int db=1; 
   int k = 2; 
   while (db < N * N) 
   { 
      // fel fel jobbra 
      int yy = y-2; 
      int xx = x+1; 
      // kilepunk fenn? 
      if (yy < 0) yy = N + yy; 
      // kilepunk jobbra 
      if (xx>=N) xx=0; 
      // ez a cella mar foglalt? 
      if (m[xx, yy] != 0) 
      { 
         xx = x; 
         yy = y + 1; 
         if (yy >= N) yy = 0; 
      } 
      if (m[xx, yy] != 0) 
         throw new Exception("valami nem stimmel"); 
      // szam elhelyezese 
      m[xx, yy] = k; 
      // ez az uj aktualis cella 
      x = xx; 
      y = yy; 
      // szamlalok 
      k++; 
      db++; 
   } 
}

13.87. forráskód. Lépcsős módszer forráskódja

 
static void lepcsosModszer(int[,] m) 
{ 
   int N = m.GetLength(0); // paratlan! 
   int y = 0; 
   int x = N / 2; 
   // elso sor kozepe 
   m[x, y] = 1; 
   // 
   int db=1; 
   int k = 2; 
   while (db < N * N) 
   { 
      // fel jobbra 
      int yy = y-1; 
      int xx = x+1; 
      // kilepunk fenn? 
      if (yy < 0) yy = N - 1; 
      // kilepunk jobbra 
      if (xx>=N) xx=0; 
      // ez a cella mar foglalt? 
      if (m[xx, yy] != 0) 
      { 
         xx = x; 
         yy = y + 1; 
         if (yy >= N) yy = 0; 
      } 
      if (m[xx, yy] != 0) 
         throw new Exception("valami nem stimmel"); 
      // szam elhelyezese 
      m[xx, yy] = k; 
      // ez az uj aktualis cella 
      x = xx; 
      y = yy; 
      // szamlalok 
      k++; 
      db++; 
   } 
}

13.88. forráskód. Keresztrejtvény – főprogram

 
static void Main() 
{ 
   int[,] m; 
   bool[,] fix; 
   int[] osszegek; 
   List<int> l = new List<int>(); 
   beolvasas_rejtv(out m, out fix, out osszegek, l, "negyzet.txt"); 
   int N = m.GetLength(0); 
   Magikus_Kiiras_4(m, fix,osszegek); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("Kezdeti allapot beolvasva"); 
   Console.ReadLine(); 
   // 
   matrixBefejez_4(m,l); 
   Console.Clear(); 
   Magikus_Kiiras_4(m, fix, osszegek); 
   Console.SetCursorPosition(0, N + 2); 
   Console.WriteLine("Kezdeti allapot befejezve"); 
   Console.ReadLine(); 
   // 
   ulong fdb = 0; 
   int[] sumst = new int[N * 2]; 
   while (true) 
   { 
      int i; 
      osszegekSzamol_4(m, sumst); 
      if (elteroOsszeg(osszegek, sumst, out i)) 
      { 
         int a, b, c, d; 
         valasztElem_4(i, out a, out b, N, fix); 
         while (true) 
         { 
            c = rnd.Next(0, N); 
            d = rnd.Next(0, N); 
            if (fix[c, d] == false) break; 
         } 
         // csere 
         int x = m[a, b]; 
         m[a, b] = m[c, d]; 
         m[c, d] = x; 
      } 
      else break; 
      if (fdb % 100000 == 0) 
      { 
         Console.Clear(); 
         Magikus_Kiiras_4(m, fix, osszegek); 
         Console.SetCursorPosition(50, N + 2); 
         Console.Write(fdb); 
      } 
      fdb++; 
   } 
   // 
   Console.Clear(); 
   Magikus_Kiiras_4(m, fix, osszegek); 
   Console.ReadLine(); 
}

13.89. forráskód. Keresztrejtvény – rejtvény beolvasása

 
static void beolvasas_rejtv(out int[,] m, out bool[,] fix, 
         out int[] osszegek, List<int> szamok, string fnev) 
{ 
   m = null; 
   fix = null; 
   osszegek = null; 
   int N = 0; 
   int i = 0; 
   System.IO.StreamReader r = 
      new System.IO.StreamReader(fnev, System.Text.Encoding.Default); 
   while (!r.EndOfStream) 
   { 
      string s = r.ReadLine().Trim(); 
      string[] ss = s.Split(’ ’); 
      if (m == null) 
      { 
         N = ss.Length-1; 
         m = new int[N, N]; 
         fix = new bool[N, N]; 
         osszegek = new int[2 * N]; 
      } 
      if (i == N) // utolso sor 
      { 
         for (int j = 0; j < N; j++) 
            osszegek[N + j] = int.Parse(ss[j]); 
      } 
      else if (i == N+1) // felhasznalhato szamok 
      { 
         for (int j = 0; j < ss.Length; j++) 
            szamok.Add(int.Parse(ss[j])); 
      } 
      else 
      { 
         if (i > N+1) 
            throw new Exception("Tul sok sor a file-ban"); 
         for (int j = 0; j < N + 1; j++) 
         { 
            if (j == N) osszegek[i] = int.Parse(ss[j]); 
            else 
            { 
               if (ss[j] == ".") m[i, j] = 0; 
               else m[i, j] = int.Parse(ss[j]); 
               fix[i, j] = (m[i, j] != 0); 
            } 
         } 
      } 
      i++; 
   } 
   r.Close(); 
   if (m == null) 
      throw new Exception("File ures volt"); 
}

13.90. forráskód. Keresztrejtvény – eltérő összegek keresése

     
static bool elteroOsszeg(int[] osszegek, int[] sumst, out int i) 
{ 
   i = -1; 
   for (int k = 0; k < osszegek.Length; k++) 
   { 
      if (osszegek[k] != sumst[k]) 
      { 
         i = k; 
         return true; 
      } 
   } 
   return false; 
}
    

13.91. forráskód. Keresztrejtvény – sor- és oszlopösszegek számítása

 
static void osszegekSzamol_4(int[,] m, int[] osszegek) 
{ 
   int N = m.GetLength(0); 
   for (int i = 0; i < osszegek.Length; i++) 
      osszegek[i] = 0; 
   for (int i = 0; i < N; i++) 
      for (int j = 0; j < N; j++) 
      { 
         // i. sor osszege 
         osszegek[i] = osszegek[i] + m[i, j]; 
         // j. oszlop osszege 
         osszegek[N + j] = osszegek[N+j] + m[i, j]; 
      } 
}

13.92. forráskód. Keresztrejtvény – megjelenítés

 
static void Magikus_Kiiras_4(int[,] m, bool[,] fix, int[] sums) 
{ 
   int N = m.GetLength(0); 
   int[] sum2 = new int[2 * N + 2]; 
   osszegekSzamol_4(m, sum2); 
   // 
   Console.ForegroundColor = ConsoleColor.Yellow; 
   for (int i = 0; i < N; i++) 
   { 
      Console.Write("  "); 
      for (int j = 0; j < N; j++) 
      { 
         if (fix[i, j]) 
         { 
            Console.BackgroundColor = ConsoleColor.Green; 
            Console.ForegroundColor = ConsoleColor.Black; 
         } 
         else 
         { 
            Console.BackgroundColor = ConsoleColor.Black; 
            Console.ForegroundColor = ConsoleColor.Yellow; 
         } 
         Console.Write("{0,3} ", m[i, j]); 
         Console.BackgroundColor = ConsoleColor.Black; 
      } 
      Console.WriteLine(); 
   } 
   // sorok osszegei 
   for (int i = 0; i < N; i++) 
   { 
      if (sum2[i]!=sums[i]) Console.ForegroundColor = ConsoleColor.Red; 
      else Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(N * 4 + 4, i); 
      Console.Write("{0,3} ", sum2[i]); 
      Console.ForegroundColor = ConsoleColor.Gray; 
      Console.Write("{0,3} ", sums[i]); 
   } 
   // oszlopok osszegei 
   for (int i = 0; i < N; i++) 
   { 
      if (sum2[N+i] != sums[N+i]) 
         Console.ForegroundColor = ConsoleColor.Red; 
      else 
         Console.ForegroundColor = ConsoleColor.Cyan; 
      Console.SetCursorPosition(4 + i * 4, N); 
      Console.Write("{0,3} ", sum2[i + N]); 
      Console.SetCursorPosition(4 + i * 4, N+1); 
      Console.ForegroundColor = ConsoleColor.Gray; 
      Console.Write("{0,3} ", sums[N+i]); 
   } 
   Console.ForegroundColor = ConsoleColor.Gray; 
}

13.93. forráskód. Keresztrejtvény – kezdő kitöltés befejezése

 
static void matrixBefejez_4(int[,] m, List<int> szamok) 
{ 
   int N = m.GetLength(0); 
   int k = 0; 
   for (int i = 0; i < N; i++) 
   { 
      for (int j = 0; j < N; j++) 
      { 
         if (m[i, j] == 0) 
         { 
            m[i, j] = szamok[k]; 
            k++; 
         } 
      } 
   } 
}

13.94. forráskód. Keresztrejtvény – cserélendő elem választása

 
static void valasztElem_4(int i, out int a, out int b, 
                     int N, bool[,] fix) 
{ 
   while (true) 
   { 
      valasztElem(i, out a, out b, N); 
      if (fix[a, b] == false) return; 
   } 
}



[1] Nincs igazán konszenzus az angol és magyar elnevezésekben. Angolul létező fogalmak a „magic square” és „mystic square”, ami két hasonló, bár egy ponton különböző dolog. A „mystic square”-ben az is követelmény, hogy az négyzetben csak közötti számok fordulhatnak elő. Ennek megfelelője jegyzetünkben a „bűvös négyzet”, a „magic square”-t ellenben „mágikus négyzetnek” fordítjuk.

[2] egyben bűvös négyzet

[3] egyben bűvös négyzet

[4] angolul néha Border Square-nek nevezik

[5] Bimagic square

[6] Trimagic square

[7] Staircase method