Matematické Fórum

Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.

Nástěnka
22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.

Nejste přihlášen(a). Přihlásit

#1 03. 03. 2012 11:43

Mirgeee
Příspěvky: 129
Reputace:   
 

Pruchod sachovnice konem

Zdravim,
pomohl by mi někdo prosim najit chybu v kratkem programu, ktery by mel najit cestu kone celym sachovym polem? Program hazi chybu 216 (genreal protection fault)...

Code:

program PruchodSachovniceZasobnik;
{
    * Zpusob realizace: zasobnik.
    * Z kazde pozice v zasobniku se pokusime jit vsemi smery. Pokud
    * budeme uvnitř šachovnice a pokud pole, na ktere se hodlame premistit
    * drzi cislo -1 nebo cislo vetsi nez cislo soucasne, zaznamename na toto
    * misto cislo kroku (ulozene v zaznamu zasobniku). Pokud se cislo kroku
    * bude rovnat 63, nalezeno:=true, jinak neudelame nic a pokracujeme
    * ve smycce. 
}
type
    Index = 1..8;
    ZasUk = ^Zasobnik;
    Zasobnik = record
        s1 : Index;
        s2 : Index;
        krok : integer;
        dalsi : ZasUk;
    end;
var
    Nalezeno : boolean;
    Zasob : ZasUk;
    U : ZasUk;
    Start1,Start2 : index;
    Tah : array[index] of record d1,d2 : integer; end;
    S : array[index,index] of integer;
    i1,i2 : index;
    i,j : integer;

{Vlozi do zasobniku zaznam s informaci o souradnici a cislem kroku}    
procedure vloz(s1,s2 : index; krok : integer);
var Pom : ZasUk;
begin
    new(Pom);
    Pom^.s1 := s1;
    Pom^.s2 := s2;
    Pom^.krok := krok;
    Pom^.dalsi := Zasob;
    Zasob := Pom;
end;

{Navratovou hodnotou je prvni naboj v zasobniku}
function ven : ZasUk;
var Pom : ZasUk;
begin
    new(Pom);
    Pom := Zasob;
    Zasob := Zasob^.Dalsi;
    Ven := Pom;
    dispose(Pom);
end;

begin    
Tah[1].d1 := 1; Tah[1].d2 := 2;
Tah[2].d1 := 2; Tah[2].d2 := 1;
Tah[3].d1 := 2; Tah[3].d2 := -1;
Tah[4].d1 := 1; Tah[4].d2 := -2;
Tah[5].d1 := -1; Tah[5].d2 := -2;
Tah[6].d1 := -2; Tah[6].d2 := -1;
Tah[7].d1 := -2; Tah[7].d2 := 1;
Tah[8].d1 := -1; Tah[8].d2 := 2;

write('Pocatecni pozice kone: ');
readln(Start1, Start2);
for i:=1 to 8 do
        for j:=1 to 8 do S[i,j] := -1;
S[Start1,Start2] := 0;

Nalezeno := false;

new(Zasob);    
vloz(Start1,Start2,0);

while Nalezeno = false do
    U := Ven;                                                        {Nabijeme}
    writeln('1');
    begin
    for i:=1 to 8 do                                                 {Zkusíme jít ze všech směrů ze současné souřadnice}
        begin
        writeln('2');
        i1 := U^.s1 + Tah[i].d1;
        i2 := U^.s2 + Tah[i].d2;
        if (i1>=1) and (i1<=8) and (i2>=1) and (i2<=8) then            {Pokud lezi na sachovnici}
            begin
            writeln('3');
            if (S[i1,i2]=-1) or (S[i1,i2]>Zasob^.Krok) then            {Pokud jsme tam jeste nebyli nebo byli pri neuspesnem pruchodu}
                begin
                writeln('4');
                S[i1,i2] := U^.Krok+1;                                {Ulozime na misto cislo kroku o jeden vyssi}
                Vloz(i1,i2,U^.Krok+1);                                {Vlozime toto misto do zasobniku}
                end
            else if U^.Krok=63 then                                    {Jinak se neni kam hnout a pokud pocet kroku je 63}
                Nalezeno := true;                                    {Reseni Nalezeno}
                writeln('5');
            end;
        end;
    end;

if Nalezeno=true then
    for i:=1 to 8 do
        begin
        for j:=1 to 8 do
            writeln(S[i,j]:4);
        writeln;
        end
else
    writeln('Cesta neexistuje');
writeln;
end.

Offline

 

#2 04. 03. 2012 15:57 — Editoval RePRO (04. 03. 2012 15:57)

RePRO
Místo: Jihlava
Příspěvky: 363
Škola: AI VŠPJ (09-12, Bc.)
Pozice: programátor
Reputace:   11 
Web
 

Re: Pruchod sachovnice konem

Zdravím,
lépe, než takto nepomůžu.


Srdcem trochu-programátor, duší rádoby-matematik a povoláním analytik-vývojář.

Offline

 

#3 05. 03. 2012 21:53 — Editoval Mirgeee (06. 03. 2012 18:14)

Mirgeee
Příspěvky: 129
Reputace:   
 

Re: Pruchod sachovnice konem

↑ RePRO:
Prosím, pomoc, jsem zoufalej... Chápu, že se nechceš nimrat v tom kódu, tak si aspoň poslechni tu logiku, podle který by měl pracovat, protože v ní nejspíš bude chyba...
Nesmím použít rekurzi, tak používám zásobník, do kterýho ukládám souřadnice tahu a jeho pořadí. Na každém políčku šachovnice se pokusím jít všemi tahy koně a pokud políčko, na které se snažím jít leží na šachovnici a ještě jsem ho nenavšítivil nebo má na sobě uloženo číslo kroku větší než moje aktuální číslo kroku (tedy jsem na něm byl při neúspěšném průchodu), zapíšu na políčko nové číslo kroku a do zásobníku uložím souřadnice tohoto políčka a krok+1. Pokud jsem vyzkoušel všech osm tahů bez úspěchu (není se kam hnout), tak jsem nalezl řešení a můžu jít slavit, jinak opět čtu ze zásobníku a tak pořád dokola (jedná se o průchod do hloubky).
Když vypadá takhle, dostávám infinite loop... Ale klidně to přepracuju tak, abych dostával segmantation fault! :)

Code:

program PruchodSachovniceZasobnik;
{
    * Zpusob realizace: zasobnik.
    * Z kazde pozice v zasobniku se pokusime jit vsemi smery. Pokud
    * budeme uvnitř šachovnice a pokud pole, na ktere se hodlame premistit
    * drzi cislo -1 nebo cislo stejne vetsi nez cislo soucasne, zaznamename na toto
    * misto cislo kroku (ulozene v zaznamu zasobniku). Pokud se cislo kroku
    * bude rovnat 63, nalezeno:=true, jinak neudelame nic a pokracujeme
    * ve smycce. 
}
type
    Index = 1..8;
    ZasUk = ^Zasobnik;
    Zasobnik = record
        s1 : Index;
        s2 : Index;
        krok : integer;
        dalsi : ZasUk;
    end;
var
    Nalezeno : boolean;
    Zasob : ZasUk;
    U : ZasUk;
    Start1,Start2 : index;
    Tah : array[index] of record d1,d2 : integer; end;
    S : array[index,index] of integer;
    i1,i2 : index;
    i,j : integer;

{Vlozi do zasobniku zaznam s informaci o souradnici a cislem kroku}    
procedure vloz(s1,s2 : index; krok : integer);
var Pom : ZasUk;
begin
    new(Pom);
    Pom^.s1 := s1;
    Pom^.s2 := s2;
    Pom^.krok := krok;
    Pom^.dalsi := Zasob;
    Zasob := Pom;
end;

{Navratovou hodnotou je prvni naboj v zasobniku}
function ven : ZasUk;
var Pom : ZasUk;
begin
    Pom := Zasob;
    Zasob := Zasob^.Dalsi;
    Ven := Pom;
end;

begin    
Tah[1].d1 := 1; Tah[1].d2 := 2;
Tah[2].d1 := 2; Tah[2].d2 := 1;
Tah[3].d1 := 2; Tah[3].d2 := -1;
Tah[4].d1 := 1; Tah[4].d2 := -2;
Tah[5].d1 := -1; Tah[5].d2 := -2;
Tah[6].d1 := -2; Tah[6].d2 := -1;
Tah[7].d1 := -2; Tah[7].d2 := 1;
Tah[8].d1 := -1; Tah[8].d2 := 2;

write('Pocatecni pozice kone: ');
readln(Start1, Start2);
for i:=1 to 8 do
        for j:=1 to 8 do S[i,j] := -1;
S[Start1,Start2] := 0;

Nalezeno := false;

new(Zasob);
vloz(Start1,Start2,0);

while (Nalezeno=false) do
    begin
    j:=0;
    U := Ven;                                                        {Nabijeme}
    for i:=1 to 8 do                                                 {Zkusíme jít do všech směrů ze současné souřadnice}
        begin
        i1 := U^.s1 + Tah[i].d1;
        i2 := U^.s2 + Tah[i].d2;
        if (i1>=1) and (i1<=8) and (i2>=1) and (i2<=8)
        and ((S[i1,i2]=-1) or (S[i1,i2]>=U^.Krok)) then                {Pokud lezi na sachovnici a už jsme tam byli nebo nenavštíveno}
            begin
                S[i1,i2] := U^.Krok+1;                                {Ulozime na misto cislo kroku o jeden vyssi}
                Vloz(i1,i2,(S[i1,i2]));                                {Vlozime toto misto do zasobniku}
            end
        else j:=j+1;
        end;
    if (j=8) and (U^.Krok=63) then Nalezeno:=true;                    {Neni se kam hnout a krok je 63 - nalezeno}
    writeln(U^.Krok);
    end;
if Nalezeno=true then
    for i:=1 to 8 do
        begin
        for j:=1 to 8 do
            write(S[i,j]:4);
        writeln;
        end
else
    writeln('Cesta neexistuje');
writeln;
end.

Offline

 

#4 06. 03. 2012 18:01

Mirgeee
Příspěvky: 129
Reputace:   
 

Re: Pruchod sachovnice konem

Zvláštní, pro číslo kroku menší než 19 program pracuje normálně... Pro víc hází segmentation fault. Asi dochází ke stack overflow, tedy bych měl podle http://www.cprogramming.com/debugging/segfaults.html mít někde špatně ošetřenej base case. Ale kde? Vidí to někdo? Kdokoli?? Prosím...

Offline

 

#5 07. 03. 2012 13:01

zpsi
Příspěvky: 38
Reputace:   
 

Re: Pruchod sachovnice konem

↑ Mirgeee:
Nevím jestli je to jediná chyba, ale v proceduře ven si neuklízíš (na konec přidat dispose(Pom);)

Offline

 

#6 07. 03. 2012 19:00

Mirgeee
Příspěvky: 129
Reputace:   
 

Re: Pruchod sachovnice konem

↑ zpsi:
Díky za odpověď! Bohužel pokud tam to dispose přidám, tak program nefunguje vůbec.

Offline

 

#7 09. 03. 2012 19:44

Mirgeee
Příspěvky: 129
Reputace:   
 

Re: Pruchod sachovnice konem

Kdyby to někoho zajímalo: podle materiálů, které jsem shromáždil, tato úloha je bez nečekně složité heuristiky neřešitelná. Zadat ji tedy jako cvičení na DFS byla trochu rána pod pás :)
http://lionel.textmalaysia.com/knights- … 1pO3E9j25k
http://www.slideshare.net/kelumkps/knights-tour
http://delphiforfun.org/programs/knights_tour.htm
http://en.wikipedia.org/wiki/Knight%27s_tour

Offline

 

#8 09. 03. 2012 20:17

zpsi
Příspěvky: 38
Reputace:   
 

Re: Pruchod sachovnice konem

↑ Mirgeee:
Ta  úloha je samozřejmě řešitelná.  Jediný problém je, že bez jednoduché heuristiky může výpočet pro
šachovnici 8x8 trvat už docela dlouho (záleží na počáteční pozici koně).  Pro šachovnici 6x6 vypadne výsledek ihned i bez heuristiky pro libovolnou počáteční polohu koně.

Offline

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson