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
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)...
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
↑ 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! :)
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
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
↑ Mirgeee:
Nevím jestli je to jediná chyba, ale v proceduře ven si neuklízíš (na konec přidat dispose(Pom);)
Offline
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
↑ 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