Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
13
Task/Maze-solving/Icon/maze-solving-1.icon
Normal file
13
Task/Maze-solving/Icon/maze-solving-1.icon
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
procedure main(A)
|
||||
/mh := \A[1] | 12
|
||||
/mw := \A[2] | 16
|
||||
mz := DisplayMaze(GenerateMaze(mh,mw))
|
||||
WriteImage(mz.filename) # save file
|
||||
WAttrib(mz.window,"canvas=normal") # show it
|
||||
until Event() == &lpress # wait for left mouse press
|
||||
Solver(mz.maze)
|
||||
DisplayMazeSolution(mz)
|
||||
WriteImage(mz.filename ?:= (="maze-", "maze-solved-" || tab(0)))
|
||||
until Event() == &lpress # wait
|
||||
close(mz.window)
|
||||
end
|
||||
37
Task/Maze-solving/Icon/maze-solving-2.icon
Normal file
37
Task/Maze-solving/Icon/maze-solving-2.icon
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
procedure Solver(r,c)
|
||||
static maze,h,w,rd
|
||||
|
||||
if type(r) == "list" then { # ------------------- Top Level (r == maze)
|
||||
h := *(maze := r) # height
|
||||
w := *maze[1] # width
|
||||
every r := 1 to h & c := 1 to w do # remove breadcrumbs
|
||||
maze[r,c] := iand(maze[r,c],NORTH+EAST+SOUTH+WEST+START+FINISH)
|
||||
every ((r := 1 | h) & (c := 1 to w)) | # search perimiter
|
||||
((r := 1 to h) & (c := 1 | w)) do
|
||||
if iand(maze[r,c],START) > 0 then break # until start found
|
||||
Solver(r,c) # recurse through maze
|
||||
return 1(.maze,maze := &null) # return maze and reset
|
||||
}
|
||||
else # ------------------- Recurse way through maze
|
||||
if iand(x := maze[r,c],SEEN) = 0 then { # in bounds and not seen?
|
||||
(iand(x,FINISH) > 0, maze[r,c] +:= PATH, return ) # at finish? - done!
|
||||
maze[r,c] +:= SEEN # drop bread crumb
|
||||
(iand(x,NORTH) > 0, Solver(r-1,c), maze[r,c] +:= PATH, return)
|
||||
(iand(x,EAST) > 0, Solver(r,c+1), maze[r,c] +:= PATH, return)
|
||||
(iand(x,SOUTH) > 0, Solver(r+1,c), maze[r,c] +:= PATH, return)
|
||||
(iand(x,WEST) > 0, Solver(r,c-1), maze[r,c] +:= PATH, return)
|
||||
}
|
||||
end
|
||||
|
||||
procedure DisplayMazeSolution(mz) #: draw marked PATH
|
||||
&window := mz.window
|
||||
maze := mz.maze
|
||||
WAttrib("dx="||(dxy:=BORDER+CELL/2),"dy="||dxy)
|
||||
every (r := 1 to *maze) & (c := 1 to *maze[1]) do {
|
||||
if fg ~=== "blue" then Fg(fg := "blue")
|
||||
if iand(maze[r,c],START) > 0 then Fg(fg := "red")
|
||||
if iand(maze[r,c],PATH) > 0 then
|
||||
FillCircle(x := CELL*(c-1),y := CELL*(r-1),rad := CELL/5)
|
||||
}
|
||||
return mz
|
||||
end
|
||||
130
Task/Maze-solving/Icon/maze-solving-3.icon
Normal file
130
Task/Maze-solving/Icon/maze-solving-3.icon
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
global showMice
|
||||
|
||||
import Utils # To get 'Args' singleton class
|
||||
|
||||
procedure main(A)
|
||||
Args(A)
|
||||
if \Args().get("help","yes") then helpMesg()
|
||||
showMice := Args().get("showmice","yes") # Show movements of all mice
|
||||
mh := Args().get("rows") | 32 # Maze height (rows)
|
||||
mw := Args().get("cols") | 48 # Maze width (columns)
|
||||
|
||||
mz := DisplayMaze(GenerateMaze(mh,mw)) # Build and show maze
|
||||
|
||||
QMouse(mz.maze,findStart(mz.maze),&null,0) # Start first quantum mouse
|
||||
waitForCompletion() # block until all quantum mice have finished
|
||||
|
||||
# Mark the best path into the maze and display it.
|
||||
if showPath(mz.maze) then DisplayMazeSolution(mz) else write("No path found!")
|
||||
end
|
||||
|
||||
procedure helpMesg()
|
||||
write(&errout,"Usage: qSolve [--showmice] [--cols=C] [--rows=R]")
|
||||
write(&errout,"\twhere:")
|
||||
write(&errout,"\t\t--showmice # displays all mice paths as they search")
|
||||
write(&errout,"\t\t--cols=C # sets maze width to C (default 16) columns")
|
||||
write(&errout,"\t\t--rows=R # sets maze height to R (default 12) rows")
|
||||
stop()
|
||||
end
|
||||
|
||||
# A "Quantum-mouse" for traversing mazes. Each mouse lives for just one cell, but
|
||||
# can spawn other mice to search from adjoining cells.
|
||||
|
||||
global qMice, bestMouse, bestMouseLock, region, qMiceEmpty
|
||||
record Position(r,c)
|
||||
|
||||
# Must match values used in maze generation!
|
||||
$define FINISH 64 # exit
|
||||
$define START 32 # entrance
|
||||
$define PATH 128
|
||||
$define SEEN 16 # bread crumbs for generator
|
||||
$define NORTH 8 # sides ...
|
||||
$define EAST 4
|
||||
$define SOUTH 2
|
||||
$define WEST 1
|
||||
$define EMPTY 0 # like new
|
||||
|
||||
class QMouse(maze, loc, parent, len, val)
|
||||
|
||||
method getLoc(); return loc; end
|
||||
method getParent(); return \parent; end
|
||||
method getLen(); return len; end
|
||||
method atEnd(); return EMPTY ~= iand(val, FINISH); end
|
||||
method goNorth(); if EMPTY ~= iand(val,NORTH) then return visit(loc.r-1, loc.c); end
|
||||
method goSouth(); if EMPTY ~= iand(val,SOUTH) then return visit(loc.r+1, loc.c); end
|
||||
method goEast(); if EMPTY ~= iand(val,EAST) then return visit(loc.r, loc.c+1); end
|
||||
method goWest(); if EMPTY ~= iand(val,WEST) then return visit(loc.r, loc.c-1); end
|
||||
|
||||
method visit(r,c)
|
||||
critical region[r,c]: if EMPTY = iand(maze[r,c],SEEN) then {
|
||||
if /bestMouse | (len <= bestMouse.getLen()) then { # Keep going?
|
||||
mark(maze, r,c)
|
||||
unlock(region[r,c])
|
||||
return Position(r,c)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
initially (m, l, p, n)
|
||||
initial { # Construct critical region mutexes and completion condvar
|
||||
qMice := mutex(set())
|
||||
qMiceEmpty := condvar()
|
||||
bestMouseLock := mutex()
|
||||
region := list(*m) # Minimize critical region size
|
||||
every r := 1 to *m do region[r] := list(*m[1])
|
||||
every !!region := mutex()
|
||||
}
|
||||
maze := m
|
||||
loc := l
|
||||
parent := p
|
||||
len := n+1
|
||||
val := maze[loc.r,loc.c] | fail # Fail if outside maze
|
||||
insert(qMice, self)
|
||||
thread {
|
||||
if atEnd() then {
|
||||
critical bestMouseLock:
|
||||
if /bestMouse | (len < bestMouse.getLen()) then bestMouse := self
|
||||
}
|
||||
else { # Spawn more mice to look for finish
|
||||
QMouse(maze, goNorth(), self, len)
|
||||
QMouse(maze, goSouth(), self, len)
|
||||
QMouse(maze, goEast(), self, len)
|
||||
QMouse(maze, goWest(), self, len)
|
||||
}
|
||||
|
||||
delete(qMice, self)
|
||||
if *qMice=0 then signal(qMiceEmpty)
|
||||
}
|
||||
end
|
||||
|
||||
procedure mark(maze, r,c)
|
||||
ior(maze[r,c],SEEN)
|
||||
if \showMice then markCell(r,c,"grey",5)
|
||||
return Position(r,c)
|
||||
end
|
||||
|
||||
procedure clearMaze(maze) # Clear out dregs from maze creation
|
||||
every r := 1 to *maze & c := 1 to *maze[1] do # remove breadcrumbs
|
||||
maze[r,c] := iand(maze[r,c],NORTH+EAST+SOUTH+WEST+START+FINISH)
|
||||
end
|
||||
|
||||
procedure findStart(maze) # Anywhere in maze
|
||||
clearMaze(maze) # Remove breadcrumbs
|
||||
every r := 1 to *maze & c := 1 to *maze[1] do # Locate START cell
|
||||
if EMPTY ~= iand(maze[r,c],START) then return mark(maze, r,c)
|
||||
end
|
||||
|
||||
procedure showPath(maze)
|
||||
if path := \bestMouse then { # Mark it in maze
|
||||
repeat {
|
||||
loc := path.getLoc()
|
||||
maze[loc.r,loc.c] +:= PATH
|
||||
path := \path.getParent() | break
|
||||
}
|
||||
return
|
||||
}
|
||||
end
|
||||
|
||||
procedure waitForCompletion()
|
||||
critical qMiceEmpty: while *qMice > 0 do wait(qMiceEmpty)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue