| Bytes | Lang | Time | Link |
|---|---|---|---|
| 230 | Python3 | 250516T031221Z | Ajax1234 |
| 166 | Python 3 | 200609T122629Z | Jitse |
| 213 | R | 200609T163336Z | Dominic |
| 305 | Perl 5 | 200506T230237Z | Kjetil S |
| 029 | Sledgehammer | 200506T092225Z | the defa |
Python3, 230 bytes
E=enumerate
def f(b):
q=[(0,0,{(x,y)for x,r in E(b)for y,v in E(r)if v and x+y})]
for x,y,m in q:
if not m:return 1
for X,Y in[[2,1],[1,2],[-2,1],[2,-1],[-2,-1],[1,-2],[-1,2],[-1,-2]]:
if(S:=(x+X,y+Y))in m:q+=[(*S,m-{S})]
Python 3, 166 bytes
def f(g,s=[0]):w=len(g[0])+2;k='XX'.join(g)+w*'XXX';*p,x=s;return{*s,'.'}>{*p,k[x]}and any(f(g,s+[x+a])|f(g,s+[x-a])for a in(w+2,w-2,w-~w,w+w-1))|len(s)//k.count('.')
Brute force all paths.
Adaptation from my answer to Find the shortest route on an ASCII road.
R, 243 213 bytes
Edit: -30 bytes by merciless code-trimming...
function(p,m,n=1e4,f=function(p,m,x){m[t(p)]=1
d=p+matrix(c(q<-c(1,2,2,1,1,-2,2,-1),-q),2)
`if`(w<-sum(v<-!m[d<-t(d[,!colSums(d<1|d>dim(m))])]),f(d[which(v)[sample(w,1)],],m),!sum(!m))})mean(sapply(1:n,f,p=p,m=m))
This is a stochastic algorithm.
The complete search (163 bytes) of all tours on a 6x6 board without holes can require up to approx 36 (positions) x 2^36 (combinations of already-visited squares or holes), which does not run in a <1 minute time-frame, and even memoising already-tried partial-tours isn't feasible (since unfortunately R vectors are limited to a length of 2^31).
So instead we repeatedly attempt random tours. 1e5 random tours is sufficient to sample the entire, no-hole, 6x6 board and repeatedly find successful tours within 1 minute (although unfortunately not on TIO).
At the cost of 1 wasted byte, the implementation here reports the fraction of successful to unsuccessful attempted tours.
Perl 5, 305 bytes
sub f{my($b,$x,$y)=(@_,1,1);$b=~/.+/;$lx=length$&;$P=sub{($X,$Y)=@_;$X<1||$X>$lx||$Y<1||$Y>$b=~y/\n//?0:($Y-1)*($lx+1)+$X};(!(substr($b,&$P($x,$y)-1,1)=~s,\.,x,)or$b!~/\./)||(any{f($b,@$_)}grep{substr($b,&$P(@$_)-1,1)eq'.'}map[$x+$$_[0],$y+$$_[1]],[2,-1],[2,1],[1,-2],[1,2],[-2,1],[-2,-1],[-1,2],[-1,-2])}
Sledgehammer, 29 bytes
⠑⡘⣡⡪⡾⢸⢹⣎⡷⡬⢵⣅⢞⣽⣤⡥⠃⠏⢂⢜⠩⡬⢸⠜⡻⣠⡪⢄⡯
That's not very readable, so here's the corresponding Mathematica code:
AnyTrue[Thread@
FindHamiltonianPath[
Subgraph[KnightTourGraph[#2, #3],
o = First /@ StringPosition[#, "."]], 1, o],
ListQ@# && Length@# > 0 &] &
This removes unneeded vertices from the knight's graph (first obtained via KnightTourGraph), calls FindHamiltonianPath with all possible end vertices (it either takes nothing and finds any Hamiltonian path, or it takes both a start and an end vertex) and checks whether any paths were actually found.
Example input (for the fourth test case)
{"..X..X...X......X...X..XX", 5, 5}
The first line is a flat version of the grid (obtained by reading it in row-major order).
I have first thought that this doesn't work, but then I investigated and finally found what seems to be a bug in the interpreter: the hammer.wls main script doesn't call postprocess, and (when decoding) it ends up evaluating the code with all slots (#, #2, #3) replaced by variables s1, s2, s3 :(. Fortunately, the interactive app, while even less convenient, doesn't have this bug.