Solve a Hopido puzzle: Difference between revisions

m
No edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(28 intermediate revisions by 11 users not shown)
Line 28:
* [[Solve the no connection puzzle]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">V neighbours = [[2, 2], [-2, 2], [2, -2], [-2, -2], [3, 0], [0, 3], [-3, 0], [0, -3]]
V cnt = 0
V pWid = 0
V pHei = 0
 
F is_valid(a, b)
R -1 < a & a < :pWid & -1 < b & b < :pHei
 
F iterate(&pa, x, y, v)
I v > :cnt
R 1
 
L(i) 0 .< :neighbours.len
V a = x + :neighbours[i][0]
V b = y + :neighbours[i][1]
I is_valid(a, b) & pa[a][b] == 0
pa[a][b] = v
V r = iterate(&pa, a, b, v + 1)
I r == 1
R r
pa[a][b] = 0
R 0
 
F solve(pz, w, h)
V pa = [[-1] * h] * w
V f = 0
:pWid = w
:pHei = h
L(j) 0 .< h
L(i) 0 .< w
I pz[f] == ‘1’
pa[i][j] = 0
:cnt++
f++
 
L(y) 0 .< h
L(x) 0 .< w
I pa[x][y] == 0
pa[x][y] = 1
I 1 == iterate(&pa, x, y, 2)
R (1, pa)
pa[x][y] = 0
R (0, pa)
 
V r = solve(‘011011011111111111111011111000111000001000’, 7, 6)
I r[0] == 1
L(j) 6
L(i) 7
I r[1][i][j] == -1
print(‘ ’, end' ‘’)
E
print(‘ #02’.format(r[1][i][j]), end' ‘’)
print()
E
print(‘No solution!’, end' ‘’)</syntaxhighlight>
 
{{out}}
<pre>
01 25 17 03
27 13 10 07 14 11 08
24 21 18 02 22 19 16
06 26 12 09 04
23 20 15
05
</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">SolveHopido(Grid, Locked, Max, row, col, num:=1, R:="", C:=""){
if (R&&C) ; if neighbors (not first iteration)
{
Line 99 ⟶ 168:
}
return StrReplace(map, ">")
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">;--------------------------------
Grid := [["",0 ,0 ,"",0 ,0 ,""]
,[0 ,0 ,0 ,0 ,0 ,0 ,0]
Line 128 ⟶ 197:
;--------------------------------
MsgBox, 262144, ,% SolveHopido(Grid, Locked, Max, row, col)
return</langsyntaxhighlight>
Outputs:<pre> 17 24 16 25
22 8 11 21 7 10 20
Line 135 ⟶ 204:
12 3 6
27</pre>
 
=={{header|C sharp}}==
The same solver can solve Hidato, Holy Knight's Tour, Hopido and Numbrix puzzles.<br/>
The input can be an array of strings if each cell is one character. The length of the first row must be the number of columns in the puzzle.<br/>
Any non-numeric value indicates a no-go.<br/>
If there are cells that require more characters, then a 2-dimensional array of ints must be used. Any number < 0 indicates a no-go.<br/>
<syntaxhighlight lang="csharp">using System.Collections;
using System.Collections.Generic;
using static System.Console;
using static System.Math;
using static System.Linq.Enumerable;
 
public class Solver
{
private static readonly (int dx, int dy)[]
//other puzzle types elided
hopidoMoves = {(-3,0),(0,-3),(0,3),(3,0),(-2,-2),(-2,2),(2,-2),(2,2)},
 
private (int dx, int dy)[] moves;
public static void Main()
{
Print(new Solver(hopidoMoves).Solve(false,
".00.00.",
"0000000",
"0000000",
".00000.",
"..000..",
"...0..."
));
}
 
public Solver(params (int dx, int dy)[] moves) => this.moves = moves;
 
public int[,] Solve(bool circular, params string[] puzzle)
{
var (board, given, count) = Parse(puzzle);
return Solve(board, given, count, circular);
}
 
public int[,] Solve(bool circular, int[,] puzzle)
{
var (board, given, count) = Parse(puzzle);
return Solve(board, given, count, circular);
}
 
private int[,] Solve(int[,] board, BitArray given, int count, bool circular)
{
var (height, width) = (board.GetLength(0), board.GetLength(1));
bool solved = false;
for (int x = 0; x < height && !solved; x++) {
solved = Range(0, width).Any(y => Solve(board, given, circular, (height, width), (x, y), count, (x, y), 1));
if (solved) return board;
}
return null;
}
 
private bool Solve(int[,] board, BitArray given, bool circular,
(int h, int w) size, (int x, int y) start, int last, (int x, int y) current, int n)
{
var (x, y) = current;
if (x < 0 || x >= size.h || y < 0 || y >= size.w) return false;
if (board[x, y] < 0) return false;
if (given[n - 1]) {
if (board[x, y] != n) return false;
} else if (board[x, y] > 0) return false;
board[x, y] = n;
if (n == last) {
if (!circular || AreNeighbors(start, current)) return true;
}
for (int i = 0; i < moves.Length; i++) {
var move = moves[i];
if (Solve(board, given, circular, size, start, last, (x + move.dx, y + move.dy), n + 1)) return true;
}
if (!given[n - 1]) board[x, y] = 0;
return false;
 
bool AreNeighbors((int x, int y) p1, (int x, int y) p2) => moves.Any(m => (p2.x + m.dx, p2.y + m.dy).Equals(p1));
}
 
private static (int[,] board, BitArray given, int count) Parse(string[] input)
{
(int height, int width) = (input.Length, input[0].Length);
int[,] board = new int[height, width];
int count = 0;
for (int x = 0; x < height; x++) {
string line = input[x];
for (int y = 0; y < width; y++) {
board[x, y] = y < line.Length && char.IsDigit(line[y]) ? line[y] - '0' : -1;
if (board[x, y] >= 0) count++;
}
}
BitArray given = Scan(board, count, height, width);
return (board, given, count);
}
 
private static (int[,] board, BitArray given, int count) Parse(int[,] input)
{
(int height, int width) = (input.GetLength(0), input.GetLength(1));
int[,] board = new int[height, width];
int count = 0;
for (int x = 0; x < height; x++)
for (int y = 0; y < width; y++)
if ((board[x, y] = input[x, y]) >= 0) count++;
BitArray given = Scan(board, count, height, width);
return (board, given, count);
}
 
private static BitArray Scan(int[,] board, int count, int height, int width)
{
var given = new BitArray(count + 1);
for (int x = 0; x < height; x++)
for (int y = 0; y < width; y++)
if (board[x, y] > 0) given[board[x, y] - 1] = true;
return given;
}
 
private static void Print(int[,] board)
{
if (board == null) {
WriteLine("No solution");
} else {
int w = board.Cast<int>().Where(i => i > 0).Max(i => (int?)Ceiling(Log10(i+1))) ?? 1;
string e = new string('-', w);
foreach (int x in Range(0, board.GetLength(0)))
WriteLine(string.Join(" ", Range(0, board.GetLength(1))
.Select(y => board[x, y] < 0 ? e : board[x, y].ToString().PadLeft(w, ' '))));
}
WriteLine();
}
 
}</syntaxhighlight>
{{out}}
<pre style="height:30ex;overflow:scroll">
-- 1 8 -- 2 7 --
25 22 19 26 23 20 27
9 16 13 10 17 14 11
-- 4 24 21 3 6 --
-- -- 18 15 12 -- --
-- -- -- 5 -- -- --
</pre>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">
#include <vector>
#include <sstream>
Line 271 ⟶ 481:
return system( "pause" );
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 285 ⟶ 495:
{{trans|C++}}
From the refactored C++ version with more precise typing. This tries all possible start positions. The HopidoPuzzle struct is created at compile-time, so its pre-conditions can catch most malformed puzzles at compile-time.
<langsyntaxhighlight lang="d">import std.stdio, std.conv, std.string, std.range, std.algorithm, std.typecons;
 
 
Line 398 ⟶ 608:
else
writefln("One solution:\n%(%-(%2s %)\n%)", solution);
}</langsyntaxhighlight>
{{out}}
<pre>One solution:
Line 411 ⟶ 621:
{{trans|Ruby}}
This solution uses HLPsolver from [[Solve_a_Hidato_puzzle#Elixir | here]]
<langsyntaxhighlight lang="elixir"># require HLPsolver
adjacent = [{-3, 0}, {0, -3}, {0, 3}, {3, 0}, {-2, -2}, {-2, 2}, {2, -2}, {2, 2}]
Line 423 ⟶ 633:
. . . 1 . . .
"""
HLPsolver.solve(board, adjacent)</langsyntaxhighlight>
 
{{out}}
Line 442 ⟶ 652:
23 20 15
1
</pre>
 
=={{header|Go}}==
{{trans|Java}}
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"sort"
)
 
var board = []string{
".00.00.",
"0000000",
"0000000",
".00000.",
"..000..",
"...0...",
}
 
var moves = [][2]int{
{-3, 0}, {0, 3}, {3, 0}, {0, -3},
{2, 2}, {2, -2}, {-2, 2}, {-2, -2},
}
 
var grid [][]int
 
var totalToFill = 0
 
func solve(r, c, count int) bool {
if count > totalToFill {
return true
}
nbrs := neighbors(r, c)
if len(nbrs) == 0 && count != totalToFill {
return false
}
sort.Slice(nbrs, func(i, j int) bool {
return nbrs[i][2] < nbrs[j][2]
})
 
for _, nb := range nbrs {
r = nb[0]
c = nb[1]
grid[r][c] = count
if solve(r, c, count+1) {
return true
}
grid[r][c] = 0
}
return false
}
 
func neighbors(r, c int) (nbrs [][3]int) {
for _, m := range moves {
x := m[0]
y := m[1]
if grid[r+y][c+x] == 0 {
num := countNeighbors(r+y, c+x) - 1
nbrs = append(nbrs, [3]int{r + y, c + x, num})
}
}
return
}
 
func countNeighbors(r, c int) int {
num := 0
for _, m := range moves {
if grid[r+m[1]][c+m[0]] == 0 {
num++
}
}
return num
}
 
func printResult() {
for _, row := range grid {
for _, i := range row {
if i == -1 {
fmt.Print(" ")
} else {
fmt.Printf("%2d ", i)
}
}
fmt.Println()
}
}
 
func main() {
nRows := len(board) + 6
nCols := len(board[0]) + 6
grid = make([][]int, nRows)
for r := 0; r < nRows; r++ {
grid[r] = make([]int, nCols)
for c := 0; c < nCols; c++ {
grid[r][c] = -1
}
for c := 3; c < nCols-3; c++ {
if r >= 3 && r < nRows-3 {
if board[r-3][c-3] == '0' {
grid[r][c] = 0
totalToFill++
}
}
}
}
pos, r, c := -1, 0, 0
for {
for {
pos++
r = pos / nCols
c = pos % nCols
if grid[r][c] != -1 {
break
}
}
grid[r][c] = 1
if solve(r, c, 2) {
break
}
grid[r][c] = 0
if pos >= nRows*nCols {
break
}
}
printResult()
}</syntaxhighlight>
 
{{out}}
<pre>
1 22 14 21
18 10 7 17 11 8 16
5 24 27 4 23 26 13
2 19 9 15 20
6 25 12
3
</pre>
 
Line 448 ⟶ 794:
Minor variant of [[Solve_a_Holy_Knight's_tour]]. Works in Unicon only.
 
<langsyntaxhighlight lang="unicon">global nCells, cMap, best
record Pos(r,c)
 
Line 545 ⟶ 891:
QMouse(puzzle, visit(loc.r, loc.c+3), self, val)
QMouse(puzzle, visit(loc.r-2,loc.c+2), self, val)
end</langsyntaxhighlight>
 
Sample run:
Line 577 ⟶ 923:
=={{header|Java}}==
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.util.*;
 
public class Hopido {
Line 685 ⟶ 1,031:
}
}
}</langsyntaxhighlight>
 
<pre>
Line 695 ⟶ 1,041:
3 </pre>
 
=={{header|Perl 6Julia}}==
UsingUses the Hidato puzzle solver frommodule, which has its source code listed [[Solve_a_Hidato_puzzle#Julia | here]] in the Hadato task.
<syntaxhighlight lang="julia">using .Hidato # Note that the . here means to look locally for the module rather than in the libraries
<lang perl6>my @adjacent = [3, 0],
 
[2, -2], [2, 2],
const hopid = """
[0, -3], [0, 3],
. 0 0 . 0 0 .
[-2, -2], [-2, 2],
0 0 0 0 0 [-3,0 0];
0 0 0 0 0 0 0
. 0 0 0 0 0 .
. . 0 0 0 . .
. . . 0 . . . """
 
const hopidomoves = [[-3, 0], [0, -3], [-2, -2], [-2, 2], [2, -2], [0, 3], [3, 0], [2, 2]]
 
board, maxmoves, fixed, starts = hidatoconfigure(hopid)
printboard(board, " 0", " ")
hidatosolve(board, maxmoves, hopidomoves, fixed, starts[1][1], starts[1][2], 1)
printboard(board)
</syntaxhighlight>{{output}}<pre>
0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0
0 0 0
0
 
4 15 5 16
1 22 25 2 21 24 27
14 11 8 17 12 9 6
3 20 23 26 19
13 10 7
18
</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">// version 1.2.0
 
val board = listOf(
".00.00.",
"0000000",
"0000000",
".00000.",
"..000..",
"...0..."
)
 
val moves = listOf(
-3 to 0, 0 to 3, 3 to 0, 0 to -3,
2 to 2, 2 to -2, -2 to 2, -2 to -2
)
 
lateinit var grid: List<IntArray>
var totalToFill = 0
 
fun solve(r: Int, c: Int, count: Int): Boolean {
if (count > totalToFill) return true
val nbrs = neighbors(r, c)
if (nbrs.isEmpty() && count != totalToFill) return false
nbrs.sortBy { it[2] }
for (nb in nbrs) {
val rr = nb[0]
val cc = nb[1]
grid[rr][cc] = count
if (solve(rr, cc, count + 1)) return true
grid[rr][cc] = 0
}
return false
}
 
fun neighbors(r: Int, c: Int): MutableList<IntArray> {
val nbrs = mutableListOf<IntArray>()
for (m in moves) {
val x = m.first
val y = m.second
if (grid[r + y][c + x] == 0) {
val num = countNeighbors(r + y, c + x) - 1
nbrs.add(intArrayOf(r + y, c + x, num))
}
}
return nbrs
}
 
fun countNeighbors(r: Int, c: Int): Int {
var num = 0
for (m in moves)
if (grid[r + m.second][c + m.first] == 0) num++
return num
}
 
fun printResult() {
for (row in grid) {
for (i in row) {
print(if (i == -1) " " else "%2d ".format(i))
}
println()
}
}
 
fun main(args: Array<String>) {
val nRows = board.size + 6
val nCols = board[0].length + 6
grid = List(nRows) { IntArray(nCols) { -1} }
for (r in 0 until nRows) {
for (c in 3 until nCols - 3) {
if (r in 3 until nRows - 3) {
if (board[r - 3][c - 3] == '0') {
grid[r][c] = 0
totalToFill++
}
}
}
}
var pos = -1
var rr: Int
var cc: Int
do {
do {
pos++
rr = pos / nCols
cc = pos % nCols
}
while (grid[rr][cc] == -1)
 
grid[rr][cc] = 1
if (solve(rr, cc, 2)) break
grid[rr][cc] = 0
}
while (pos < nRows * nCols)
 
printResult()
}</syntaxhighlight>
 
solveboard q:to/END/;
. _ _ . _ _ .
_ _ _ _ _ _ _
_ _ _ _ _ _ _
. _ _ _ _ _ .
. . _ _ _ . .
. . . 1 . . .
END</lang>
{{out}}
<pre>
<pre> 21 4 20 3
1 22 14 21
26 12 15 25 11 14 24
17 6 9 18 10 5 7 17 11 8 1916
22 5 24 27 13 4 23 26 13 2
16 7 10 2 19 9 15 20
1 6 25 12
3
59 tries</pre>
</pre>
 
=={{header|PhixMathematica}}/{{header|Wolfram Language}}==
Uses shortest tours on graphs to solve it:
Simple brute force approach.
<syntaxhighlight lang="mathematica">puzz = ".00.00.\n0000000\n0000000\n.00000.\n..000..\n...0...";
<lang Phix>sequence board
puzz //= StringSplit[#, "\n"] & /* Map[Characters];
puzz //= Transpose /* Map[Reverse];
pos = Position[puzz, "0", {2}];
moves = Select[Select[Tuples[pos, 2], MatchQ[EuclideanDistance @@ #, 2 Sqrt[2] | 3] &], OrderedQ];
g = Graph[UndirectedEdge @@@ moves];
ord = Most[FindShortestTour[g][[2]]];
Graphics[MapThread[Text, {Range[Length[ord]], VertexList[g][[ord]]}]]</syntaxhighlight>
{{out}}
Shows a graphical solution.
 
=={{header|Nim}}==
integer limit, tries
{{trans|Go}}
 
<syntaxhighlight lang="nim">import algorithm, sequtils, strformat
constant ROW = 1, COL = 2
constant moves = {{-2,-2},{-2,2},{2,-2},{2,2},{-3,0},{3,0},{0,-3},{0,3}}
 
const Moves = [(-3, 0), (0, 3), ( 3, 0), ( 0, -3),
function solve(integer row, integer col, integer n)
( 2, 2), (2, -2), (-2, 2), (-2, -2)]
integer nrow, ncol
tries+= 1
if n>limit then return 1 end if
for move=1 to length(moves) do
nrow = row+moves[move][ROW]
ncol = col+moves[move][COL]*3
if nrow>=1 and nrow<=length(board)
and ncol>=1 and ncol<=length(board[row])
and board[nrow][ncol]=' ' then
board[nrow][ncol-1..ncol] = sprintf("%2d",n)
if solve(nrow,ncol,n+1) then return 1 end if
board[nrow][ncol-1..ncol] = " "
end if
end for
return 0
end function
 
type
procedure Hopido(sequence s, integer w, integer h)
integer x, y
atom t0 = time()
board = split(s,'\n')
limit = 0
for x=1 to h do
for y=3 to w*3 by 3 do
if board[x][y]='0' then
board[x][y] = ' '
limit += 1
end if
end for
end for
while 1 do
x = rand(h)
y = rand(w)*3
if board[x][y]=' ' then exit end if
end while
board[x][y] = '1'
tries = 0
if solve(x,y,2) then
puts(1,join(board,"\n"))
printf(1,"\nsolution found in %d tries (%3.2fs)\n",{tries,time()-t0})
else
puts(1,"no solutions found\n")
end if
end procedure
 
Hopido = object
constant board1 = """
grid: seq[seq[int]]
. 0 0 . 0 0 .
nRows, nCols: int
0 0 0 0 0 0 0
totalToFill : Natural
0 0 0 0 0 0 0
 
. 0 0 0 0 0 .
Neighbor = (int, int, int)
. . 0 0 0 . .
 
. . . 0 . . ."""
 
Hopido(board1,7,6)</lang>
proc initHopido(board: openArray[string]): Hopido =
result.nRows = board.len + 6
result.nCols = board[0].len + 6
result.grid = newSeqWith(result.nRows, repeat(-1, result.nCols))
 
for row in 0..board.high:
for col in 0..board[0].high:
if board[row][col] == '0':
result.grid[row + 3][col + 3] = 0
inc result.totalToFill
 
 
proc countNeighbors(hopido: Hopido; row, col: Natural): int =
for (x, y) in Moves:
if hopido.grid[row + y][col + x] == 0:
inc result
 
 
proc neighbors(hopido: Hopido; row, col: Natural): seq[Neighbor] =
for (x, y) in Moves:
if hopido.grid[row + y][col + x] == 0:
let num = hopido.countNeighbors(row + y, col + x) - 1
result.add (row + y, col + x, num)
 
 
proc solve(hopido: var Hopido; row, col, count: Natural): bool =
 
if count > hopido.totalTofill: return true
 
var nbrs = hopido.neighbors(row, col)
if nbrs.len == 0 and count != hopido.totalToFill:
return false
 
nbrs.sort(proc(a, b: Neighbor): int = cmp(a[2], b[2]))
 
for (row, col, _) in nbrs:
hopido.grid[row][col] = count
if hopido.solve(row, col, count + 1):
return true
hopido.grid[row][col] = 0
 
 
proc findSolution(hopido: var Hopido) =
var pos = -1
var row, col: Natural
 
while true:
while true:
inc pos
row = pos div hopido.nCols
col = pos mod hopido.nCols
if hopido.grid[row][col] != -1:
break
hopido.grid[row][col] = 1
if hopido.solve(row, col, 2):
break
hopido.grid[row][col] = 0
if pos >= hopido.nRows * hopido.nCols:
break
 
 
proc print(hopido: Hopido) =
for row in hopido.grid:
for val in row:
stdout.write if val == -1: " " else: &"{val:2} "
echo()
 
 
when isMainModule:
 
const Board = [".00.00.",
"0000000",
"0000000",
".00000.",
"..000..",
"...0..."]
 
var hopido = initHopido(Board)
hopido.findSolution()
hopido.print()</syntaxhighlight>
 
{{out}}
<pre>
1 22 14 21
18 10 7 17 11 8 16
5 24 27 4 23 26 13
2 19 9 15 20
6 25 12
3
</pre>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # http://www.rosettacode.org/wiki/Solve_a_Hopido_puzzle
use warnings;
 
$_ = do { local $/; <DATA> };
s/./$&$&/g; # double chars
my $w = /\n/ && $-[0];
my $wd = 3 * $w + 1; # vertical gap
my $wr = 2 * $w + 8; # down right gap
my $wl = 2 * $w - 8; # down left gap
place($_, '00');
die "No solution\n";
 
sub place
{
(local $_, my $last) = @_;
(my $new = $last)++;
/$last.{10}(?=00)/g and place( s/\G00/$new/r, $new ); # right
/(?=00.{10}$last)/g and place( s/\G00/$new/r, $new ); # left
/$last.{$wd}(?=00)/gs and place( s/\G00/$new/r, $new ); # down
/(?=00.{$wd}$last)/gs and place( s/\G00/$new/r, $new ); # up
/$last.{$wr}(?=00)/gs and place( s/\G00/$new/r, $new ); # down right
/(?=00.{$wr}$last)/gs and place( s/\G00/$new/r, $new ); # up left
/$last.{$wl}(?=00)/gs and place( s/\G00/$new/r, $new ); # down left
/(?=00.{$wl}$last)/gs and place( s/\G00/$new/r, $new ); # up right
/00/ and return;
print "Solution\n\n", s/ / /gr =~ s/0\B/ /gr;
exit;
}
 
__DATA__
. 0 0 . 0 0 .
0 0 0 0 0 0 0
0 0 0 0 0 0 0
. 0 0 0 0 0 .
. . 0 0 0 . .
. . . 0 . . .</syntaxhighlight>
{{out}}
<pre>
Solution
 
.. 2 24 .. 1 25 ..
7 10 13 6 9 12 5
15 22 19 16 23 20 17
.. 3 8 11 4 26 ..
.. .. 14 21 18 .. ..
.. .. .. 27 .. .. ..
</pre>
 
=={{header|Phix}}==
Simple brute force approach.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">board</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">limit</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tries</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">ROW</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">COL</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">moves</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">solve</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">row</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">col</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">nrow</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ncol</span>
<span style="color: #000000;">tries</span><span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">></span><span style="color: #000000;">limit</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">move</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">nrow</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">row</span><span style="color: #0000FF;">+</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">move</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ROW</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">ncol</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">col</span><span style="color: #0000FF;">+</span><span style="color: #000000;">moves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">move</span><span style="color: #0000FF;">][</span><span style="color: #000000;">COL</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">3</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">nrow</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">nrow</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">ncol</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ncol</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">row</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nrow</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ncol</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nrow</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ncol</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">ncol</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%2d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nrow</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ncol</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nrow</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ncol</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">ncol</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" "</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Hopido</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">rx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ry</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">limit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">h</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">to</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">*</span><span style="color: #000000;">3</span> <span style="color: #008080;">by</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">' '</span>
<span style="color: #000000;">limit</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">rx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ry</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">3</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ry</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ry</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'1'</span>
<span style="color: #000000;">tries</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ry</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nsolution found in %d tries (%3.2fs)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tries</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"no solutions found\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">board1</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
. 0 0 . 0 0 .
0 0 0 0 0 0 0
0 0 0 0 0 0 0
. 0 0 0 0 0 .
. . 0 0 0 . .
. . . 0 . . ."""</span>
<span style="color: #000000;">Hopido</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
The best and worse cases observed were:
<pre>
Line 799 ⟶ 1,442:
. . . 24 . . .
solution found in 67702 tries (0.09s)
</pre>
=={{header|Picat}}==
<syntaxhighlight lang="picat">
import sat.
main =>
Grid = {{0,1,1,0,1,1,0},
{1,1,1,1,1,1,1},
{1,1,1,1,1,1,1},
{0,1,1,1,1,1,0},
{0,0,1,1,1,0,0},
{0,0,0,1,0,0,0}},
NR = len(Grid), NC = len(Grid[1]),
Es = [{(R,C), (R1,C1), _} : R in 1..NR, C in 1..NC, R1 in 1..NR, C1 in 1..NC, % Edges
((R1 = R, abs(C1 - C) = 3); (C1 = C, abs(R1 - R) = 3); % horizontal hop
(abs(R1 - R) = 2, abs(C1 - C) = 2)), % diagonal hop
Grid[R,C] = 1, Grid[R1,C1] = 1],
hcp_grid(Grid, Es), % find a Hamiltion cylce on the vertices in Grid through the edges in Es
solve(vars(Es)),
% Write the solution as a matrix, starting at the base tile 6|4:
M = {{0: _ in 1..NC} : _ in 1..NR},
R1 = 6, C1 = 4, I = 0,
do
I := I + 1, M[R1,C1] := I, Stop = 0,
foreach({(R1,C1), (R2,C2), 1} in Es, break(Stop == 1))
R1 := R2, C1 := C2, Stop := 1
end
while ((R1,C1) != (6,4)),
foreach(R in 1..NR, C in 1..NC)
if M[R,C] = 0 then print(" ") else printf("%2d ", M[R,C]) end,
if C = NC then nl end
end.
</syntaxhighlight>
Output:
<pre> 24 15 23 26
6 9 12 5 8 11 4
14 17 20 25 16 19 22
2 7 10 3 27
13 18 21
1
CPU time 0.019 seconds</pre>
 
=={{header|Prolog}}==
This is a pure prolog implementation (no cuts,etc..), the only libary predicate used is select/3 witch is pure.
<syntaxhighlight lang="prolog">hopido(Grid,[C|Solved],Xs,Ys) :-
select(C,Grid,RGrid),
solve(RGrid,C,Solved,Xs,Ys).
solve([],_,[],_,_).
solve(Grid,p(X,Y),[p(X1,Y1)|R],Xs,Ys) :-
valid_move(X,Y,Xs,Ys,X1,Y1),
select(p(X1,Y1),Grid,NextGrid),
solve(NextGrid,p(X1,Y1),R,Xs,Ys).
valid_move(X,Y,Xs,_,X1,Y) :- j3(X,X1,Xs). % right (3,0)
valid_move(X,Y,Xs,_,X1,Y) :- j3(X1,X,Xs). % left (-3,0)
valid_move(X,Y,_,Ys,X,Y1) :- j3(Y,Y1,Ys). % up (0,3).
valid_move(X,Y,_,Ys,X,Y1) :- j3(Y1,Y,Ys). % down (0,-3).
valid_move(X,Y,Xs,Ys,X1,Y1) :- j2(X,X1,Xs), j2(Y,Y1,Ys). % up-right (2,2).
valid_move(X,Y,Xs,Ys,X1,Y1) :- j2(X1,X,Xs), j2(Y,Y1,Ys). % up-left (-2,2).
valid_move(X,Y,Xs,Ys,X1,Y1) :- j2(X1,X,Xs), j2(Y1,Y,Ys). % down-left (-2,-2).
valid_move(X,Y,Xs,Ys,X1,Y1) :- j2(X,X1,Xs), j2(Y1,Y,Ys). % down-right (2,-2).
 
j2(O,N,[O,_,N|_]).
j2(O,N,[_|T]) :- j2(O,N,T).
 
j3(O,N,[O,_,_,N|_]).
j3(O,N,[_|T]) :- j3(O,N,T).</syntaxhighlight>
To test send in a list of p/2 terms that represent points that can be hopped to (order is not important).
 
The grid coords can be anything so need to specify the valid coordinates as a list (in this case numbers between 0 and 6).
<syntaxhighlight lang="prolog">puzzle([
p(1,0),p(2,0) ,p(4,0),p(5,0),
p(0,1),p(1,1),p(2,1),p(3,1),p(4,1),p(5,1),p(6,1),
p(0,2),p(1,2),p(2,2),p(3,2),p(4,2),p(5,2),p(6,2),
p(1,3),p(2,3),p(3,3),p(4,3),p(5,3),
p(2,4),p(3,4),p(4,4),
p(3,5)
]).
test :-
puzzle(P),
XYs = [0,1,2,3,4,5,6],
hopido(P,S,XYs,XYs),
maplist(writeln,S).</syntaxhighlight>
{{out}}
<pre>
?- time(test).
p(1,0)
p(4,0)
p(4,3)
p(1,3)
p(3,5)
p(5,3)
p(5,0)
p(2,0)
p(4,2)
p(1,2)
p(3,4)
p(5,2)
p(2,2)
p(4,4)
p(6,2)
p(3,2)
p(0,2)
p(2,4)
p(2,1)
p(5,1)
p(3,3)
p(1,1)
p(4,1)
p(2,3)
p(0,1)
p(3,1)
p(6,1)
% 356,635 inferences, 0.062 CPU in 0.081 seconds (78% CPU, 5715268 Lips)
true
</pre>
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">
from sys import stdout
 
Line 866 ⟶ 1,626:
else:
stdout.write("No solution!")
</langsyntaxhighlight> {{out}}<pre>
01 25 17 03
27 13 10 07 14 11 08
Line 881 ⟶ 1,641:
essentially the neighbourhood function.
 
<langsyntaxhighlight lang="racket">#lang racket
(require "hidato-family-solver.rkt")
 
Line 898 ⟶ 1,658:
#(_ _ 0 0 0 _ _)
#(_ _ _ 0 _ _ _)))))
</syntaxhighlight>
</lang>
 
{{out}}
Line 907 ⟶ 1,667:
_ _ 14 23 26 _ _
_ _ _ 17 _ _ _</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
 
This uses a Warnsdorff solver, which cuts down the number of tries by more than a factor of six over the brute force approach. This same solver is used in:
 
* [[Solve a Hidato puzzle#Raku|Solve a Hidato puzzle]]
* [[Solve a Hopido puzzle#Raku|Solve a Hopido puzzle]]
* [[Solve a Holy Knight's tour#Raku|Solve a Holy Knight's tour]]
* [[Solve a Numbrix puzzle#Raku|Solve a Numbrix puzzle]]
* [[Solve the no connection puzzle#Raku|Solve the no connection puzzle]]
 
<syntaxhighlight lang="raku" line>my @adjacent = [3, 0],
[2, -2], [2, 2],
[0, -3], [0, 3],
[-2, -2], [-2, 2],
[-3, 0];
 
solveboard q:to/END/;
. _ _ . _ _ .
_ _ _ _ _ _ _
_ _ _ _ _ _ _
. _ _ _ _ _ .
. . _ _ _ . .
. . . 1 . . .
END
 
sub solveboard($board) {
my $max = +$board.comb(/\w+/);
my $width = $max.chars;
 
my @grid;
my @known;
my @neigh;
my @degree;
@grid = $board.lines.map: -> $line {
[ $line.words.map: { /^_/ ?? 0 !! /^\./ ?? Rat !! $_ } ]
}
sub neighbors($y,$x --> List) {
eager gather for @adjacent {
my $y1 = $y + .[0];
my $x1 = $x + .[1];
take [$y1,$x1] if defined @grid[$y1][$x1];
}
}
 
for ^@grid -> $y {
for ^@grid[$y] -> $x {
if @grid[$y][$x] -> $v {
@known[$v] = [$y,$x];
}
if @grid[$y][$x].defined {
@neigh[$y][$x] = neighbors($y,$x);
@degree[$y][$x] = +@neigh[$y][$x];
}
}
}
print "\e[0H\e[0J";
 
my $tries = 0;
 
try_fill 1, @known[1];
 
sub try_fill($v, $coord [$y,$x] --> Bool) {
return True if $v > $max;
$tries++;
 
my $old = @grid[$y][$x];
 
return False if +$old and $old != $v;
return False if @known[$v] and @known[$v] !eqv $coord;
 
@grid[$y][$x] = $v; # conjecture grid value
 
print "\e[0H"; # show conjectured board
for @grid -> $r {
say do for @$r {
when Rat { ' ' x $width }
when 0 { '_' x $width }
default { .fmt("%{$width}d") }
}
}
 
 
my @neighbors = @neigh[$y][$x][];
 
my @degrees;
for @neighbors -> \n [$yy,$xx] {
my $d = --@degree[$yy][$xx]; # conjecture new degrees
push @degrees[$d], n; # and categorize by degree
}
 
for @degrees.grep(*.defined) -> @ties {
for @ties.reverse { # reverse works better for this hidato anyway
return True if try_fill $v + 1, $_;
}
}
 
for @neighbors -> [$yy,$xx] {
++@degree[$yy][$xx]; # undo degree conjectures
}
 
@grid[$y][$x] = $old; # undo grid value conjecture
return False;
}
say "$tries tries";
}</syntaxhighlight>
 
{{out}}
<pre> 21 4 20 3
26 12 15 25 11 14 24
17 6 9 18 5 8 19
22 27 13 23 2
16 7 10
1
59 tries</pre>
 
=={{header|REXX}}==
Line 912 ⟶ 1,791:
 
No particular effort was made to reduce the elapsed time in solving the puzzle.
<langsyntaxhighlight lang="rexx">/*REXX program solves a Hopido puzzle, it also displays the puzzle and the solution. */
call time 'Reset' /*reset the REXX elapsed timer to zero.*/
maxR=0; maxC=0; maxX=0; minR=9e9; minC=9e9; minX=9e9; cells=0; @.=
Line 967 ⟶ 1,846:
say _
end /*r*/
say; return</langsyntaxhighlight>
'''output''' &nbsp; when the input is: <br>
<tt> 1 4 1 \2 3 . . . \3 2 . . . . . \4 1 . . . . . . . \5 1 . . . . . . . \6 2 . . \6 5 . . </tt>
Line 992 ⟶ 1,871:
=={{header|Ruby}}==
This solution uses HLPsolver from [[Solve_a_Hidato_puzzle#With_Warnsdorff | here]]
<langsyntaxhighlight lang="ruby">require 'HLPsolver'
 
ADJACENT = [[-3, 0], [0, -3], [0, 3], [3, 0], [-2, -2], [-2, 2], [2, -2], [2, 2]]
Line 1,006 ⟶ 1,885:
t0 = Time.now
HLPsolver.new(board1).solve
puts " #{Time.now - t0} sec"</langsyntaxhighlight>
Which produces:
<pre>
Line 1,030 ⟶ 1,909:
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
 
oo::class create HopidoSolver {
Line 1,125 ⟶ 2,004:
HopidoSolver create hop $puzzle
hop solve
showPuzzle [hop solution] "Output"</langsyntaxhighlight>
{{out}}
<pre>
Line 1,142 ⟶ 2,021:
15 18 21
1
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-sort}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./sort" for Sort
import "./fmt" for Fmt
 
var board = [
".00.00.",
"0000000",
"0000000",
".00000.",
"..000..",
"...0..."
]
 
var moves = [
[-3, 0], [0, 3], [ 3, 0], [ 0, -3],
[ 2, 2], [2, -2], [-2, 2], [-2, -2]
]
 
var grid = []
var totalToFill = 0
 
var countNeighbors = Fn.new { |r, c|
var num = 0
for (m in moves) if (grid[r + m[1]][c + m[0]] == 0) num = num + 1
return num
}
 
var neighbors = Fn.new { |r, c|
var nbrs = []
for (m in moves) {
var x = m[0]
var y = m[1]
if (grid[r + y][c + x] == 0) {
var num = countNeighbors.call(r + y, c + x) - 1
nbrs.add([r + y, c + x, num])
}
}
return nbrs
}
 
var solve // recursive
solve = Fn.new { |r, c, count|
if (count > totalToFill) return true
var nbrs = neighbors.call(r, c)
if (nbrs.isEmpty && count != totalToFill) return false
var cmp = Fn.new { |n1, n2| (n1[2] - n2[2]).sign }
Sort.insertion(nbrs, cmp) // stable sort
for (nb in nbrs) {
var rr = nb[0]
var cc = nb[1]
grid[rr][cc] = count
if (solve.call(rr, cc, count + 1)) return true
grid[rr][cc] = 0
}
return false
}
 
var printResult = Fn.new {
for (row in grid) {
for (i in row) {
if (i == -1) {
System.write(" ")
} else {
Fmt.write("$2d ", i)
}
}
System.print()
}
}
 
var nRows = board.count + 6
var nCols = board[0].count + 6
grid = List.filled(nRows, null)
for (r in 0...nRows) {
grid[r] = List.filled(nCols, -1)
for (c in 3...nCols - 3) {
if (r >= 3 && r < nRows - 3) {
if (board[r - 3][c - 3] == "0") {
grid[r][c] = 0
totalToFill = totalToFill + 1
}
}
}
}
var pos = -1
var r
var c
while (true) {
while (true) {
pos = pos + 1
r = (pos / nCols).truncate
c = pos % nCols
if (grid[r][c] != -1) break
}
grid[r][c] = 1
if (solve.call(r, c, 2)) break
grid[r][c] = 0
if (pos >= nRows * nCols) break
}
printResult.call()</syntaxhighlight>
 
{{out}}
<pre>
1 22 14 21
18 10 7 17 11 8 16
5 24 27 4 23 26 13
2 19 9 15 20
6 25 12
3
</pre>
 
=={{header|zkl}}==
This solution uses the code from [[Solve_a_Numbrix_puzzle#zkl]]
<langsyntaxhighlight lang="zkl">hi:= // 0==empty cell, X==not a cell
#<<<
" X 0 0 X 0 0 X
Line 1,166 ⟶ 2,159:
println();
puzzle.print_board();
println();</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits