Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Microsoft.VisualBasic;
- using System.Text;
- using System.Text.Json;
- namespace MestInt
- {
- /// <summary>
- /// Minden állapot osztály őse.
- /// </summary>
- public abstract class AbsztraktÁllapot : ICloneable
- {
- // Megvizsgálja, hogy a belső állapot állapot-e.
- // Ha igen, akkor igazat ad vissza, egyébként hamisat.
- public abstract bool ÁllapotE();
- // Megvizsgálja, hogy a belső állapot célállapot-e.
- // Ha igen, akkor igazat ad vissza, egyébként hamisat.
- public abstract bool CélÁllapotE();
- // Visszaadja az alapoperátorok számát.
- public abstract int OperátorokSzáma();
- // A szuper operátoron keresztül lehet elérni az összes operátort.
- // Igazat ad vissza, ha az i.dik alap operátor alkalmazható a belső állapotra.
- // for ciklusból kell hívni 0-tól kezdve az alap operátorok számig. Pl. így:
- // for (int i = 0; i < állapot.GetNumberOfOps(); i++)
- // {
- // AbsztraktÁllapot klón=(AbsztraktÁllapot)állapot.Clone();
- // if (klón.SzuperOperátor(i))
- // {
- // Console.WriteLine("Az {0} állapotra az {1}.dik " +
- // "operátor alkalmazható", állapot, i);
- // }
- // }
- public abstract bool SzuperOperátor(int i);
- // Klónoz. Azért van rá szükség, mert némelyik operátor hatását vissza kell vonnunk.
- // A legegyszerűbb, hogy az állapotot leklónozom. Arra hívom az operátort.
- // Ha gond van, akkor visszatérek az eredeti állapothoz.
- // Ha nincs gond, akkor a klón lesz az állapot, amiből folytatom a keresést.
- // Ez sekély klónozást alkalmaz. Ha elég a sekély klónozás, akkor nem kell felülírni a gyermek osztályban.
- // Ha mély klónozás kell, akkor mindenképp felülírandó.
- public virtual object Clone() { return MemberwiseClone(); }
- // Csak akkor kell felülírni, ha emlékezetes backtracket akarunk használni, vagy mélységi keresést.
- // Egyébként maradhat ez az alap implementáció.
- // Programozás technikailag ez egy kampó metódus, amit az OCP megszegése nélkül írhatok felül.
- public override bool Equals(Object a) { return false; }
- // Ha két példány egyenlő, akkor a hasítókódjuk is egyenlő.
- // Ezért, ha valaki felülírja az Equals metódust, ezt is illik felülírni.
- public override int GetHashCode() { return base.GetHashCode(); }
- }
- public class Feladat_2_38 : AbsztraktÁllapot
- {
- int ember1_testsúly;
- int ember2_testsúly;
- int ember3_testsúly;
- int kő_súly;
- int toronyban;
- int földszinten;
- int kosár1;
- int kosár2;
- bool kosár1_földszinten;
- bool kosár2_földszinten;
- public Feladat_2_38()
- {
- ember1_testsúly = 78;
- ember2_testsúly = 42;
- ember3_testsúly = 36;
- kő_súly = 30;
- toronyban = 186;
- földszinten = 0;
- kosár1 = 0;
- kosár2 = 0;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- public override bool CélÁllapotE()
- {
- //ember1, ember2, ember3 testsúlyának összege
- return földszinten == 156 && kosár1_földszinten == true && kosár2_földszinten == false;
- }
- public override int OperátorokSzáma()
- {
- //szuperoperátorok számának az összege
- return 25;
- }
- public override bool SzuperOperátor(int i)
- {
- switch (i)
- {
- case 0: return kosár2_kő_be();
- case 1: return kosár1_ember3_be();
- case 2: return kosár2_kő_ki();
- case 3: return kosár1_ember3_ki();
- case 4: return kosár1_ember1_be();
- case 5: return kosár2_ember2_kő_be();
- case 6: return kosár2_ember2_ki();
- case 7: return kosár1_ember1_ki();
- case 8: return kosár1_ember3_be2();
- case 9: return kosár2_kő_ki2();
- case 10: return kosár2_ember2_be();
- case 11: return kosár1_ember3_ki2();
- case 12: return kosár2_ember2_ki2();
- case 13: return kosár1_kő_be();
- case 14: return kosár2_ember3_be();
- case 15: return kosár2_ember3_ki();
- case 16: return ujeset();
- case 17: return ujeset2();
- case 18: return ujeset3();
- case 19: return ujeset4();
- case 20: return ujeset5();
- case 21: return ujeset6();
- case 22: return ujeset7();
- case 24: return ujeset8();
- default: return false;
- }
- }
- private bool ujeset8()
- {
- if (toronyban == 0 && kosár1 == 0 && kosár2 == 30 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 156)
- {
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset7()
- {
- if (toronyban == 0 && kosár1 == 36 && kosár2 == 30 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 120)
- {
- kosár1 = kosár1 - ember3_testsúly;
- földszinten = földszinten + ember3_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset6()
- {
- if (toronyban == 36 && kosár1 == 0 && kosár2 == 30 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 120)
- {
- kosár1 = kosár1 + ember3_testsúly;
- toronyban = toronyban - ember3_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset5()
- {
- if (toronyban == 66 && kosár1 == 0 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 120)
- {
- kosár2 = kosár2 + kő_súly;
- toronyban = toronyban - kő_súly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset4()
- {
- if (toronyban == 66 && kosár1 == 42 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 78)
- {
- kosár1 = kosár1 - ember2_testsúly;
- földszinten = földszinten + ember2_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset3()
- {
- if (toronyban == 30 && kosár1 == 42 && kosár2 == 36 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 78)
- {
- kosár2 = kosár2 - ember3_testsúly;
- toronyban = toronyban + ember3_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset2()
- {
- if (toronyban == 72 && kosár1 == 0 && kosár2 == 0 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 114)
- {
- kosár2 = kosár2 - ember3_testsúly;
- földszinten = földszinten - ember3_testsúly;
- kosár1 = kosár1 + ember2_testsúly;
- toronyban = toronyban - ember2_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool ujeset()
- {
- if (toronyban == 72 && kosár1 == 0 && kosár2 == 36 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 78)
- {
- kosár2 = kosár2 - ember3_testsúly;
- földszinten = földszinten + ember3_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_ember3_ki()
- {
- if (toronyban == 42 && kosár1 == 30 && kosár2 == 36 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 78)
- {
- kosár1 = kosár1 - kő_súly;
- toronyban = toronyban + kő_súly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- return true;
- }
- return ÁllapotE();
- }
- private bool kosár2_ember3_be()
- {
- if (toronyban == 78 && kosár1 == 30 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 78)
- {
- kosár2 = kosár2 + ember3_testsúly;
- toronyban = toronyban - ember3_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_kő_be()
- {
- if (toronyban == 108 && kosár1 == 0 && kosár2 == 0 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 78)
- {
- kosár1 = kosár1 + kő_súly;
- toronyban = toronyban - kő_súly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_ember2_ki2()
- {
- if (toronyban == 108 && kosár1 == 0 && kosár2 == 78 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 0)
- {
- kosár2 = kosár2 - ember1_testsúly;
- földszinten = földszinten + ember1_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_ember3_ki2()
- {
- if (toronyban == 36 && kosár1 == 72 && kosár2 == 78 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 0)
- {
- kosár1 = (kosár1 - ember2_testsúly) - kő_súly;
- toronyban = (toronyban + ember2_testsúly) + kő_súly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_ember2_be()
- {
- if (toronyban == 114 && kosár1 == 72 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 0)
- {
- kosár2 = kosár2 + ember1_testsúly;
- toronyban = toronyban - ember1_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_kő_ki2()
- {
- if (toronyban == 114 && kosár1 == 30 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 42)
- {
- kosár1 = kosár1 + ember2_testsúly;
- földszinten = földszinten - ember2_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_ember3_be2()
- {
- if (toronyban == 144 && kosár1 == 0 && kosár2 == 0 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 42)
- {
- kosár1 = kosár1 + kő_súly;
- toronyban = toronyban - kő_súly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_ember1_ki()
- {
- if (toronyban == 144 && kosár1 == 0 && kosár2 == 42 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 0)
- {
- kosár2 = kosár2 - ember2_testsúly;
- földszinten = földszinten + ember2_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_ember2_ki()
- {
- if (toronyban == 108 && kosár1 == 36 && kosár2 == 42 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 0)
- {
- kosár1 = kosár1 - ember3_testsúly;
- toronyban = toronyban + ember3_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_ember2_kő_be()
- {
- if (toronyban == 150 && kosár1 == 36 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 0)
- {
- kosár2 = kosár2 + ember2_testsúly;
- toronyban = toronyban - ember2_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_ember1_be()
- {
- if (toronyban == 150 && kosár1 == 0 && kosár2 == 0 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 36)
- {
- kosár1 = kosár1 + ember3_testsúly;
- földszinten = földszinten - ember3_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_ember3_ki()
- {
- if (toronyban == 150 && kosár1 == 36 && kosár2 == 0 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 0)
- {
- kosár1 = kosár1 - ember3_testsúly;
- földszinten = földszinten + ember3_testsúly;
- kosár1_földszinten = false;
- kosár2_földszinten = true;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_kő_ki()
- {
- if (toronyban == 120 && kosár1 == 36 && kosár2 == 30 && kosár1_földszinten == true && kosár2_földszinten == false && földszinten == 0)
- {
- kosár2 = kosár2 - kő_súly;
- toronyban = toronyban + kő_súly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár1_ember3_be()
- {
- if (toronyban == 156 && kosár1 == 0 && kosár2 == 30 && kosár1_földszinten == false && kosár2_földszinten == true && földszinten == 0)
- {
- toronyban = toronyban - ember3_testsúly;
- kosár1 = kosár1 + ember3_testsúly;
- kosár1_földszinten = true;
- kosár2_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- private bool kosár2_kő_be()
- {
- if (toronyban == 186 && kosár1_földszinten == true && kosár2_földszinten == false && kosár1 == 0 && kosár2 == 0 && földszinten == 0)
- {
- kosár2 = kosár2 + kő_súly;
- toronyban = toronyban - kő_súly;
- kosár2_földszinten = true;
- kosár1_földszinten = false;
- }
- else
- {
- return false;
- }
- return ÁllapotE();
- }
- public override bool ÁllapotE()
- {
- return toronyban >= 0 && Math.Abs(kosár1 - kosár2) >= 6 && toronyban <= 186;
- }
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("földszint: ");
- sb.Append(földszinten);
- sb.Append(" torony: ");
- sb.Append(toronyban);
- sb.Append(" kosár1: " );
- sb.Append(kosár1);
- sb.Append(" kosár 2: ");
- sb.Append(kosár2);
- return sb.ToString();
- }
- }
- //probléma redukció: természetes megoldási
- //először is van egy célom
- //a következő részt célt azt úgy érem el hogy amit eddig csináltam azt nem rontom el
- public class Feladat_1_3 : AbsztraktÁllapot
- {
- int[,] tábla = { {1,5,3,4,3,6,7,1,1,6 },
- {4,4,3,4,2,6,2,6,2,5 },
- {1,3,9,4,5,2,4,2,9,5 },
- {5,2,3,5,5,6,4,6,2,4 },
- {1,3,3,2,5,6,5,2,3,2 },
- {2,5,2,5,5,6,4,8,6,1 },
- {9,2,3,6,5,6,2,2,2,0 } };
- int figX, figY;
- public Feladat_1_3() { figX = 0; figY = 0; }
- public override bool CélÁllapotE()
- {
- //return figX == 6 && figY == 9;
- return tábla[figX, figY] == 0;
- }
- public override int OperátorokSzáma()
- {
- return 8;
- }
- public override bool SzuperOperátor(int i)
- {
- switch (i)
- {
- case 0: return lépés(0, 1);
- case 1: return lépés(0, -1);
- case 2: return lépés(1, 0);
- case 3: return lépés(-1, 0);
- case 4: return lépés(1, 1);
- case 5: return lépés(-1, -1);
- case 6: return lépés(-1, 1);
- case 7: return lépés(1, -1);
- default : return false;
- }
- }
- private bool lépés(int xirány, int yirány)
- {
- //előfeltétel
- //if(!preLépés(xirány,yirány)) return false;
- //állapot átmenet
- int lépésSzám = tábla[figX, figY];
- figX += lépésSzám * xirány;
- figY += lépésSzám * yirány;
- //utófeltétel
- if (ÁllapotE()) return true; else return false;
- }
- public override bool ÁllapotE()
- {
- return figX >= 0 && figX <= 6 && figY >=0 && figY <=9;
- }
- //klónozást nem kell felülírni, habár van tömb de az nem változik, két int mező van, e miatt nem kell klónozás
- //viszont lehet kör, e miatt Equals-t felül kell írni kiíratáshoz
- public override bool Equals(object a)
- {
- //típus kényszerítés
- Feladat_1_3 másik = a as Feladat_1_3;
- //minden mezőnek egyenlőnek kell lenni
- return this.figX == másik.figX && this.figY == másik.figY;
- }
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("figX=");
- sb.Append(figX);
- sb.Append(", figY=");
- sb.Append(figY);
- sb.Append(", tábla [figX, figY]=");
- sb.Append(tábla[figX, figY]);
- return sb.ToString();
- }
- }
- public class Feladat2p8 : AbsztraktÁllapot
- {
- //kezdoállapot
- int[,] tábla = { {2,3,4,5,1},
- {6,7,8,9,10},
- {11,12,13,14,15},
- {16,17,18,19,20},
- {21,22,23,24,25}
- };
- public int[,] GetTábla() { return tábla; }
- int[,] céltábla = { {1,2,3,4,5},
- {6,7,8,9,10},
- {11,12,13,14,15},
- {16,17,18,19,20},
- {21,22,23,24,25}
- };
- public override bool CélÁllapotE()
- {
- for (int i = 0; i < tábla.GetLength(0); i++)
- {
- for (int j = 0; j < tábla.GetLength(1); j++)
- {
- //ha a két aktuális elem nem egyenlő return false
- if (tábla[i, j] != céltábla[i, j])
- return false;
- }
- }
- return true;
- }
- public override int OperátorokSzáma()
- {
- return 20;
- }
- public override bool SzuperOperátor(int i)
- {
- switch (i)
- {
- case 0: return forgatBalra(0);
- case 1: return forgatBalra(1);
- case 2: return forgatBalra(2);
- case 3: return forgatBalra(3);
- case 4: return forgatBalra(4);
- case 5: return forgatJobbra(0);
- case 6: return forgatJobbra(1);
- case 7: return forgatJobbra(2);
- case 8: return forgatJobbra(3);
- case 9: return forgatJobbra(4);
- case 10: return forgatFel(0);
- case 11: return forgatFel(1);
- case 12: return forgatFel(2);
- case 13: return forgatFel(3);
- case 14: return forgatFel(4);
- case 15: return forgatLe(0);
- case 16: return forgatLe(1);
- case 17: return forgatLe(2);
- case 18: return forgatLe(3);
- case 19: return forgatLe(4);
- default: return false;
- }
- }
- public override bool ÁllapotE()
- {
- return true;
- }
- // Nem biztos hogy jól csináltuk, csináljunk unit tesztet
- // A unit teszt a metódusok tesztje
- // Ehhez szükséges egy unit teszt framework (java: JUNIT5, c#: MSTEST, NTEST)
- // A lépések nem intuitívak.
- // [TestMethod]
- // Minden unit testben 5 dolog van: target, fix paraméterek, expected value(elvárt), actual value(aktuális érték), és a kettő összehasonlítása
- // target:: tesztelendő cucc egy példánya
- public bool forgatBalra(int sor)
- {
- int elsőElem = tábla[sor, 0];
- for (int i = 1; i < tábla.GetLength(1); i++)
- {
- tábla[sor, i - 1] = tábla[sor, i];
- }
- tábla[sor, tábla.GetLength(1) - 1] = elsőElem;
- return true;
- }
- public bool forgatJobbra(int sor)
- {
- int utolsóElem = tábla[sor, tábla.GetLength(1) - 1];
- for (int i = tábla.GetLength(1) - 2; i >= 0; i--)
- {
- tábla[sor, i + 1] = tábla[sor, i];
- }
- tábla[sor, 0] = utolsóElem;
- return true;
- }
- public bool forgatFel(int oszlop)
- {
- int felsoElem = tábla[0, oszlop];
- for (int i = 1; i < tábla.GetLength(0); i++)
- {
- tábla[i - 1, oszlop] = tábla[i, oszlop];
- }
- tábla[tábla.GetLength(0) - 1, oszlop] = felsoElem;
- return true;
- }
- public bool forgatLe(int oszlop)
- {
- int alsoElem = tábla[tábla.GetLength(0) - 1, oszlop];
- for (int i = tábla.GetLength(0) - 2; i >= 0; i--)
- {
- tábla[i + 1, oszlop] = tábla[i, oszlop];
- }
- tábla[0, oszlop] = alsoElem;
- return true;
- }
- public override object Clone()
- {
- Feladat2p8 myClone = new Feladat2p8();
- myClone.tábla = this.tábla.Clone() as int[,];
- return myClone;
- }
- public override bool Equals(object? a)
- {
- Feladat2p8 másik = a as Feladat2p8;
- return másik.tábla.Equals(this.tábla);
- }
- class Macska
- {
- string név;
- double éhség;
- string[] csíkok;
- public override bool Equals(object? obj)
- {
- Macska másik = obj as Macska;
- return másik.név == this.név &&
- másik.éhség == this.éhség &&
- másik.csíkok.Equals(this.csíkok);
- }
- }
- // Ha elképzelhető hogy visszajutok ugyanabba az állapotba akkor felül kell írni az Equals-t is
- // Ez végtelen ciklust okozhat
- // Minden mezőt fel kell használni
- // Két objektum akkor egyenlő ha minden mezőjük egyenlő
- public override string ToString()
- {
- //minden mezőt fel kell használni
- StringBuilder sb = new StringBuilder();
- for(int i = 0;i<tábla.GetLength(0);i++)
- {
- for (int j = 0; j < tábla.GetLength(1); j++)
- {
- sb.Append(tábla[i, j]);
- sb.Append(" ");
- }
- sb.Append('\n');
- }
- return sb.ToString();
- }
- }
- class Feladat2p5 : AbsztraktÁllapot
- {
- int alma, körte, barack;
- public Feladat2p5()
- {
- alma = 1;
- körte = 1;
- barack = 59;
- }
- public override bool CélÁllapotE()
- {
- return (alma == 0 && körte == 0) ||
- (alma == 0 && barack == 0) ||
- (barack == 0 && körte == 0);
- }
- public override int OperátorokSzáma()
- {
- //egy almát és egy körtét 2 barackra
- //egy almát és egy barackot 2 körtére
- //egy körtét és egy barackor 2 almára
- return 3;
- }
- public override bool SzuperOperátor(int i)
- {
- switch (i)
- {
- case 0: return barackra();
- case 1: return körtére();
- case 2: return almára();
- default: return false;
- }
- }
- private bool barackra()
- {
- if (alma == 0 || körte == 0) return false;
- alma--;
- körte--;
- barack += 2;
- return ÁllapotE();
- }
- private bool körtére()
- {
- if (alma == 0 || barack == 0) return false;
- alma--;
- barack--;
- körte += 2;
- return ÁllapotE();
- }
- private bool almára()
- {
- if (barack == 0 || körte == 0) return false;
- barack--;
- körte--;
- alma += 2;
- return ÁllapotE();
- }
- public override bool ÁllapotE()
- {
- return alma >= 0 && körte >= 0 && barack >= 0;
- }
- public override string ToString()
- {
- //minden mezőt fel kell használni
- StringBuilder sb = new StringBuilder();
- sb.Append("alma= ").Append(alma)
- .Append(", körte= ").Append(körte)
- .Append(", barack= ").Append(barack);
- return sb.ToString();
- }
- }
- class DieHardProbléma : AbsztraktÁllapot
- {
- int jug3G, jug5G;
- public DieHardProbléma()
- {
- jug3G = 0;
- jug5G = 0;
- }
- public override bool CélÁllapotE()
- {
- return jug5G == 4;
- }
- public override int OperátorokSzáma()
- {
- //teletöltöm a 3G-st
- //kiöntok mindent a 3G-ből
- //áttöltök 3G-ből 5G-be
- //teletöltöm a 5G-st
- //kiöntok mindent a 5G-ből
- //áttöltök 5G-ből
- //megoldás: 5G tele, át 3g-be, 3g ürít, 5g-ben maradt 2 át 3g-be, 5g tele, 1g fér át a 3-asba marad 4
- return 3;
- }
- public override bool SzuperOperátor(int i)
- {
- switch (i)
- {
- case 0: return tele5G();
- case 1: return urit3G();
- case 2: return át5ből3ba();
- default: return false;
- }
- }
- private bool tele5G()
- {
- //if (!preTele5G()) return false;
- if (jug5G == 5) return false;
- //állapotátmenet
- jug5G = 5;
- //if(!ÁllapotE()) return false;
- return true;
- }
- private bool urit3G()
- {
- if (jug3G == 0) return false;
- jug3G = 0;
- return true;
- }
- private bool át5ből3ba()
- {
- if (jug3G == 3 || jug5G == 0) return false;
- int hely3ban = 3 - jug3G;
- if (hely3ban >= jug5G) hely3ban = jug5G;
- jug5G -= hely3ban;
- jug3G += hely3ban;
- return true;
- }
- public override bool ÁllapotE()
- {
- return jug3G >= 0 && jug5G >= 0 &&
- jug3G <= 3 && jug5G <= 5;
- }
- public override string ToString()
- {
- //minden mezőt fel kell használni
- return "jug3G=" + jug3G + "jug5G=" + jug5G;
- }
- }
- //8.4.1
- /// <summary>
- /// A "3 szerzetes és 3 kannibál" probléma állapottér reprezentációja.
- /// Illetve általánosítása akárhány szerzetesre és kannibálra.
- /// Probléma: 3 szerzet és 3 kannibál van a folyó bal partján.
- /// Át kell juttatni az összes embert a másik partra.
- /// Ehhez rendelkezésre áll egy két személyes csónak.
- /// Egy ember is elég az átjutáshoz, de kettőnél több ember nem fér el.
- /// Ha valaki átmegy a másik oldalra, akkor ki is kell szállni, nem maradhat a csónakban.
- /// A gond ott van, hogy ha valamelyik parton több kannibál van,
- /// mint szerzetes, akkor a kannibálok megeszik a szerzeteseket.
- /// Kezdő állapot:
- /// 3 szerzetes a bal oldalon.
- /// 3 kannibál a bal oldalon.
- /// A csónak a bal parton van.
- /// 0 szerzetes a jobb oldalon.
- /// 0 kannibál a jobb oldalon.
- /// Ezt az állapotot ezzel a rendezett 5-össel írjuk le:
- /// (3,3,'B',0,0)
- /// A célállapot:
- /// (0,0,'J',3,3)
- /// Operátor:
- /// Op(int sz, int k):
- /// sz darab szerzetes átmegy a másik oldalra és
- /// k darab kannibál átmegy a másik oldalra.
- /// Lehetséges paraméterezése:
- /// Op(1,0): 1 szerzetes átmegy a másik oldalra.
- /// Op(2,0): 2 szerzetes átmegy a másik oldalra.
- /// Op(1,1): 1 szerzetes és 1 kannibál átmegy a másik oldalra.
- /// Op(0,1): 1 kannibál átmegy a másik oldalra.
- /// Op(0,2): 2 kanibál átmegy a másik oldalra.
- /// </summary>
- class SzerzetesekÉsKannibálokÁllapot : AbsztraktÁllapot
- {
- int sz; // ennyi szerzetes van összesen
- int k; // ennyi kannibál van összesen
- int szb; // szerzetesek száma a bal oldalon
- int kb; // kannibálok száma a bal oldalon
- char cs; // Hol a csónak? Értéke vagy 'B' vagy 'J'.
- int szj; // szerzetesek száma a jobb oldalon
- int kj; // kannibálok száma a jobb oldalon
- public SzerzetesekÉsKannibálokÁllapot(int sz, int k) // beállítja a kezdő állapotot
- {
- this.sz = sz;
- this.k = k;
- szb = sz;
- kb = k;
- cs = 'B';
- szj = 0;
- kj = 0;
- }
- public override bool ÁllapotE()
- { // igaz, ha a szerzetesek biztonságban vannak
- return ((szb >= kb) || (szb == 0)) &&
- ((szj >= kj) || (szj == 0));
- }
- public override bool CélÁllapotE()
- {
- // igaz, ha mindenki átért a jobb oldalra
- return szj == sz && kj == k;
- }
- private bool preOp(int sz, int k)
- {
- // A csónak 2 személyes, legalább egy ember kell az evezéshez.
- // Ezt végül is felesleges vizsgálni, mert a szuper operátor csak ennek megfelelően hívja.
- if (sz + k > 2 || sz + k < 0 || sz < 0 || k < 0) return false;
- // Csak akkor lehet átvinni sz szerzetest és
- // k kannibált, ha a csónak oldalán van is legalább ennyi.
- if (cs == 'B')
- return szb >= sz && kb >= k;
- else
- return szj >= sz && kj >= k;
- }
- // Átvisz a másik oldalra sz darab szerzetes és k darab kannibált.
- private bool op(int sz, int k)
- {
- if (!preOp(sz, k)) return false;
- SzerzetesekÉsKannibálokÁllapot mentes = (SzerzetesekÉsKannibálokÁllapot)Clone();
- if (cs == 'B')
- {
- szb -= sz;
- kb -= k;
- cs = 'J';
- szj += sz;
- kj += k;
- }
- else
- {
- szb += sz;
- kb += k;
- cs = 'B';
- szj -= sz;
- kj -= k;
- }
- if (ÁllapotE()) return true;
- szb = mentes.szb;
- kb = mentes.kb;
- cs = mentes.cs;
- szj = mentes.szj;
- kj = mentes.kj;
- return false;
- }
- public override int OperátorokSzáma() { return 5; }
- public override bool SzuperOperátor(int i)
- {
- switch (i)
- {
- case 0: return op(0, 1);
- case 1: return op(0, 2);
- case 2: return op(1, 1);
- case 3: return op(1, 0);
- case 4: return op(2, 0);
- default: return false;
- }
- }
- public override string ToString()
- {
- return szb + "," + kb + "," + cs + "," + szj + "," + kj;
- }
- public override bool Equals(Object a)
- {
- SzerzetesekÉsKannibálokÁllapot aa = (SzerzetesekÉsKannibálokÁllapot)a;
- // szj és kj számítható, ezért nem kell vizsgálni
- return aa.szb == szb && aa.kb == kb && aa.cs == cs;
- }
- // Ha két példány egyenlő, akkor a hasítókódjuk is egyenlő.
- public override int GetHashCode()
- {
- return szb.GetHashCode() + kb.GetHashCode() + cs.GetHashCode();
- }
- }
- //8.5.1
- /// <summary>
- /// A csúcs tartalmaz egy állapotot, a csúcs mélységét, és a csúcs szülőjét.
- /// Így egy csúcs egy egész utat reprezentál a start csúcsig.
- /// </summary>
- class Csúcs
- {
- // A csúcs tartalmaz egy állapotot, a mélységét és a szülőjét
- AbsztraktÁllapot állapot;
- int mélység;
- Csúcs szülő; // A szülőkön felfelé haladva a start csúcsig jutok.
- // Konstruktor:
- // A belső állapotot beállítja a start csúcsra.
- // A hívó felelőssége, hogy a kezdő állapottal hívja meg.
- // A start csúcs mélysége 0, szülője nincs.
- public Csúcs(AbsztraktÁllapot kezdőÁllapot)
- {
- állapot = kezdőÁllapot;
- mélység = 0;
- szülő = null;
- }
- // Egy új gyermek csúcsot készít.
- // Erre még meg kell hívni egy alkalmazható operátor is, csak azután lesz kész.
- public Csúcs(Csúcs szülő)
- {
- állapot = (AbsztraktÁllapot)szülő.állapot.Clone();
- mélység = szülő.mélység + 1;
- this.szülő = szülő;
- }
- public Csúcs GetSzülő() { return szülő; }
- public int GetMélység() { return mélység; }
- public bool TerminálisCsúcsE() { return állapot.CélÁllapotE(); }
- public int OperátorokSzáma() { return állapot.OperátorokSzáma(); }
- public bool SzuperOperátor(int i) { return állapot.SzuperOperátor(i); }
- public override bool Equals(Object obj)
- {
- Csúcs cs = (Csúcs)obj;
- return állapot.Equals(cs.állapot);
- }
- public override int GetHashCode() { return állapot.GetHashCode(); }
- public override String ToString() { return állapot.ToString(); }
- // Alkalmazza az összes alkalmazható operátort.
- // Visszaadja az így előálló új csúcsokat.
- public List<Csúcs> Kiterjesztes()
- {
- List<Csúcs> újCsúcsok = new List<Csúcs>();
- for (int i = 0; i < OperátorokSzáma(); i++)
- {
- // Új gyermek csúcsot készítek.
- Csúcs újCsúcs = new Csúcs(this);
- // Kiprobálom az i.dik alapoperátort. Alkalmazható?
- if (újCsúcs.SzuperOperátor(i))
- {
- // Ha igen, hozzáadom az újakhoz.
- újCsúcsok.Add(újCsúcs);
- }
- }
- return újCsúcsok;
- }
- }
- //8.6.1
- /// <summary>
- /// Minden gráfkereső algoritmus őse.
- /// A gráfkeresőknek csak a Keresés metódust kell megvalósítaniuk.
- /// Ez visszaad egy terminális csúcsot, ha talált megoldást, egyébként null értékkel tér vissza.
- /// A terminális csúcsból a szülő referenciákon felfelé haladva áll elő a megoldás.
- /// </summary>
- abstract class GráfKereső
- {
- private Csúcs startCsúcs; // A start csúcs csúcs.
- // Minden gráfkereső a start csúcsból kezd el keresni.
- public GráfKereső(Csúcs startCsúcs)
- {
- this.startCsúcs = startCsúcs;
- }
- // Jobb, ha a start csúcs privát, de a gyermek osztályok lekérhetik.
- protected Csúcs GetStartCsúcs() { return startCsúcs; }
- /// Ha van megoldás, azaz van olyan út az állapottér gráfban,
- /// ami a start csúcsból egy terminális csúcsba vezet,
- /// akkor visszaad egy megoldást, egyébként null.
- /// A megoldást egy terminális csúcsként adja vissza.
- /// Ezen csúcs szülő referenciáin felfelé haladva adódik a megoldás fordított sorrendben.
- public abstract Csúcs Keresés();
- /// <summary>
- /// Kiíratja a megoldást egy terminális csúcs alapján.
- /// Feltételezi, hogy a terminális csúcs szülő referenciáján felfelé haladva eljutunk a start csúcshoz.
- /// A csúcsok sorrendjét megfordítja, hogy helyesen tudja kiírni a megoldást.
- /// Ha a csúcs null, akkor kiírja, hogy nincs megoldás.
- /// </summary>
- /// <param name="egyTerminálisCsúcs">
- /// A megoldást képviselő terminális csúcs vagy null.
- /// </param>
- public void megoldásKiírása(Csúcs egyTerminálisCsúcs)
- {
- if (egyTerminálisCsúcs == null)
- {
- Console.WriteLine("Nincs megoldás");
- return;
- }
- // Meg kell fordítani a csúcsok sorrendjét.
- Stack<Csúcs> megoldás = new Stack<Csúcs>();
- Csúcs aktCsúcs = egyTerminálisCsúcs;
- while (aktCsúcs != null)
- {
- megoldás.Push(aktCsúcs);
- aktCsúcs = aktCsúcs.GetSzülő();
- }
- // Megfordítottuk, lehet kiírni.
- foreach (Csúcs akt in megoldás) Console.WriteLine(akt);
- }
- }
- //8.7.1
- /// <summary>
- /// A backtrack gráfkereső algoritmust megvalósító osztály.
- /// A három alap backtrack algoritmust egyben tartalmazza. Ezek
- /// - az alap backtrack
- /// - mélységi korlátos backtrack
- /// - emlékezetes backtrack
- /// Az ág-korlátos backtrack nincs megvalósítva.
- /// </summary>
- class BackTrack : GráfKereső
- {
- int korlát; // Ha nem nulla, akkor mélységi korlátos kereső.
- bool emlékezetes; // Ha igaz, emlékezetes kereső.
- public BackTrack(Csúcs startCsúcs, int korlát, bool emlékezetes) : base(startCsúcs)
- {
- this.korlát = korlát;
- this.emlékezetes = emlékezetes;
- }
- // nincs mélységi korlát, se emlékezet
- public BackTrack(Csúcs startCsúcs) : this(startCsúcs, 0, false) { }
- // mélységi korlátos kereső
- public BackTrack(Csúcs startCsúcs, int korlát) : this(startCsúcs, korlát, false) { }
- // emlékezetes kereső
- public BackTrack(Csúcs startCsúcs, bool emlékezetes) : this(startCsúcs, 0, emlékezetes) { }
- // A keresés a start csúcsból indul.
- // Egy terminális csúcsot ad vissza. A start csúcsból el lehet jutni ebbe a terminális csúcsba.
- // Ha nincs ilyen, akkor null értéket ad vissza.
- public override Csúcs Keresés() { return Keresés(GetStartCsúcs()); }
- // A kereső algoritmus rekurzív megvalósítása.
- // Mivel rekurzív, ezért a visszalépésnek a "return null" felel meg.
- private Csúcs Keresés(Csúcs aktCsúcs)
- {
- int mélység = aktCsúcs.GetMélység();
- // mélységi korlát vizsgálata
- if (korlát > 0 && mélység >= korlát) return null;
- // emlékezet használata kör kiszűréséhez
- Csúcs aktSzülő = null;
- if (emlékezetes) aktSzülő = aktCsúcs.GetSzülő();
- while (aktSzülő != null)
- {
- // Ellenőrzöm, hogy jártam-e ebben az állapotban. Ha igen, akkor visszalépés.
- if (aktCsúcs.Equals(aktSzülő)) return null;
- // Visszafelé haladás a szülői láncon.
- aktSzülő = aktSzülő.GetSzülő();
- }
- if (aktCsúcs.TerminálisCsúcsE())
- {
- // Megvan a megoldás, vissza kell adni a terminális csúcsot.
- return aktCsúcs;
- }
- // Itt hívogatom az alapoperátorokat a szuper operátoron
- // keresztül. Ha valamelyik alkalmazható, akkor új csúcsot
- // készítek, és meghívom önmagamat rekurzívan.
- for (int i = 0; i < aktCsúcs.OperátorokSzáma(); i++)
- {
- // Elkészítem az új gyermek csúcsot.
- // Ez csak akkor lesz kész, ha alkalmazok rá egy alkalmazható operátort is.
- Csúcs újCsúcs = new Csúcs(aktCsúcs);
- // Kipróbálom az i.dik alapoperátort. Alkalmazható?
- if (újCsúcs.SzuperOperátor(i))
- {
- // Ha igen, rekurzívan meghívni önmagam az új csúcsra.
- // Ha nem null értéket ad vissza, akkor megvan a megoldás.
- // Ha null értéket, akkor ki kell próbálni a következő alapoperátort.
- Csúcs terminális = Keresés(újCsúcs);
- if (terminális != null)
- {
- // Visszaadom a megoldást képviselő terminális csúcsot.
- return terminális;
- }
- // Az else ágon kellene visszavonni az operátort.
- // Erre akkor van szükség, ha az új gyermeket létrehozásában nem lenne klónozást.
- // Mivel klónoztam, ezért ez a rész üres.
- }
- }
- // Ha kipróbáltam az összes operátort és egyik se vezetett megoldásra, akkor visszalépés.
- // A visszalépés hatására eggyel feljebb a következő alapoperátor kerül sorra.
- return null;
- }
- }
- //8.9.1
- class Program
- {
- static void Main(string[] args)
- {
- Csúcs startCsúcs;
- GráfKereső kereső;
- Console.WriteLine("A 3 szerzetes 3 kanibál problémát oldjuk meg.");
- startCsúcs = new Csúcs(new SzerzetesekÉsKannibálokÁllapot(3, 3));
- Console.WriteLine("A kereső egy 15 mélységi korlátos és emlékezetes backtrack.");
- kereső = new BackTrack(startCsúcs, 15, true);
- kereső.megoldásKiírása(kereső.Keresés());
- Console.WriteLine("A Die Hard problémát oldjuk meg.");
- startCsúcs = new Csúcs(new DieHardProbléma());
- Console.WriteLine("A kereső egy 15 mélységi korlátos és emlékezetes backtrack.");
- kereső = new BackTrack(startCsúcs, 15, true);
- kereső.megoldásKiírása(kereső.Keresés());
- Console.WriteLine("A gyümölcsös problémát oldjuk meg.");
- startCsúcs = new Csúcs(new Feladat2p5());
- Console.WriteLine("A kereső egy 15 mélységi korlátos és emlékezetes backtrack.");
- kereső = new BackTrack(startCsúcs, 15, true);
- kereső.megoldásKiírása(kereső.Keresés());
- Console.WriteLine("A forgatós problémát oldjuk meg.");
- startCsúcs = new Csúcs(new Feladat2p8());
- Console.WriteLine("A kereső egy 15 mélységi korlátos és emlékezetes backtrack.");
- kereső = new BackTrack(startCsúcs, 15, true);
- kereső.megoldásKiírása(kereső.Keresés());
- Console.WriteLine("A Feladat 1.3 problémát oldjuk meg.");
- startCsúcs = new Csúcs(new Feladat_1_3());
- Console.WriteLine("A kereső egy 15 mélységi korlátos és emlékezetes backtrack.");
- kereső = new BackTrack(startCsúcs, 15, true);
- kereső.megoldásKiírása(kereső.Keresés());
- Console.WriteLine("A Feladat 2.38 problémát oldjuk meg.");
- startCsúcs = new Csúcs(new Feladat_2_38());
- Console.WriteLine("A kereső egy 25 mélységi korlátos és emlékezetes backtrack.");
- kereső = new BackTrack(startCsúcs, 30, true);
- kereső.megoldásKiírása(kereső.Keresés());
- Console.ReadLine();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment