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}}==