Solve a Hopido puzzle: Difference between revisions
Content added Content deleted
No edit summary |
No edit summary |
||
Line 22: | Line 22: | ||
* [[Solve a Numbrix puzzle]] |
* [[Solve a Numbrix puzzle]] |
||
* [[Knight's tour]] |
* [[Knight's tour]] |
||
==Icon and {{header|Unicon}}== |
|||
Minor variant of [[Solve_a_Holy_Knight's_tour]]. Works in Unicon only. |
|||
<lang unicon>global nCells, cMap, best |
|||
record Pos(r,c) |
|||
procedure main(A) |
|||
puzzle := showPuzzle("Input",readPuzzle()) |
|||
QMouse(puzzle,findStart(puzzle),&null,0) |
|||
showPuzzle("Output", solvePuzzle(puzzle)) | write("No solution!") |
|||
end |
|||
procedure readPuzzle() |
|||
# Start with a reduced puzzle space |
|||
p := [[-1],[-1]] |
|||
nCells := maxCols := 0 |
|||
every line := !&input do { |
|||
put(p,[: -1 | -1 | gencells(line) | -1 | -1 :]) |
|||
maxCols <:= *p[-1] |
|||
} |
|||
every put(p, [-1]|[-1]) |
|||
# Now normalize all rows to the same length |
|||
every i := 1 to *p do p[i] := [: !p[i] | (|-1\(maxCols - *p[i])) :] |
|||
return p |
|||
end |
|||
procedure gencells(s) |
|||
static WS, NWS |
|||
initial { |
|||
NWS := ~(WS := " \t") |
|||
cMap := table() # Map to/from internal model |
|||
cMap["#"] := -1; cMap["_"] := 0 |
|||
cMap[-1] := " "; cMap[0] := "_" |
|||
} |
|||
s ? while not pos(0) do { |
|||
w := (tab(many(WS))|"", tab(many(NWS))) | break |
|||
w := numeric(\cMap[w]|w) |
|||
if -1 ~= w then nCells +:= 1 |
|||
suspend w |
|||
} |
|||
end |
|||
procedure showPuzzle(label, p) |
|||
write(label," with ",nCells," cells:") |
|||
every r := !p do { |
|||
every c := !r do writes(right((\cMap[c]|c),*nCells+1)) |
|||
write() |
|||
} |
|||
return p |
|||
end |
|||
procedure findStart(p) |
|||
if \p[r := !*p][c := !*p[r]] = 1 then return Pos(r,c) |
|||
end |
|||
procedure solvePuzzle(puzzle) |
|||
if path := \best then { |
|||
repeat { |
|||
loc := path.getLoc() |
|||
puzzle[loc.r][loc.c] := path.getVal() |
|||
path := \path.getParent() | break |
|||
} |
|||
return puzzle |
|||
} |
|||
end |
|||
class QMouse(puzzle, loc, parent, val) |
|||
method getVal(); return val; end |
|||
method getLoc(); return loc; end |
|||
method getParent(); return parent; end |
|||
method atEnd(); return nCells = val; end |
|||
method visit(r,c) |
|||
if /best & validPos(r,c) then return Pos(r,c) |
|||
end |
|||
method validPos(r,c) |
|||
v := val+1 |
|||
xv := (0 <= puzzle[r][c]) | fail |
|||
if xv = (v|0) then { # make sure this path hasn't already gone there |
|||
ancestor := self |
|||
while xl := (ancestor := \ancestor.getParent()).getLoc() do |
|||
if (xl.r = r) & (xl.c = c) then fail |
|||
return |
|||
} |
|||
end |
|||
initially |
|||
val := val+1 |
|||
if atEnd() then return best := self |
|||
QMouse(puzzle, visit(loc.r-3,loc.c), self, val) |
|||
QMouse(puzzle, visit(loc.r-2,loc.c-2), self, val) |
|||
QMouse(puzzle, visit(loc.r, loc.c-3), self, val) |
|||
QMouse(puzzle, visit(loc.r+2,loc.c-2), self, val) |
|||
QMouse(puzzle, visit(loc.r+3,loc.c), self, val) |
|||
QMouse(puzzle, visit(loc.r+2,loc.c+2), self, val) |
|||
QMouse(puzzle, visit(loc.r, loc.c+3), self, val) |
|||
QMouse(puzzle, visit(loc.r-2,loc.c+2), self, val) |
|||
end</lang> |
|||
Sample run: |
|||
<pre> |
|||
->hopido <hopido1.in |
|||
Input with 27 cells: |
|||
_ _ _ _ |
|||
_ _ _ _ _ _ _ |
|||
_ _ _ _ _ _ _ |
|||
_ _ _ _ _ |
|||
_ _ _ |
|||
1 |
|||
Output with 27 cells: |
|||
3 21 13 22 |
|||
25 9 6 26 10 7 27 |
|||
20 17 14 2 18 15 12 |
|||
4 24 8 5 23 |
|||
19 16 11 |
|||
1 |
|||
-> |
|||
</pre> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |