Advertisement
mixster

mixster

Oct 24th, 2009
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 10.35 KB | None | 0 0
  1. // nielsie's maze solver
  2. // pasted by mixster for the Leage of Scripters competition on Villavu
  3. const
  4.   xGridLo = 0;
  5.   xGridHi = 25;
  6.   yGridLo = 0;
  7.   yGridHi = 12;
  8.  
  9.  
  10.   sMap =
  11.     '00000000000000000000000002' +
  12.     '03011111011111100010001102' +
  13.     '01010101010000111111101002' +
  14.     '01111101010110101000101002' +
  15.     '01000111010100101110111112' +
  16.     '01010100010110100000100012' +
  17.     '01110111010011101100101012' +
  18.     '00101101010110001011101012' +
  19.     '01111001010100101010011012' +
  20.     '01001011110111111110010012' +
  21.     '01111010010000000111110012' +
  22.     '00100111111111111000000042' +
  23.     '0000000000000000000000000';
  24.  
  25. type
  26.   TGrid = array[xGridLo..xGridHi] of array[yGridLo..yGridHi] of Boolean;
  27.   TPossibles = array[xGridLo..xGridHi] of array[yGridLo..yGridHi] of record
  28.     Count: Byte;
  29.     L, R, U, D: Boolean;
  30.   end;
  31.  
  32.   TMap = record
  33.     Grid: TGrid;
  34.     Possibles: TPossibles;
  35.     sp, ep: TPoint;
  36.   end;
  37.  
  38.   TNode = record
  39.     Path, Possibles: TPointArray;
  40.     PosLen: Integer;
  41.     Grid: TGrid;
  42.   end;
  43.   TNodeArray = array of TNode;
  44.  
  45.   function QueryPerformanceFrequency(out Frequency: Int64): LongBool; external '[email protected] stdcall';
  46.   function QueryPerformanceCounter(out Counter: Int64): LongBool; external '[email protected] stdcall';
  47.  
  48. procedure MarkTime(var Time: Int64);
  49. var
  50.   Freq: Int64;
  51. begin
  52.   if QueryPerformanceFrequency(Freq) then
  53.     QueryPerformanceCounter(Time)
  54.   else
  55.     Time := GetTickCount;
  56. end;
  57.  
  58. function TimeFromMark(Mark: Int64): Double;
  59. var
  60.   Freq, Now: Int64;
  61. begin
  62.   if QueryPerformanceFrequency(Freq) then
  63.   begin
  64.     QueryPerformanceCounter(Now);
  65.     Result := ((Now - Mark) / Freq) * 1000;
  66.   end
  67.   else
  68.     Result := (GetTickCount - Mark);
  69. end;
  70.  
  71. function GetPossiblesForPoint(s: TPoint; var Grid: TGrid; Possibles: TPossibles): TPointArray;
  72. var
  73.   Len: Integer;
  74. begin
  75.   with Possibles[s.x][s.y] do
  76.   begin
  77.     SetLength(Result, Count);
  78.     if (Count < 1) then
  79.       Exit;
  80.     Len := 0;
  81.  
  82.     if U then
  83.       if Grid[s.x][s.y - 1] then
  84.       begin
  85.         Grid[s.x][s.y - 1] := False;
  86.         Result[Len] := Point(s.x, s.y - 1);
  87.         Inc(Len);
  88.       end;
  89.     if D then
  90.       if Grid[s.x][s.y + 1] then
  91.       begin
  92.         Grid[s.x][s.y + 1] := False;
  93.         Result[Len] := Point(s.x, s.y + 1);
  94.         Inc(Len);
  95.       end;
  96.     if L then
  97.       if Grid[s.x - 1][s.y] then
  98.       begin
  99.         Grid[s.x - 1][s.y] := False;
  100.         Result[Len] := Point(s.x - 1, s.y);
  101.         Inc(Len);
  102.       end;
  103.     if R then
  104.       if Grid[s.x + 1][s.y] then
  105.       begin
  106.         Grid[s.x + 1][s.y] := False;
  107.         Result[Len] := Point(s.x + 1, s.y);
  108.         Inc(Len);
  109.       end;
  110.     if (Len <> Count) then
  111.       SetLength(Result, Len);
  112.   end;
  113. end;
  114.  
  115. function Node(const aPath, aPossibles: TPointArray; const aGrid: TGrid): TNode;
  116. begin
  117.   with Result do
  118.   begin
  119.     Path := aPath;
  120.     Possibles := aPossibles;
  121.     PosLen := Length(aPossibles);
  122.     Grid := aGrid;
  123.   end;
  124. end;
  125.  
  126. procedure AddNodeToArray(var a: TNodeArray; n: TNode);
  127. begin
  128.   SetLength(a, Length(a) + 1);
  129.   a[High(a)] := n;
  130. end;
  131.  
  132. procedure AddPointToArrayProc(var a: TPointArray; p: TPoint);
  133. begin
  134.   SetLength(a, Length(a) + 1);
  135.   a[High(a)] := p;
  136. end;
  137.  
  138. function AddPointToArrayFunc(const a: TPointArray; p: TPoint): TPointArray;
  139. begin
  140.   Result := a;
  141.   SetLength(Result, Length(Result) + 1);
  142.   Result[High(Result)] := p;
  143.   //AddPointToArrayProc(Result, p);
  144. end;
  145.  
  146. function GetPaths(const Map: TMap): T2DPointArray;
  147. var
  148.   tp: TPoint;
  149.   p: TPointArray;
  150.   i, c, t: Integer;
  151.   Nodes: TNodeArray;
  152. begin
  153.   SetLength(Result, 0);
  154.  
  155.   p := GetPossiblesForPoint(Map.sp, Map.Grid, Map.Possibles);
  156.   AddNodeToArray(Nodes, Node([Map.sp], p, Map.Grid));
  157.  
  158.   c := 0;
  159.   while (c < Length(Nodes)) do
  160.   begin
  161.   //repeat
  162.     for i := 0 to Nodes[c].PosLen - 1 do
  163.       with Nodes[c] do
  164.       begin
  165.         if (Possibles[i].y = Map.ep.y) and
  166.            (Possibles[i].x = Map.ep.x) then
  167.         begin
  168.           SetLength(Result, Length(Result) + 1);
  169.           Result[High(Result)] := AddPointToArrayFunc(Path, Possibles[i]);
  170.           Break;
  171.         end;
  172.  
  173.         p := GetPossiblesForPoint(Possibles[i], Grid, Map.Possibles);
  174.         t := Length(p);
  175.         if (t = 1) and (PosLen = 1) then
  176.         begin
  177.           AddPointToArrayProc(Path, Possibles[i]);
  178.  
  179.           repeat
  180.             tp := p[0];
  181.             if (tp.y = Map.ep.y) and (tp.x = Map.ep.x) then
  182.             begin
  183.               SetLength(Result, Length(Result) + 1);
  184.               Result[High(Result)] := AddPointToArrayFunc(Path, tp);
  185.               t := -123;
  186.               Break;
  187.             end;
  188.             p := GetPossiblesForPoint(tp, Grid, Map.Possibles);
  189.             t := Length(p);
  190.             if (t = 1) then
  191.               AddPointToArrayProc(Path, tp);
  192.           until (t <> 1);
  193.  
  194.           if (t = -123) then
  195.             Continue;
  196.         end
  197.         else
  198.           tp := Possibles[i];
  199.  
  200.         if (t > 0) then
  201.           AddNodeToArray(Nodes, Node(AddPointToArrayFunc(Path, tp), p, Grid))
  202.         {else if (Map.Possibles[tp.x][tp.y].Count > 0) then
  203.         begin
  204.           Map.Possibles[tp.x][tp.y].Count := 0;
  205.           with Map do
  206.             for t := High(Path) downto 0 do
  207.               if (Possibles[Path[t].x][Path[t].y].Count <= 2) then
  208.                 Possibles[Path[t].x][Path[t].y].Count := 0
  209.               else
  210.                 Break;
  211.         end};
  212.       end;
  213.     {t := Length(Nodes) - 1;
  214.     for i := 0 to t - 1 do
  215.       Nodes[i] := Nodes[i + 1];
  216.     SetLength(Nodes, t);}
  217.     Inc(c);
  218.   //until (t < 1);
  219.   end;
  220. end;
  221.  
  222. procedure LoadStringMap(sMap: string; var Grid: TGrid; out sp, ep: TPoint);
  223. var
  224.   x, y, t: Integer;
  225. begin
  226.   x := -1;
  227.   y := 0;
  228.   t := 1;
  229.  
  230.   for t := 1 to Length(sMap) do
  231.   begin
  232.     case sMap[t] of
  233.       '0', '1', '3', '4':
  234.         begin
  235.           Inc(x);
  236.           if (sMap[t] = '0') then
  237.             Grid[x][y] := False
  238.           else
  239.           begin
  240.             Grid[x][y] := True;
  241.             case sMap[t] of
  242.               '3': sp := Point(x, y);
  243.               '4': ep := Point(x, y);
  244.             end;
  245.           end;
  246.         end;
  247.       '2':
  248.         begin
  249.           Inc(y);
  250.           x := -1;
  251.         end;
  252.     end;
  253.   end;
  254. end;
  255.  
  256. procedure PrepareMap(var Map: TMap);
  257. var
  258.   x, y: Integer;
  259. begin
  260.   for x := xGridLo to xGridHi do
  261.     for y := yGridLo to yGridHi do
  262.       with Map, Map.Possibles[x][y] do
  263.       begin
  264.         if (y > yGridLo) then
  265.           if Grid[x][y - 1] then
  266.           begin
  267.             U := True;
  268.             Inc(Count);
  269.           end;
  270.         if (y < yGridHi) then
  271.           if Grid[x][y + 1] then
  272.           begin
  273.             D := True;
  274.             Inc(Count);
  275.           end;
  276.         if (x > xGridLo) then
  277.           if Grid[x - 1][y] then
  278.           begin
  279.             L := True;
  280.             Inc(Count);
  281.           end;
  282.         if (x < xGridHi) then
  283.           if Grid[x + 1][y] then
  284.           begin
  285.             R := True;
  286.             Inc(Count);
  287.           end;
  288.       end;
  289. end;
  290.  
  291. function CreateMapFromBoolArray(BoolMap: array of array of Boolean; s, e: TPoint): TMap;
  292. var
  293.   x, y: Integer;
  294. begin
  295.   if (Length(BoolMap) <> (yGridHi - yGridLo + 1)) or (Length(BoolMap[0]) <> (xGridHi - xGridLo + 1)) then
  296.   begin
  297.     WriteLn('Oops! Range error in BoolMap!');
  298.     Exit;
  299.   end;
  300.  
  301.   with Result do
  302.   begin
  303.     sp := s;
  304.     ep := e;
  305.  
  306.     for x := xGridHi - xGridLo downto 0 do
  307.       for y := yGridHi - yGridLo downto 0 do
  308.         Grid[x + xGridLo][y + yGridLo] := Boolmap[y][x];
  309.   end;
  310.  
  311.   PrepareMap(Result);
  312. end;
  313.  
  314. function CreateMapFromString(sMap: string): TMap;
  315. begin
  316.   LoadStringMap(sMap, Result.Grid, Result.sp, Result.ep);
  317.   PrepareMap(Result);
  318. end;
  319.  
  320. procedure JackJill(out Jacks_Path: TPointArray; out Jills_RouteCount: Integer; Input: array of array of Boolean; Start, Finish: TPoint);
  321. var
  322.   Map: TMap;
  323.   p: T2DPointArray;
  324.   i, mi, ml: Integer;
  325. begin
  326.   Map := CreateMapFromBoolArray(Input, Start, Finish);
  327.   p := GetPaths(Map);
  328.  
  329.   ml := -1;
  330.   mi := -1;
  331.   Jills_RouteCount := Length(p) - 1;
  332.   for i := 0 to Jills_RouteCount do
  333.     if (Length(p[i]) > ml) then
  334.       mi := i;
  335.      
  336.   if (mi > -1) then
  337.     Jacks_Path := p[mi];
  338. end;
  339.  
  340. {$IFNDEF SCAR320_UP}
  341. type
  342.   TBooleanArray = array of Boolean;
  343. {$ENDIF}
  344. var
  345.   bmp: Integer;
  346.   Canvas: TCanvas;
  347. var
  348.   Map: TMap;
  349.   x, y, w, h: Integer;
  350.   p: T2DPointArray;
  351.   pt: TPoint;
  352. var
  353.   t: Int64;
  354. begin
  355.   w := ((xGridHi - xGridLo) + 1) * 12;
  356.   h := ((yGridHi - yGridLo) + 1) * 12;
  357.   bmp := BitmapFromString(w, h, '');
  358.   Canvas := GetBitmapCanvas(bmp);
  359.   FastDrawClear(bmp, clLightSteelBlue);
  360.   DisplayDebugImgWindow(w, h);
  361.  
  362.   Map := CreateMapFromString(sMap);
  363.   {Map := CreateMapFromBoolArray
  364.     (
  365.       [
  366.         TBooleanArray([False, False, False, False, False]),
  367.         TBooleanArray([False, True,  False, True,  False]),
  368.         TBooleanArray([False, True,  True,  True,  False]),
  369.         TBooleanArray([False, False, False, False, False])
  370.       ],
  371.       Point(1, 1),
  372.       Point(3, 1)
  373.     );}
  374.  
  375.   MarkTime(t);
  376.   p := GetPaths(Map);
  377.   WriteLn('Time: '+FloatToStr(TimeFromMark(t))+'ms - '+IntToStr(Length(p)));
  378.  
  379.   Canvas.Brush.Color := clBlack;
  380.   Canvas.Pen.Color := clBlack;
  381.   for x := xGridLo to xGridHi do
  382.     for y := yGridLo to yGridHi do
  383.       if (not Map.Grid[x][y]) then
  384.       begin
  385.         pt := Point(x * 12, y * 12);
  386.         Canvas.Rectangle(pt.x, pt.y, pt.x + 12, pt.y + 12);
  387.       end;
  388.  
  389.   t := Length(p);
  390.   for y := t - 1 downto 0 do
  391.   begin
  392.     case y mod 5 of
  393.       3: Canvas.Brush.Color := RGBtoColor(85 * (y mod 3), 255 - ((255 / t) * y), ((255 / t) * y));
  394.       0: Canvas.Brush.Color := RGBtoColor(255 - ((255 / t) * y), 85 * (y mod 3), ((255 / t) * y));
  395.       4: Canvas.Brush.Color := RGBtoColor(255 - ((255 / t) * y), ((255 / t) * y), 85 * (y mod 3));
  396.       2: Canvas.Brush.Color := RGBtoColor(((255 / t) * y), 255 - ((255 / t) * y), 85 * (y mod 3));
  397.       1: Canvas.Brush.Color := RGBtoColor(((255 / t) * y), 85 * (y mod 3), 255 - ((255 / t) * y));
  398.     end;
  399.     Canvas.Pen.Color := Canvas.Brush.Color;
  400.     for x := 0 to High(p[y]) do
  401.     begin
  402.       pt := Point(p[y][x].x * 12, p[y][x].y * 12);
  403.       Canvas.Rectangle(pt.x, pt.y, pt.x + 12, pt.y + 12);
  404.     end;
  405.     SafeDrawBitmap(bmp, GetDebugCanvas, 0, 0);
  406.     Wait(2500);
  407.   end;
  408.  
  409.   SafeDrawBitmap(bmp, GetDebugCanvas, 0, 0);
  410.   FreeBitmap(bmp);
  411. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement