[Question]
  [
## Background
A **snake** is a path over the cells of a square grid, such that it doesn't touch itself on a side of a unit square. Touching at a corner is allowed.
An example snake:
```
##.#.
.#.##
##..#
#.###
###..
```
Some example non-snakes:
```
###.#
#.#.#
#####
.#...
.####
###
.#.
##
##
```
## Challenge
Given an empty grid with the two endpoints of a snake marked on it, find the longest possible snake that fits on the grid. If there are multiple answers having the same length, you may choose to output one or all of them.
The input can be given as a character matrix (or equivalent) with two endpoints marked on it, or the dimensions (width, height) and the coordinates of the endpoints. You may choose to output the grid containing the snake or a list of coordinates of cells occupied by the snake (or equivalent).
Standard [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") rules apply. The shortest code in bytes wins.
## Example I/O
Each I/O example is given as a character matrix, `#` being the part of the snake.
```
Input:
..#...#...
Output:
..#####...
Input: (corner case)
......
......
..##..
......
......
......
Output: same as input (no way to get longer without violating no-touch condition)
Input:
..#.#
.....
.....
.....
Output:
###.#
#...#
#...#
#####
Input:
#....
.....
.....
.....
....#
Output:
#####
....#
#####
#....
#####
```
  
[Answer]
# [Python 3.8 (pre-release)](https://docs.python.org/3.8/), ~~207~~ ~~194~~ 181 bytes
*-7 bytes thanks to @ovs*
### Input
The width \$ w \$, the height \$ h \$, the starting point \$ s \$, and the ending point \$ e \$. \$ s \$ and \$ e \$ are complex numbers which represent the coordinates of the endpoints. 
### Output
A list of points, in the form of complex numbers.
---
```
C={1,-1,1j,-1j}
def f(w,h,s,e):P=[[s]];exec("P=[j+[t+(t==e==(A:=j+[t]))]for j in P for k in C if w>(t:=j[-1]+k).real>-1<t.imag<h>0<all({t+l}-{*j}for l in{0}|C-{-k})];"*w*h);return A
```
[Try it online!](https://tio.run/##VZBNb8IwDIbv/RUWOzSmadXypQkIEuLAlXuXQ7WlNKELVQnrpq6/vUs6GJoUxfaj1/abVF@mOOvpc1X3/Y61CQ0Tmih7q857EznkpKEFvVCBywNL0wvnK/EpXsnIVipITUAMY4Ixsl0yV3NEnp9rUCA1HMClJ5fuQObQbIixsjRMeHDCqBZZuQmTtYnke3ZcF5t4nZUlaU1QdmE7Vp3rLm13G3ffu7ANTx3y1WjcjAtc1cJcaw3bvilkKSBZetBQKChcKAhgID6ykkhdXQ1B9DzYW5amfuQPnqTzVGf6KEiBHP4c/6IGufeQuS@4D0a7Bvap1IbIwT/yW@GeYCcx8J98D6raUf9F@5E6S038W5T4mLtHCMBJsE8oJDEFEgcThUNcKPQWFOwhkxucBFMLZxTm/5QzC@d3GA9w5uAP "Python 3.8 (pre-release) – Try It Online")
## Explanation
We use a breadth-first search to search for all possible snakes, starting at \$ s \$, making sure that the next tile is not adjacent to any previous tile, and that we do not go past the boundary. After each iteration, we check for all paths whose last element is \$ e \$, meaning that we have found a complete path from \$ s \$ to \$ e \$. Instead of storing all complete paths and returning the one with maximum length, we can simply return the last path found, since breadth-first search already searches for paths by length.
[Answer]
# [R](https://www.r-project.org/), ~~275~~ ~~272~~ ~~251~~ ~~229~~ ~~206~~ 197 bytes
```
f=function(p,m){a=p+cbind(-1:0,1:0,0:-1,0:1)
v=m[a<-t(a[,!colSums(!a|a>dim(m))])]
t=sum(!!v)
m[t(p)]=2
`if`(t<3&any(v==1),m,if(t<2)(s<-lapply(split(a,seq(v))[!v],f,m))[[which.max(sapply(s,sum))]])}
```
[Try it online!](https://tio.run/##vZLNTsMwDMfveQoqJGSLFDULXKaFGy/Ax6mqWNa1LKJJQ5N2m4BnL0EbEjsAlQooShwllv3z3276qjYPhfP3zsjHQvSlKFuTe1UbsFTjsxT2NF8os4SYTRP6vpNpzMLBkHRCp3IWe5ApjfK6umm1g0i@yMul0qARM8yIF67VEEUdEp16sJiJCZmrcg5@xk@k2UInBEOqqSrD0wTBzeJKWlttwdlKhejUFU/QIaZRl9EyYGGarlcqX51puQG396UhT0iZ4Wt/fORDTW5KnJeN19I3aiN2BnIgnCb7RZJvrwGLmFCYuKCLbVOvxe313RXuotraiRxY8CEHGsLHL/2UHMkXKAnlv4cyGYnygyp8MMr5aFUGNIgPROGjUDhlwxqU/PmsHIwt@x@U/g0 "R – Try It Online")
*Edits 1-4: -69 bytes by using increasingly-arcane golfing obfuscations*
*Edit 5: -9 more bytes by removing useless explicit return of NULL for 'touching' cases, and instead just falling-off the end of the function*
Recursive function:
* find adjacent squares
* count touching squares
* mark position (differently to finish point)
* if touching < 3 and we're touching the finish: return the matrix
* else if touching > 1 (it's either a loop or an illegal position): return NULL
* otherwise (there should always be at least one adjacent empty square left)
	+ call self recursively with each adjacent empty square
	to get snakes from this position
	+ return the longest snake
Code before golfing:
```
longest_snake=function(pos,matrix){
    # find adjacent squares
    d=dim(matrix)
    adjacent_squares=lapply(list(-1:0,1:0,0:-1,0:1),function(p){n=pos+p;if(all(n>0 & n<=d)){n}})
    adjacent_squares=do.call(rbind,adjacent_squares)
    # count touching squares
    adjacent_vals=matrix[adjacent_squares]
    touching=sum(!!adjacent_vals)
    # mark current position (differently to end, which is 1)
    matrix[pos]=2
    # if touching<3 & pos is touching finish => return matrix
    if((touching<3)&&any(adjacent_vals==1)){ return( matrix ) }
    # else if touching>1 then its either an illegal position or a loop  
    else if(touching>1){ return( NULL ) }
    else { # there should always be at least one adjacent empty square
        # now consider each of the adjacent empty squares
        new_pos=lapply(which(adjacent_vals==0),function(i) adjacent_squares[i,,drop=F])
        # get the longest snake from each of them
        snakes_from_here=lapply(new_pos,longest_snake,matrix)
        # and return the longest of these
        longest=which.max(sapply(snakes_from_here,sum))
        return(snakes_from_here[[longest]])
    }
}
```
[Answer]
# [R](https://www.r-project.org/), ~~178~~ ~~169~~ ~~164~~ 161 bytes
```
f=function(s,e,w,h,l=length,`/`=c,`*`=`%in%`,k=s[1]-1/-1i/-1/1i)if(!any(s[-2]*k))`if`(e*k,s/e,{for(j in k[Re(k)*1:w&Im(k)*1:h])if(l(F)<l(n<-f(j/s,e,w,h)))F=n;F})
```
[Try it online!](https://tio.run/##ZY5Ba8JAEIXv/orpwTITJ6SrpoXWvQq99hoCa@1usyZZyybWtuJvT1cjEhB2h@F97w3Pd52RZufWrd06bFjznguuZKXdZ1uwSpRcs4qUVGPrxopL2WQij0USCxt@IixZg3cr94tNFk/zqCRS1ijUUclNovlgth43YB2U2ZvGkiLxvL9/rfutyE/xCpe0qNAtYoOb5FKCiJbSvSyP1H3bZreq7J@GRQyDsqAZ9gwFwQFGAB4kmKEctC9vXYv@tNYB16vW2x98CDR4zmq2frfuA0MjTwyhoifKg1Vc0zWNjqNrB5xNhGV4Ok8RLgkawOlkGuTZeT6GRzfBtJ8M8yETF5b2LL292Tvmp1z3Dw "R – Try It Online")
This works with complex numbers, similarly to @dingledooper's answer. Inputs are 1-indexed coordinates of start and end points, as well as width and height of the grid. Output is a vector of points which form the snake.
### Explanation
```
f = function(s, e, w, h) # start, end, width, height
{ # Select points to try at next iteration as neighbors of the snake head cell:
  k = s[1] + c(-1,1i,1,-1i) 
  # To avoid touches, only proceed if none of k points are already in snake:
  if(!any(s[-2] %in% k)) #s[2] is an exception - this is where we came from
    `if`(e %in% k, # If the neighbors include the endpoint, then...
      c(s,e)       # The loop is closed, add the endpoint to snake and return
      {# Loop through k, filtered so that all points fit in 1:w by 1:h grid:
        for(j in k[Re(k) %in% 1:w & Im(k) %in% 1:h])
        { # Prepend j to snake, and construct it further by recursive call:
          n <- f(c(j, s), e, w, h)
          if(length(F) < length(n))
            F = n # Select the longest snake that we encountered        
        }
        F # Return the longest snake
      }
    )
}  
```
[Answer]
# [Python 3.8 (pre-release)](https://docs.python.org/3.8/), 214 bytes
Takes a 1D boolean array `g` where the endpoints are marked `True`, and returns a 1D boolean array where snake tiles are marked `True`.
[Try it online!](https://tio.run/##dVHBcoIwED3DV@zItCSCiPbSYYg/ghyoBEgLgQlo4OtpEupoHc1ld9/mvX3ZdNNQtfzjsxNzQY5znTVfeQbSr/wyarIRoZr1A2qyDl18kfGSIrmuMMZFK2AExmEB93G8NFgBWV0jdInInxaLwpiwWHUh4zkqE5Zq7uHA3ncYI4YJCaEViL3JQ6ivwAWxjWp5GorlZncFPQ3qpjTBU0GrEbIHbYfd7Cwe/R86kf7c4DmnBQxUPaQULMeRbUkgUFNu6iRMsW1Vd4gqHRC0P9eDQgskfah8SE5ACLiOa6adzLRWmkJHVWpu@oJsJk1pMqb3KncrlNgg0w2psBZ7IcW2W5kmakP/9B52sPCHs@DgHrkbfLeMI/caFUd916KfjN60Vlq07im4wRN3T@xh2@4E4wOyLbPdxLasVRA4gbPyl1SdF6ltKXN4/gU "Python 3.8 (pre-release) – Try It Online")
```
lambda w,h,g:max((list(map(v,range(w*h)))for x in range(2<<(w*h))if all((v:=lambda i:0<=i<w*h and(g[i]or x>>i&1))(i)==0 or(i%w>0 and v(i-1))+(i%w<w-1 and v(i+1))+v(i-w)+v(i+w)+g[i]==2 for i in range(w*h))),key=sum)
```
---
### Explanation:
```
def f(w, h, g):
    return max(
        (
            # Brute force all possible grid configurations by counting in binary.
            # For each iteration, let the ith binary digit of x signify
            # whether the ith tile is considered part of the snake.
            [v(i) for i in range(w*h)] # <- Return a boolean array.
            for x in range(2<<(w*h))
            # Check if there is a valid snake path.
            if all(
                # The ith tile is part of the path if it's a given endpoint (g[i])
                # or the ith binary digit of x is 1 (x>>i&1).
                ( v:=lambda i:0<=i<w*h and (g[i] or x>>i&1) )(i) == 0
                # For a grid to have a valid snake path,
                # every tile must either not be part of the snake (v(i) == 0)...
                or
                # ...or the tile must have exactly 2 neighbors in the snake path.
                # (If the tile is an endpoint (g[i]), count itself as a neighbor.)
                (i%w>0 and v(i-1)) + (i%w<w-1 and v(i+1)) + v(i-w) + v(i+w) + g[i]
                == 2
                # Repeat this check for every tile.
                for i in range(w*h)
            )
        ),
        # Use max() to find the grid configuration with the most snake tiles;
        # that is, the most times that v(i) == True.
        key=sum
    )
```
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 199 bytes
```
s=>(o=g=(t,k,h=c=>t.replace(/2/,c),a=h(0),b=h(1),m=2*~s[0].length)=>a==b?[...a].some((_,i)=>_&1&~1<<B[i]>>a[i-m]>>a[i+m]>>a[i-2]>>a[i+2]|k<o)||(o=k,r=a):g(a,k)|g(b,-~k))(B=JSON.stringify(s))&&eval(r)
```
[Try it online!](https://tio.run/##TY69TsMwFEb3PkWn6F64cRuPKNdIHTowwMBoWZUTjGPy4yqOKiFFefUQRAemc74zfV/2ZlM9huuUD/HDrWdeEyuI7BkmaqnhmtUkRnftbO3gIA9UI1lu4IhUbSiQepYPS9JHIzo3@KlBVpa5etZCCGtEir0DuFDY@iUrsqUoy5MORimrQ97/8fHOXN63NHNbRpzn7UtLI1t88mCpxdlDRfnSIsKJX97fXkWaxjD48PkNCTHL3M12MOJaxyHFzokuejiD3u33uiBJhaFflZvK/7oziOsP "JavaScript (Node.js) – Try It Online")
Seems this way is not that good one
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 76 bytes
```
ＷＳ⊞υι≔⪫υ¶θ≔⟦ω⟧ηＦηＦＥ⁴⁺ικ«Ｊ⁰¦⁰Ｐθ…θ⌕θ@Ｆκ✳⊗λ#¿∧›ＫＫ#‹№ＫＶ#²¿⁼ＫＫ@«#≔ＫＡζ»⊞ηκ»ＵＭＫＡ§ζκ
```
[Try it online!](https://tio.run/##TZBPT8MwDMXP66ewwsWRQjUhbrus6gBtYqgSiAtwKG22RsuSrkn4s2mfvThlYuTiyH7@@elVTdlVttR9/9koLQHnpg3@0XfKrJFzKIJrMAhQfJJkzqm1wYVVJrbYq2FcwO48eWHsTUBDjZXtABsOQ12WLV4LKHRwqARsOHEPyWgRtu2TxbGAMW2MlkF71dJdjxE5KoZv/l1pmTe2xZ2AW2XqWNmUEYM0A35DLgftTHWy8soanNnwrmWNmpNBdsGiVq0AM9q/62TpZYeFlBs8jQXcS@cwt4EwcfBszYMM29KYs@Qq@o6Um10otTsDohs4nEwM1@AUSJRkWkfVnrpHkNrJ30ybGMQkOSaUTm63dKr@L8/83NTyC/dDXpO@T6cpvSRN/8o0TfrLD/0D "Charcoal – Try It Online") Link is to verbose version of code. Takes input as two `@` endpoints in a field of ASCII characters greater than `#` (e.g. `.`). Explanation:
```
ＷＳ⊞υι≔⪫υ¶θ
```
Input the field.
```
≔⟦ω⟧ηＦη
```
Start a breadth-first search with an empty path, and for each path...
```
ＦＥ⁴⁺ικ«
```
... search over the four possible paths formed by concatenating each direction.
```
Ｊ⁰¦⁰Ｐθ…θ⌕θ@
```
Print the field and move to the position of the first endpoint.
```
Ｆκ✳⊗λ#
```
Print the path.
```
¿∧›ＫＫ#‹№ＫＶ#²
```
Test whether the current position is legal (not off the edge, doubled back, or touching itself).
```
¿⁼ＫＫ@«
```
If we reached the other endpoint,
```
#≔ＫＡζ
```
then overwrite it with a `#` and save the canvas.
```
»⊞ηκ
```
Otherwise add this path to the search candidates.
```
»ＵＭＫＡ§ζκ
```
Restore the canvas from the saved last (i.e. longest) path that reached the other endpoint.
]